Ajax Call fails because of number of arguments - ajax

Ajax Call to msgcall method:
PopAjaxPost('mesaj/popup/msgcall/' + i + '/' + $('input#mesajkategori').val(), mysarr, function (data) {
if (data.Durum == '1') {
$wrapper.html('Mesaj<div class="preview"><div class="block"><strong>Gönderen:</strong>'
+ data.Data.Mesaj.Gonderen + '<br /><p>Sayın <strong>' + data.Data.Mesaj.Alici + '</strong></p><p>'
+ data.Data.Mesaj.Mesaj + '</p></div>' + (data.Data.Mesaj.SecenekId > 1 && !giden ? ('<input type="submit" value="Cevapla" onclick="mesajcevapla('
+ data.Data.Mesaj.MesajId + ');return false;" style="margin-bottom: 8px;">') : '') + '</div>');
}
else {
}
});
Here is msgcall method with three arguments:
[HttpPost]
[AjaxException]
[UserFilter]
public ActionResult MsgCall(string id, string pid, MsgHire model)
{
....
}
It does not invoke the msgcall method with the supplied arguments. If I remove the + i + '/', it invokes the msgcall method. What am I doing wrong?
From Route.config:
routes.MapRoute("MesajPopup", "mesaj/popup/{action}/{id}",
new { controller = "Mesaj", action = "Liste", id = UrlParameter.Optional });
routes.MapRoute("Mesaj", "mesaj/{action}/{id}",
new { controller = "Mesaj", action = "Liste", id = UrlParameter.Optional });

There is no configuration for additional parameter named pid, so you should define a maproute for this parameter.
Add something like this line:
routes.MapRoute("Msg_Call", "mesaj/popup/{action}/{id}/{pid}",
new {
controller = "Mesaj",
action = "Liste",
id = UrlParameter.Optional,
pid = UrlParameter.Optional
});

Related

Trouble accessing the property of a class in Ajax

In index.cshtml I am using Ajax. In click event of .removelink to get changes from action controller as follows:
$(".RemoveLink").click(function () {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
if (recordToDelete != '' || recordToDelete != null) {
// Perform the ajax post
$.ajax({
//contentType: 'application/json',
//dataType: 'text',
type: 'post',
dataType: 'JSON',
url: '/ShoppingCart/RemoveFromCart/',
data: { id: recordToDelete },
success: function (data) {
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
}
else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
}
});
}
});
And in controller:
//AJAX: /ShoppingCart/RemoveFromCart/5
[HttpPost]
public IActionResult 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 albumName = _context.Carts
//.Single(item => item.RecordId == id).Album.Title;
Cart cartt = ShoppingCart.getCartForGetalbumName(id);
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message = HtmlEncoder.Default.Encode(cartt.Album.Title) +
" has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
//CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return Json(results);
}
However, it does not work. Additionally, the text of the tags does not change and fadeOut() does not work.
When I send a unit field (eg, a string or an integer) Jason reads it well.
However, when I send a class containing some properties (like the example above), its value in the data parameter is problematic.
Please modify your property to lowercase , try to use :
success: function (data)
{
if (data.itemCount == 0) {
$('#row-' + data.deleteId).fadeOut('slow');
}
else {
$('#item-count-' + data.deleteId).text(data.itemCount);
}
$('#cart-total').text(data.cartTotal);
$('#update-message').text(data.message);
$('#cart-status').text('Cart (' + data.cartCount + ')');
}
i add The following code to convert data to json in RemoveFromCart controller action:
var resulTtoJson = Newtonsoft.Json.JsonConvert.SerializeObject(results);
and return json type :
[HttpPost]
public IActionResult 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 albumName = _context.Carts
//.Single(item => item.RecordId == id).Album.Title;
Cart cartt = ShoppingCart.getCartForGetalbumName(id);
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message ="محصول"+ cartt.Album.Title +
"از سبد خریدتان حذف گردید.",
CartTotal = cart.GetTotal(),
//CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
var resulTtoJson = Newtonsoft.Json.JsonConvert.SerializeObject(results);
return Json(resulTtoJson);
also add the following code in view to convert data to javascript type:
var data =JSON.parse(dataa);
and use it:
$(".RemoveLink").click(function () {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
// alert(recordToDelete);
if (recordToDelete != '' || recordToDelete != null) {
// Perform the ajax post
$.post("/ShoppingCart/RemoveFromCart/", { id: recordToDelete},
function (dataa) {
// Successful requests get here
// Update the page elements
var data =JSON.parse(dataa);
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
} else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
}
});
}
});

My jquery and ajax call is not responding and showing unexpected error in console

I don't know why my code is giving error while making the ajax call and not responding or working at all. I ran this on an html file. I took this function - getParameterByName() from another stackoverflow answer.tweet-container tag is down the code below outside this script and an empty division.I tried some jquery also.
<script>
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
$(document).ready(function(){
console.log("working");
var query = getParameterByName("q")
// console.log("query");
var tweetList = [];
function parseTweets(){
if (tweetList == 0){
$("#tweet-container").text("No tweets currently found.")
} else {
//tweets are existing, so parse and display them
$.each(parseTweets, function(key, value){
//console.log(key)
// console.log(value.user)
// console.log(value.content)
var tweetKey = value.key;
var tweetUser = value.user;
var tweetContent = value.content;
$("#tweet-container").append(
"<div class=\"media\"><div class=\"media-body\">" + tweetContent + "</br> via " + tweetUser.username + " | " + View + "</div></div><hr/>"
)
})
}
}
$.ajax({
url:"/api/tweet/",
data:{
"q": query
},
method: "GET",
success:function(data){
//console.log(data)
tweetList = data
parseTweets()
},
error:
function(data){
console.log("error")
console.log(data)
}
})
});
</script>
strong text
Fix the quotes to resolve your syntax error:
$("#tweet-container").append("<div class=\"media\"><div class=\"media-body\">" + tweetContent + " </br> via " + tweetUser.username + " | " + "View</div></div><hr/>")

How to include the #Html.AntiForgeryToken() when deleting an object using a Delete link

i have the following ajax.actionlink which calls a Delete action method for deleting an object:-
#if (!item.IsAlreadyAssigned(item.LabTestID))
{
string i = "Are You sure You want to delete (" + #item.Description.ToString() + ") ?";
#Ajax.ActionLink("Delete",
"Delete", "LabTest",
new { id = item.LabTestID },
new AjaxOptions
{ Confirm = i,
HttpMethod = "Post",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
})
}
but is there a way to include #Html.AntiForgeryToken() with the Ajax.actionlink deletion call to make sure that no attacker can send a false deletion request?
BR
You need to use the Html.AntiForgeryToken helper which sets a cookie and emits a hidden field with the same value. When sending the AJAX request you need to add this value to the POST data as well.
So I would use a normal link instead of an Ajax link:
#Html.ActionLink(
"Delete",
"Delete",
"LabTest",
new {
id = item.LabTestID
},
new {
#class = "delete",
data_confirm = "Are You sure You want to delete (" + item.Description.ToString() + ") ?"
}
)
and then put the hidden field somewhere in the DOM (for example before the closing body tag):
#Html.AntiForgeryToken()
and finally unobtrusively AJAXify the delete anchor:
$(function () {
$('.delete').click(function () {
if (!confirm($(this).data('confirm'))) {
return false;
}
var token = $(':input:hidden[name*="RequestVerificationToken"]');
var data = { };
data[token.attr('name')] = token.val();
$.ajax({
url: this.href,
type: 'POST',
data: data,
success: function (result) {
},
error: function () {
}
});
return false;
});
});
Now you could decorate your Delete action with the ValidateAntiForgeryToken attribute:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id)
{
...
}
Modifying the answer by Bronx:
$.ajaxPrefilter(function (options, localOptions, jqXHR) {
var token, tokenQuery;
if (options.type.toLowerCase() !== 'get') {
token = GetAntiForgeryToken();
if (options.data.indexOf(token.name)===-1) {
tokenQuery = token.name + '=' + token.value;
options.data = options.data ? (options.data + '&' + tokenQuery)
: tokenQuery;
}
}
});
combined with this answer by Jon White
function GetAntiForgeryToken() {
var tokenField = $("input[type='hidden'][name$='RequestVerificationToken']");
if (tokenField.length == 0) { return null;
} else {
return {
name: tokenField[0].name,
value: tokenField[0].value
};
}
Edit
sorry - realised I am re-inventing the wheel here SO asp-net-mvc-antiforgerytoken-over-ajax/16495855#16495855

MVC3 and Ajax error "The parameters dictionary contains a null entry for parameter ..."

This is driving me nuts!
I have a view that is populated using Ajax using the script below.
function loadAcquisitions() {
var description = $("input#searchDescription").val();
var startDate = $("input#searchStartDate").val();
var endDate = $("input#searchEndDate").val();
$.ajax({
type: "POST",
dataType: "json",
url: "/Acquisition/Find",
data: { searchDescription: description, searchStartDate: startDate, searchEndDate: endDate },
success: function (jsonresults) {
$("tbody#acquisitionContent").find("tr").remove().end();
var pageCount = parseInt(jsonresults.length / pageSize);
var startItemIndex = currentPageIndex * pageSize;
var itemsToDisplay = pageSize + startItemIndex;
if ((jsonresults.length - startItemIndex) < pageSize) {
itemsToDisplay = jsonresults.length - startItemIndex + pageSize;
}
for (var i = startItemIndex; i < itemsToDisplay; i++) {
$("tbody#acquisitionContent").append('<tr>' +
'<td>Edit</td>' +
'<td>' + jsonresults[i].AcquisitionDescription + '</td>' +
'<td>' + jsonresults[i].AcquisitionDate + '</td>' +
'<td>$' + jsonresults[i].AcquisitionCost + '</td>' +
'<td>$' + jsonresults[i].InstallationCost + '</td>' +
'<td class="last">$' + jsonresults[i].DeliveryCost + '</td>' +
'</tr>');
}
$('#pageTitle').text('Page ' + (currentPageIndex + 1) + ' of ' + pageCount);
},
error: function (c, b, a) {
alert(a);
}
});
}
Please note that the link is generated using the line:
'<td>Edit</td>'
The link tag appears to be generated correctly and is in the form of
/Acquisition/Edit/123
In the controller, I have the following function called 'Edit' which looks like this:
public ActionResult Edit(int acquisitionID)
{
Acquisition acquisition = Acquisition.Get(acquisitionID);
return View(acquisition);
}
Then, in the global.asax I have a route defined for 'Edit' that looks like this:
routes.MapRoute(
"EditAcquisition",
"{controller}/{action}/{acquisitionID}",
new { controller = "Acquisition", action = "Edit"}
);
I've tried changing the 'Edit' function in the controller to accept a nullable int (int?) acquisitionID which gets rid of the error - but doesn't change the fact that a null is being passed into the controllers 'Edit' function from the link generated by the Ajax code.
Any help would be greatly appreciated!
Thanks!
Update:
When I update the global.asax and add 'acquisitionID' as a parameter like this:
routes.MapRoute(
"EditAcquisition",
"{controller}/{action}/{acquisitionID}",
new { controller = "Acquisition", action = "Edit", acquisitionID = 0 }
);
the application behaves very differently in that the navigation links now all have 'Index' appended to them.
/Acquisition/
becomes
/Acquisition/Index
Update:
Here is the RegisterRoutes method of the global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"EditProperty",
"{controller}/{action}/{propertyID}",
new {controller = "Property", action = "Edit"}
);
routes.MapRoute(
"EditAssignee",
"{controller}/{action}/{assigneeID}",
new {controller = "Assignee", action = "Edit"}
);
routes.MapRoute(
"EditAcquisition",
"{controller}/{action}/{acquisitionID}",
new {controller = "Acquisition", action = "Edit"}
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
}
Your route
routes.MapRoute(
"EditProperty",
"{controller}/{action}/{propertyID}",
new {controller = "Property", action = "Edit"}
);
Matches every other route.. (since they all have the same pattern of /controller/action/id)
The values provided by new {controller = "Property", action = "Edit"} are the default, not the allowed ones..
so any url in the form /somecontroller/someaction/someid will be matched by that, and the id will be called propertyID.
That is why you receive no acquisitionID
Either just keep that one route only and name the propertyID to something generic like id and use that in your method, or use constraints for all your routes that have identical pattern
routes.MapRoute(
"EditProperty",
"{controller}/{action}/{propertyID}",
new {controller = "Property", action = "Edit"},
new {controller = "Property", action="Edit"} // constraint
);
For my routes, I always include the URLParameter setting:
routes.MapRoute(
"EditAcquisition",
"{controller}/{action}/{acquisitionID}",
new
{
controller = "Acquisition",
action = "Edit",
acquisitionID = UrlParameter.Optional
}
);
which works even if the parameter is not nullable int. I've also done
acquisitionID = 0
I'm afraid I can't really explain why it works though.
EDIT
Something else to try
"EditAcquisition",
"Acquisition/Edit/{acquisitionID}",
new
{
controller = "Acquisition",
action = "Edit",
acquisitionID = UrlParameter.Optional
}
So the URL is being matched against the second parameter, URL, not the third, which are the defaults.

Passing jquery object to MVC action

I am trying to use .ajax() to post a People object to a MVC2 action that expects a ViewModel as parameter. The ViewModel has a People property.
The problem is that when the MVC action is activated, the ajax() postback People object is always null. I used Fiddler to diagnose the problem. The property values in the People object are all contained in the header. Here is my client jQuery script. Please note that I used three methods to stuff the property values into People object, but none of them works.
StaffDlg.delegate("#SaveButton", "click",
function (e) {
e.preventDefault();
People["PKey"] = $("#PKey").val();
People["FName"] = $("#FName").val();
People["LName"] = $("#LName").val();
People["MName"] = $("#MName").val();
People["SSN"] = $("#SSN").val();
People["Gender"] = $("#Gender").val();
People["DOB"] = $("#DOB").val();
People["BirthPlace"] = $("#BirthPlace").val();
People["NetworkAccount"] = $("#NetworkAccount").val();
var pkey = $("#PKey").val();
var action;
if (!isNaN(parseFloat(pkey)) && isFinite(pkey)) {
action = "Edit" + "/" + pkey;
}
else {
action = "Create";
}
$.ajax({
url: getRootUrl() + "/Staff/" + action,
//data: { FName: $("#FName").val(), LName: $("#LName").val(), MName: $("#MName").val(),
// SSN: $("#SSN").val(), Gender: $("#Gender").val(), DOB: $("#DOB").val(),
// BirthPlace: $("#BirthPlace").val(), NetworkAccount: $("#NetworkAccount").val()
//},
//data: JSON.stringify(People),
data: $("Form").serialize(),
dataType: "json",
contentType: "application/json; charset=utf-8",
type: "POST",
success: function (result) {
$("#ajaxResponse").addClass("whiteOnGreen").html("Update succeeded");
},
error: function (qXHR, textStatus, errorThrown) {
$("#ajaxResponse").addClass("whiteOnRed").html("Failed to save the record!\r\n" +
textStatus + ": " + errorThrown + "\r\n" +
"data : " + JSON.stringify(People));
}
})
}
);
and here is the MVC action.
public ActionResult Edit(int id, StaffViewModel updatedStaff)
{
People staff = _staffService.GetStaff(id);
if (updatedStaff == null)
return View("NotFound");
if (ModelState.IsValid)
{
TryUpdateModel<People>(staff, "staff");
staff.RecordLastUpdated = DateTime.Now;
staff.UpdatedBy = HttpContext.User.Identity.Name;
_staffService.SaveStaff();
//return RedirectToAction("Index", new { id = thisStaff.PKey });
if (Request.IsAjaxRequest())
return this.Json(staff, JsonRequestBehavior.AllowGet);
else
{
if (string.IsNullOrEmpty(updatedStaff.previousURL))
return Redirect("/Staff/Startwith/" + staff.LName.Substring(1, 1));
else
return Redirect(updatedStaff.previousURL);
}
}
else
{
if (Request.IsAjaxRequest())
{
string errorMessage = "<div class='whiteOnRed error'>"
+ "The following errors occurred:<ul>";
foreach (var key in ModelState.Keys)
{
var error = ModelState[key].Errors.FirstOrDefault();
if (error != null)
{
errorMessage += "<li>"
+ error.ErrorMessage + "</li>";
}
}
errorMessage += "</ul></div>";
return Json(new { Message = errorMessage });
}
else
return View(updatedStaff);
}
}
You state that the form expects a StaffViewModel as a parameter, and a StaffViewModel has a People property... but you are not passing the full StafFViewModel object - instead you are passing a People object from the Ajax call, and hoping that the People property gets populated on the MVC end.
There is a disconnect there and the auto-binder doesn't know how to bridge it.
Try creating a controller method with a (int, People) signature, and see if that works for you.
Otherwise, you might need to create a custom binder.
Try removing dataType and contentType settings from your ajax call:
$.ajax({
url: getRootUrl() + "/Staff/" + action,
data: $("Form").serializeArray(),
type: "POST",
success: function (result) {
$("#ajaxResponse").addClass("whiteOnGreen").html("Update succeeded");
},
error: function (qXHR, textStatus, errorThrown) {
$("#ajaxResponse").addClass("whiteOnRed").html("Failed to save the record!\r\n" +
textStatus + ": " + errorThrown + "\r\n" +
"data : " + JSON.stringify(People));
}
})
I solved the problem with the .ajax() not posting the form values to the MVC Create(People person) action. It was the parameter type that this different than the one used in Edit(StaffViewModel). Now both action accept the same type of parameter, StaffViewMode.

Resources