partial view is not display back anything error 404 is generated - javascript

I am trying to fix this problem I got an error 404 on the partial view path url: localhost:49259/Panier/TableContent. This TableContent is under the Panier folder.
I can't figure out what is wrong with the URL.
Does the TableContent should be under this folder ViewModels instead since it is using this model
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel?
Thanks
TableContent.cshtml (partial view) from Panier
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Table Content";
}
<a href="#" class="TableContent">
<table>
<tr>
<th>
Produit
</th>
<th>
Prix (unitaire)
</th>
<th>
Quantite
</th>
<th></th>
</tr>
#foreach (var item in Model.CartItems)
{
<tr id="row-#item.ProduitId">
<td>
#Html.ActionLink(item.Produit.Description, "Details", "Produit", new { id =
item.ProduitId }, null)
</td>
<td>
#item.Produit.Prix
</td>
<td id="item-count-#item.PanierId">
#item.Quantite
</td>
<td>
<a href="#" class="RemoveLink" data-id="#item.PanierId"> Enlever du panier
</a>
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total">
#Model.CartTotal
</td>
</tr>
</table>
</a>
Index.cshtml from Panier
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$('.RemoveLink').click(function () {
$.ajax({
url: '/Panier/RemoveFromCart',
data: { id: $(this).data('id') },
type: 'POST',
cache: false,
success: function (result) {
$('#row-' + result.DeleteId).remove();
$('#row-' + result.DeleteId).fadeOut('slow');
$('#cart-status').text('Cart (' + result.CartCount + ')');
$('#update-message').text(result.Message);
$('#cart-total').text(result.CartTotal);
$.get("/Panier/TableContent").done(function (data) { <==error 404
$("#TableContent").html(data); });
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("Status: " + textStatus); alert("Error: " + errorThrown);
}
});
return false;
});
});
</script>
<h3>
<em>Details</em> du panier:
</h3>
<p class="button">
#Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")
</p>
<div id="update-message">
</div>
<div id="table-content">
#Html.Partial("TableContent") <=== partial view call
</div>
PanierController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Tp1WebStore3.Models;
using Tp1WebStore3.ViewModels;
namespace Tp1WebStore3.Controllers
{
public class PanierController : Controller
{
//
// GET: /Panier/
Tp1WebStoreDBEntities dbProduit = new Tp1WebStoreDBEntities();
//
// GET: /ShoppingCart/
public ActionResult Index()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
// Set up our ViewModel
var viewModel = new ShoppingCartViewModel
{
CartItems = cart.GetCartItems(),
CartTotal = cart.GetTotal()
};
// Return the view
return View(viewModel);
}
//
// GET: /Store/AddToCart/5
public ActionResult AddToCart(int id)
{
// Retrieve the album from the database
var addedProduit = dbProduit.Produits
.Single(produit => produit.ProduitId == id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(addedProduit);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
//
// AJAX: /ShoppingCart/RemoveFromCart/5
[HttpPost]
public ActionResult RemoveFromCart(int id)
{
// Remove the item from the cart
var cart = ShoppingCart.GetCart(this.HttpContext);
// Get the name of the album to display confirmation
string produitDescription = dbProduit.Paniers
.Single(item => item.PanierId == id).Produit.Description;
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message = Server.HtmlEncode(produitDescription) +
" has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return Json(results);
/* return View("CartSummary"); */
}
//
// GET: /ShoppingCart/CartSummary
[ChildActionOnly]
public ActionResult CartSummary()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
ViewData["CartCount"] = cart.GetCount();
return PartialView("CartSummary");
}
}
}

You'll want to keep your partial view inside the view folder (not view models)... the specific subdirectory is up to you but I believe it will default to looking in shared.
I'd suggest specifying more of the URL when you call the partial view and see if that fixes your issue...
For Example:
Html.Partial("~/Views/Shared/TableContent.cshtml")
More Info Here:
Render partial from different folder (not shared)
Ok I realize I misunderstood the question and the 404 was being generated by the script call not the #Html.Partial at the bottom of the file.
I'm going by this snippet from the comments...
$.get("~/Views/Shared/TableContent").done(function (data) { $("#TableContent").html(data); });
I see two issues here... First is that you are going to want to resolve your path differently as the "~" operator isn't going to help in javascript. You can use #url.Action("TableContent") in this case to get the actual url on the server and pass it in to your get statement.
The second issue is that I believe TableContent is just a view without a corresponding action. This is fine for rendering inline with a Html.Partial, however the server isn't going to be able to render it outside of that context. You'll want to add a corresponding action and call that instead from your ajax.

Your controller, Panier, doesn't seem to have a method called TableContent which should return the partial view TableContent.cshtml.
Also, when you refer the urls, try to use the Url.Action in the ajax / get calls:
url: '/Panier/RemoveFromCart',
Should be:
url: '#Url.Action("RemoveFromCart","Panier")',

Another way of solving this is to create an action TableContent in the Panier Controller which would call the partial view TableContent. The TableContent.cshtml should be in the same directory as Index (ie /Views/Panier)
public PartialViewResult TableContent()
{
return PartialView("TableContent");
}
You'll then need to replace a line in the ajax call
$.get("/Panier/TableContent")
becomes
$.get('#Url.Action("TableContent", "Panier")')

Related

Ajax paging is duplicating _layout page while using pagination to replace page content

I am using x.PagedList to use pagination in my ASP.NET MVC page. The only problem I have with the plugin is , it used a page refresh when I navigate between pages.
To avoid that I am using jQuery calls to replace page contents as explained in this article.
My View and javascript looks like this.
<div id="circuitsContent">
<table class="table">
<tr>
--Header
</tr>
#foreach (var item in Model)
{
<tr>
--Loop through and create content
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
#Html.ActionLink("Details", "Details", new { id = item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
}
</table>
</div>
<div id="circuitContentPager">
#Html.PagedListPager((IPagedList)Model, page => Url.Action("Circuits", new { page }))
</div>
#section scripts
{
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$(document).on("click", "#circuitContentPager a[href]", function () {
$.ajax({
url: $(this).attr("href"),
type: 'GET',
cache: false,
success: function (result) {
$('#circuitsContent').html(result);
}
});
return false;
});
});
</script>
And this is my controller code:
public ActionResult Circuits(int? page)
{
var pageNumber = page ?? 1;
var circuits = _repo.GetAllCircuits().OrderBy(circ=>circ.ID).ToList();
var pagedCircuits = circuits.ToPagedList(pageNumber, 25);
return View(pagedCircuits);
}
What am I missing here?
Your ajax call returns the html from Circuits() method which is the same view you have used to render the page initially, which includes all the initial html, but you only replacing part of of the existing page, so elements such as the paging buttons generated by the #Html.PagedListPager() method are going to be repeated. Your also generating invalid html because of duplicate id attributes (you will have multiple <div id="circuitsContent"> elements
There are 2 ways you could solve this.
Create a separate controller method that returns a partial view of just the <table> and call that method, however you would need to extract the value of the page number for the href attribute of you pager buttons to pass that as well.
Using your current Circuits() method, test if the request is ajax, and if so, return a partial view of just the <table>.
public ActionResult Circuits(int? page)
{
var pageNumber = page ?? 1;
var circuits = _repo.GetAllCircuits().OrderBy(circ=>circ.ID);
var pagedCircuits = circuits.ToPagedList(pageNumber, 25);
if (Request.IsAjaxRequest)
{
return PartialView("_Circuits", pagedCircuits);
}
return View(pagedCircuits);
}
Note: Do not use .ToList() in your query. That is defeating the whole purpose of using server side paging because .ToList() immediately downloads all the records fro the database.
Where _Circuits.cshtml would be
#model IEnumerable<yourModel>
<table class="table">
<thead>
<tr>
// <th> elements
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
.... // Loop through and create content
</tr>
}
</tbody>
</table>
Note that your header elements should be in a <thead> element and the records in a <tbody> element.

Update HTML page after jquery.click

I have an onclick function which basically just returns sorted data like following:
$(document).ready(function () {
$(".feedbackClick").click(function () {
$.post("/Analyze/GetSortedByFeedback")
.done(function (data) {
var sellers = $('<table />').append(data).find('#tableSellers').html();
$('#tableSellers').html(sellers);
});
});
});
});
And this is how the table looks like that I'm trying to update after the jquery post:
<table id="tableSellers" class="table table-striped jambo_table bulk_action">
<thead>
<tr class="headings">
<th class="column-title"><h4><i class="fa fa-user" style="text-align:center"></i> <span>Username</span></h4> </th>
<th class="column-title"> <h4><span class="glyphicon glyphicon-tasks salesClick" aria-hidden="true"></span></h4></th>
<th class="column-title"><h4><i class="fa fa-star feedbackClick"></i></h4></th>
</tr>
</thead>
<tbody>
#foreach (var item in ViewBag.rezultati)
{
<tr>
<td>#item.StoreName</td>
<td>
<b>
#item.SaleNumber
</b>
</td>
<td><b>#item.Feedback</b></td>
</tr>
}
</tbody>
</table>
The click would basically just fetch the results and update the table in HTMl...
Can someone help me out?
Edit:
This current method doesn't works... I trigger the event but nothing happens... The code in the Action is called properly, but the results aren't displayed...
Edit 2:
This is the content of the data object after .done:
System.Collections.Generic.List`1[WebApplication2.Controllers.ResultItem]
Edit 3:
This is the action:
public List<ResultItem> GetSortedByFeedback()
{
return lista.OrderByDescending(x => x.Feedback).ToList();
}
Edit4 this is the data after the Alexandru's post:
Array[100]
Now I can do:
data[0].Feedback
And this outputs in console:
61259
Please use this:
public JsonResult GetSortedByFeedback()
{
var list=lista.OrderByDescending(x => x.Feedback).ToList();
return Json(list);
}
If your method is GET please use this:
public JsonResult GetSortedByFeedback()
{
var list=lista.OrderByDescending(x => x.Feedback).ToList();
return Json(list,JsonRequestBehavior.AllowGet);
}
Then please use this:
.done(function (data) {
$('#tableSellers tbody').empty();
$.each(data,function(i,item){
var tr='<tr><td>'+item.StoreName+'</td><td><b>'+item.SaleNumber+'</b></td><td><b>'+item.Feedback+'</b></td></tr>';
$('#tableSellers tbody').append(tr);//append the row
});
});
What you are trying to do is actually appending a JSON data to a HTML element which is of course will not work as expected.
Consider using a template engine like jQuery Templates. You will be able to compile a HTML template and use it to render your data whenever you need. For example:
var markup = "<li><b>${Name}</b> (${ReleaseYear})</li>";
// Compile the markup as a named template
$.template( "movieTemplate", markup );
$.ajax({
dataType: "jsonp",
url: moviesServiceUrl,
jsonp: "$callback",
success: showMovies
});
// Within the callback, use .tmpl() to render the data.
function showMovies( data ) {
// Render the template with the "movies" data and insert
// the rendered HTML under the 'movieList' element
$.tmpl( "movieTemplate", data )
.appendTo( "#movieList" );
}
TRy something like this:
$(document).ready(function () {
$("body").on("click",".feedbackClick",function() {//delegate the click event
$.get("/Analyze/GetSortedByFeedback",function(data) {
var sellers = $(data).find('#tableSellers').html();//find the table and take the html
$('#tableSellers').html(sellers);//append the html
});
});
});
Note: you need to return html (in your case) from the ajaxed page
from #Alexandru partial response you can do the following
public JsonResult GetSortedByFeedback()
{
var list=lista.OrderByDescending(x => x.Feedback).ToList();
return Json(list,JsonRequestBehavior.AllowGet);
}
js:
$(document).ready(function () {
$("body").on("click",".feedbackClick",function() {//delegate the click event
$.get("/Analyze/GetSortedByFeedback",function(data) {
$('#tableSellers tbody').empty();//empty the table body first
$.each(data,function(i,item){//loop each item from the json
$('#tableSellers tbody').append('<tr><td>'+item.StoreName+'</td><td><b>'+item.SaleNumber+'</b></td><td><b>'+item.Feedback+'</b></td></tr>');//build and append the html
});
});
});
});

Error using partial view, javascript and viewbag foreach

I'm trying to load a partial view using JavaScript, in turn the partial view will have a View Bag", to loop through.
All is working well, until I try to render the partial view I get an "object Object" error, if I remove the View bag loop the partial view loads
Controller
[HttpPost]
public ActionResult ServiceDetails(int id )
{
int count = 0;
var m = from c in db.ServiceCategoryFields
where c.serviceTypeID == id
select c;
ViewBag.count = count;
ViewBag.m = m.ToList();
return PartialView(m.ToList());
}
Partial View
<table style ="width:100% ">
<tr>
#foreach (var image in (List<String>)ViewBag.m)
{
<td>
#image
</td>
}
</tr>
JS File
type: "POST",
success: function (data) {
display.html('');
display.html(data);
},
error: function (reponse) {
alert("JS Error : " + reponse.toString());
}
Quick Solution
Based on your controller code below
[HttpPost]
public ActionResult ServiceDetails(int id )
{
int count = 0;
var m = from c in db.ServiceCategoryFields
where c.serviceTypeID == id
select c;
ViewBag.count = count;
ViewBag.m = m.ToList();
return PartialView(m.ToList());
}
ViewBag.m would be an instance of List<ServiceCategoryField>, but you convert it to List<string> in the partial view
#foreach (var image in (List<String>)ViewBag.m)
so you got the error. Assuming that PropertyName is the property of ServiceCategoryField with the value that you want to display inside <td> tags, you need to convert ViewBag.m to List<ServiceCategoryField> in the partial view as below
<table style ="width:100% ">
<tr>
#foreach (var image in (List<ServiceCategoryField>)ViewBag.m)
{
<td>
#image.PropertyName
</td>
}
</tr>
Alternative Solution
The previous solution requires converting ViewBag.m and it could produce runtime errors if you convert ViewBag.m to the wrong type. You can avoid the conversion in the partial view by using this alternative solution.
The first thing to do is creating a model class that will be used by the partial view, let's say the class name is ServiceDetailsViewModel and it has Count and Images property
public class ServiceDetailsViewModel
{
public int Count { get; set; }
public List<string> Images { get; set; }
}
Create an instance of ServiceDetailsViewModel, assign the properties, and pass model to the partial view in the controller. I assume PropertyName is a string and c.PropertyName is where the image in the partial view comes from
[HttpPost]
public ActionResult ServiceDetails(int id )
{
int count = 0;
var m = from c in db.ServiceCategoryFields
where c.serviceTypeID == id
select c.PropertyName;
ServiceDetailsViewModel model = new ServiceDetailsViewModel();
model.Count = count;
model.Images = m.ToList();
return PartialView(model);
}
Set ServiceDetailsViewModel as the model by using the below syntax at the top of your partial view code
#model ServiceDetailsViewModel
and loop through Model.Images as below
<table style ="width:100% ">
<tr>
#foreach (var image in Model.Images)
{
<td>
#image
</td>
}
</tr>

How to Post multiple rows with AngularJS

I am trying to submit a form with multiple table rows. I have found examples online and have managed to send the table data to the AngularJS controller but I cannot figure out how to send that data to the apiController.
The form is a Purchase Order that has a table with the Purchase Order Details. I have chained the submit button with the both the Purchase Order and Purchase Order Detail submit functions.
<table class="table" style="">
<tbody>
<tr class="pointer no_selection" ng-repeat="newJobItem in rows">
<td style="width:50px"><input style="width:20px" type="checkbox" class="form-control"></td>
<td style="width:200px">{{newJobItem.JobItemName}}</td>
<td style="width:480px">{{newJobItem.JobItemDescription}}</td>
<td style="width:100px">{{newJobItem.JobItemMatSize}}</td>
<td style="width:150px">{{newJobItem.JobItemQuantity}}</td>
<td style="width:50px">{{newJobItem.JobItemUOM}}</td>
<td style="width:150px">${{newJobItem.JobItemPrice | number : fractionSize}}</td>
<td style="width:20px"><input type="button" value="X" class="btn btn-primary btn-sm" ng-click="removeRow(newJobItem.JobItemName)" /></td>
</tr>
</tbody>
</table>
<input style="margin-right:30px" id="btn-width" type="button" class="btn btn-default" ng-click="submitPurchaseOrder();submitPurchaseOrderDetail()" value="Submit"/>
Controller
//Post Purchase Order
$scope.PODate = new Date(); //Todays Date
$scope.POId = Math.floor(Math.random() * 1000000001) //PurchaseOrder Id Generator
$scope.submitPurchaseOrder = function () {;
var data = {
JobId: $scope.job.JobId,
POId : $scope.POId,
PONumber: $scope.currentItem.PONumber,
PODate: $scope.PODate,
POAmount: $scope.currentItem.POAmount,
POLastPrintDate: $scope.currentItem.POLastPrintDate,
POEmail: $scope.POEmail,
POPrint: $scope.currentItem.POPrint,
POFaxNumber: $scope.POFaxNumber,
PONotes: $scope.currentItem.PONotes,
POCreatedBy: $scope.currentItem.POCreatedBy,
PODeliveryDate: $scope.currentItem.PODeliveryDate,
POShipVia: $scope.currentItem.POShipVia,
POShowPrices: $scope.currentItem.POShowPrices,
POCostCode: $scope.currentItem.POCostCode,
POApprovedNumber: $scope.currentItem.POApprovedNumber,
POBackorder: $scope.currentItem.POBackorder,
}
$http.post('/api/apiPurchaseOrder/PostNewPurchaseOrder', data).success(function (data, status, headers) {
console.log(data);
var tmpCurrentItem = angular.copy($scope.currentItem);
$scope.purchaseOrderArray.push(tmpCurrentItem)
angular.copy({}, $scope.currentItem);
//hide modal window
$scope.openNewPurchaseOrderModal.then(function (m) {
m.modal('hide');
});
});
};
//Post Purchase Order Detail
$scope.newJobItem = {};
$scope.submitPurchaseOrderDetail = function () {
var index = 0;
$scope.rows.forEach(function (newJobItem) {
console.log('rows #' + (index++) + ': ' + JSON.stringify(newJobItem));
});
var data = {
POId: $scope.POId,
PODItem: $scope.newJobItem.JobItemName,
PODDescription: $scope.newJobItem.JobItemDescription,
PODNotes: $scope.PODNotes,
PODUOM: $scope.newJobItem.JobItemUOM,
PODPrice: $scope.newJobItem.JobItemPrice,
PODQuantity: $scope.newJobItem.JobItemQuantity,
PODAmount: $scope.PODAmount,
PODMatSize: $scope.newJobItem.JobItemMatSize,
PODSection: $scope.PODSection,
PODMultiplier: $scope.PODMultiplier,
PODBackOrder: $scope.PODBackOrder
}
$http.post('/api/apiPurchaseOrderDetail/PostNewPurchaseOrderDetail', data).success(function (data, status, headers) {
console.log(data); window.top.location.reload();
});
};
Purchase Order Detail ApiController
// POST api/<controller>
public async Task<IHttpActionResult> PostnewPurchaseOrderDetail([FromBody]PurchaseOrderDetail newPurchaseOrderDetail)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
using (var context = new ApplicationDbContext())
{
context.PurchaseOrderDetails.Add(newPurchaseOrderDetail);
await context.SaveChangesAsync();
return CreatedAtRoute("PurchaseOrderDetailApi", new { newPurchaseOrderDetail.PODId }, newPurchaseOrderDetail);
}
}
Update
Changed as suggested
// POST api/<controller>
public HttpResponseMessage PostNewPurchaseOrderDetail(int id, PurchaseOrderDetail newPurchaseOrderDetail)
{
ApplicationDbContext db = new ApplicationDbContext();
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
if (id != newPurchaseOrderDetail.PODId)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
db.Entry(newPurchaseOrderDetail).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
You are executing two functions, each making an asyncronous request:
ng-click="submitPurchaseOrder();submitPurchaseOrderDetail()"
This doesn't feel right - both requests are sent in parallel and none is waiting for the other. Do you really mean it?
I would either package and send all data in a single request (also better experience for the user), then let the server deal with un-packaging. Or, if one request needs to wait for another, chain the Promises returned by $http:
$http.post(...)
.then(function(){
return $http.post(...);
})
.success(...)
.fail(...);
or use $q.all(promises) instead.
EDIT.
Also a cleaner and more scalable approach is to use dedicated Angular Service to post your data, see e.g. example on Angular Homepage
I'm not sure about your approach, to me it would be better to join both requests, purchaseOrder and the detail into a single call, you can still separate the data as you may feel convenient.
calling both functions at the same time could have unexpected behaviors since both are running asynchronously you may find 'race conditions'.
try to send a single request and organize how you are going to post the information like
var data = {
JobId: $scope.job.JobId, //common data between the order and the detail
POId: $scope.POId,
Order:{
PONumber: $scope.currentItem.PONumber,
PODate: $scope.PODate,
POAmount: $scope.currentItem.POAmount,
POLastPrintDate: $scope.currentItem.POLastPrintDate,
POEmail: $scope.POEmail,
POPrint: $scope.currentItem.POPrint,
POFaxNumber: $scope.POFaxNumber,
PONotes: $scope.currentItem.PONotes,
POCreatedBy: $scope.currentItem.POCreatedBy,
PODeliveryDate: $scope.currentItem.PODeliveryDate,
POShipVia: $scope.currentItem.POShipVia,
POShowPrices: $scope.currentItem.POShowPrices,
POCostCode: $scope.currentItem.POCostCode,
POApprovedNumber: $scope.currentItem.POApprovedNumber,
POBackorder: $scope.currentItem.POBackorder,
},
Detail:{
PODItem: $scope.newJobItem.JobItemName,
PODDescription: $scope.newJobItem.JobItemDescription,
PODNotes: $scope.PODNotes,
PODUOM: $scope.newJobItem.JobItemUOM,
PODPrice: $scope.newJobItem.JobItemPrice,
PODQuantity: $scope.newJobItem.JobItemQuantity,
PODAmount: $scope.PODAmount,
PODMatSize: $scope.newJobItem.JobItemMatSize,
PODSection: $scope.PODSection,
PODMultiplier: $scope.PODMultiplier,
PODBackOrder: $scope.PODBackOrder
}
}
you'll need to map the purchase order and the detail to a single dto object in your api controller.
just as a sidenote, I'd recommend you to use a stronger unique identifier rather than using a random number.
I think the trouble is with you controller try using this and also can you please elaborate the trouble.Does your APIcontroller is never found by your controller ?
public class Oders : ApiController // in your controller class
{
public HttpResponseMessage Post(PurchaseOrderDetails newOrder)
{
//your code
}
}

Redirect action with parameters in JQuery

In my ASP.Net project I'm trying to redirect a page to other action after select a row table and click on a button. So I have this code:
JQuery:
function editItem(tableId, url) {
if ($("#" + tableId + " .selected").exists()) {
var thisRowId = $("#" + tableId + " .selected").attr("id");
window.location.replace(url, { operation: "edit", carId: thisRowId });
}
};
//more code
View (ManagementCar):
#model myProject.Model.Car.Car[]
<table class="table" id="tableCars">
<thead>
#*some code to header*#
</thead>
<tbody>
foreach (var item in Model)
{
<tr id="#(item.Id)" onclick="selectRow('tableCars', '#(item.Id)')">
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.OwnerName)
</td>
<td>
#(item.IsSold == true ? "Yes" : "No")
</td>
</tr>
}
</tbody>
</table>
<br />
<button id="btEdit" type="button" class="disable" onclick="editItem('tableCars','CarOperation')">Edit</button>
Controller:
[HttpGet]
public ActionResult CarOperation(string operation, int carId)
{
//some code...
return RedirectToAction("ManagementCar", "Backoffice");
}
But I have a Server Error after redirect saying carId parameter is null. I debug my jquery and that parameter isn't null. I tried also doing
$.get(url, { operation: "edit", carId: thisRowId });
instead
window.location.replace(url, { operation: "edit", carId: thisRowId });
but it don't redirect.
How can I solve this?
set it by giving it a new value like this.
window.location = window.location.replace(url, "shouldBeAstringNotAJsonObject");
The problem with using window.location is that the referrer is not passed on the request as this behaviour simply mimics a new request as if you had typed the URL into the address bar. If you intend to use website analytics, a reliable referrer will be quite important. I use jQuery to generate a dynamic link upon which I call click().
var url = '/my/url';
$('')[0].click();
Notice I click() the underlying element not the jQuery selected object, the reason being that a jQuery click only raises the event and the href is not navigated to whereas indexing to the element and clicking that will cause the same behaviour you would expect as if you had actually clicked a link on the page.
I have put together a jQuery.navigate plugin that neatly wraps this up and abstracts your site map away from your UI logic, which you might find useful. For example, using my plugin would mean you could remove your editItem function altogether and simply change your markup to something like this?
<tr id="#(item.Id)" onclick="$.navigate('to', 'edit', { id : '#(item.Id)' })">
Ok, I finally solved the problem with a new url routing config and the following code:
My RouteConfig:
routes.MapRoute(
name: "ManipulatingCar",
url: "{controller}/{action}/{operation}/{carId}"
);
My JQuery:
editItem = function (tableId, url) {
if ($("#" + tableId + " .selected").exists()) {
var thisRowId = $("#" + tableId + " .selected").attr("id");
var fullUrl = url + "/edit/" + thisRowId;
window.location = fullUrl;
}
};
Basically, controller action parameters must match with the configurations specified in RouteConfig.cs

Categories

Resources