Use ValidateAntiForgeryToken with JQGrid in asp.net MVC? - asp.net-mvc

In a hybrid asp.net web forms/mvc 5.2.6 application, using JQuery.jqGrid v4.4.4, I'm struggling to discover a way to use the ValidateAntiForgeryToken attribute on the Controller method that jqGrid posts to when fetching its data.
The grid is read-only. The "datatype" is "json" and the "mtype" is "POST". I've tried simply appending the value of the __RequestVerificationToken hidden input to the data that gets posted back to the Controller, but that does not work; the site simply throws a missing antiforgery token exception.
I notice that when one wants to make an $.ajax post of json data to a Controller method one can pass the __RequestVerificationToken in the "headers" parameter. While the jqGrid makes an $.ajax call behind the scenes, unfortunately it does not have a headers parameter.
I've found examples on SO where one can pass the token via the editData parameter (such as this: JQGrid able to pass ValidateAntiForgeryToken through the main CRUD controls?), but my grid is read-only, and in any case I want to enforce the token when the user enters search criteria and then clicks a button to fill the grid.
Is there any way to use the ValidateAntiForgeryToken when filling a jqgrid?

You can include postData parameter with __RequestVerificationToken property defined as the following function:
postData: {
__RequestVerificationToken: function () {
return jQuery("input[name=__RequestVerificationToken]").val();
}
}
It will add __RequestVerificationToken parameter to all request sent to the server during filling the grid.

Oleg's answer was the correct answer for me, but I also bumbled across this broader-brush solution from https://github.com/VahidN/jqGrid-Samples/blob/master/jqGrid04/jqGrid04/Views/Home/Index.cshtml, which adds the verification token to every ajax POST:
$(document).ajaxSend(function (elm, xhr, s) {
let securityToken = $('[name=__RequestVerificationToken]').val();
if (s.type === 'POST' && typeof securityToken != 'undefined') {
if (s.data.length > 0) {
s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
}
else {
s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
}
}
});

Related

return Json will redirects to another view when Url specified

When you do return Json(...) you are specifically telling MVC not to use a view, and to serve serialized JSON data. Your browser opens a download dialog because it doesn't know what to do with this data.
i got the above information from below link
How to return Json object from MVC controller to view
when i give this below code in some action result
return Json(new { Url = "sep/employee"}
whether it will redirect to specified action ? how it redirects to the URl ?
for this case why i cant use return RedirectToAction("sep/employee").
how return Json code redirects to action which specified in the Url.
ex:
public ActionResult Index()
{
................................
return Json(new { Url = "sep/employee"}
}
public ActionResult employee()
{
....................
}
what is the difference b/s redirectaction and return Json
You return the following line to an ajax success call
return Json(new { Url = "sep/employee"});
you then need to specify where to redirect to the new page
success: function(result) {
window.location.href=result.Url;
}
RedirectToAction simply returns 302 code to your browser with URL telling where the browser should redirect to. The browser immediately makes yet another call to the server to that URL obtained from redirection response.
RedirectToAction internals are:
Construct redirection url from parameters passed to RedirectToAction
Return new RedirectToRouteResult
In ExecuteResult of RedirectToRouteResult you can find the following line:
context.HttpContext.Response.Redirect(destinationUrl, endResponse: false);
which is merely returning 302 with redirection URL. More info - look at source code here.
Returning JSON data simply returns JSON serialized object to your browser. Is not meant to do any redirect. To consume such a result you will likely call the server using $.ajax:
$.ajax({
url: 'sep/employee',
type: 'POST'
success: function(result) {
// handle the result from the server, i.e. process returned JSON data
}
});
ExecuteResult of JsonResult just serializes passed CLR object to the response stream, which lands in your browser after response is fully received. Then you can handle such response in JavaScript code.
EDIT:
You of course can mimic 302 redirection by returning Json like
return Json(new { Url = "redirectionUrl"}
and at client side handle it like
$.ajax({
url: 'sep/employee',
type: 'POST'
success: function(result) {
// mimic the 302 redirection
windows.location.href = result.Url
}
});
although IMHO it should be avoided since you reinvent MVC infrastructure and enlarge your code base.
whether it will redirect to specified action ? how it redirects to the URl ?
I assume you mean to ask, "will it redirect to specified action? how will it redirect the the URI?"
To answer your question: How it redirects to the URL?
In your example it will redirect to the URL, if you made the HTTP request as AJAX and that you will explicitly handle the resulting HTTP response to actually redirect to the URL that you received. So your view should have something like this:
$.ajax({
url: '{your controller}/index',
type: 'GET'
success: function(url) {
// write code to redirect to the URL
// example:
// window.navigate(url)
}
});
If your view does not have anything that, then it will not redirect. You did not post your view, so I am assuming it just a normal page load.
Your next question, what is the difference b/s redirection and return Json?
If you really just want to redirect then do RedirectToAction from your controller, that is exactly what it is for. You can do the same effect using AJAX and JSON to be able to redirect, but AJAX and JSON serves a much wider purpose than just redirecting and in most cases (unless you have very good reasons) you probably will not want replace RedirectToAction with that approach.

Ajax post throws A required anti-forgery token was not supplied or was invalid

I'm trying to secure my ajax posts using the anti-forgery mechanism.
First I've added the antiforgerytoken helper method call to my view
#Html.AntiForgeryToken()
and then adjusted my jquery post call
var values = $(this).serialize() + "&__RequestVerificationToken=" + $("input[name='__RequestVerificationToken']").val();
$.post(url, values)
.success(page.submitSuccess)
.error(page.submitError)
.complete(page.submitComplete);
and of course I decorated my action method with the ValidateAntiForgeryToken
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ProjectCreateCommand command)
{
....
}
but after submiting the form it throws the A required anti-forgery token was not supplied or was invalid error.
I've deleted the token cookie and also I've restarted the browser.
Am I missing something ?
if you use $(form).serialize(); it will serialize all input tags, so you can do it by the $.post jquery method. Try something like this:
$("#you_form").submit(function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: $(this).attr("action"), // get url from action attribute, your route setted by the Html.BeginForm()
data: $(this).serialize(), // serialize all input tags from this form
success: page.submitSuccess;
});
});
There is no problem using #Html.AntiForgeryToken(), serialize method will add this together.
Take a look at this link: http://api.jquery.com/jQuery.post/

Help with Ajax post to action method

I am a new to MVC an need a little help.
In my view I make an ajax post as below.
function PostCheckedPdf(e) {
var values = new Array();
$('input:checked').each(function () { values.push(this.value); });
$.post("/UnregisteredUserPreview/DownloadPdfInvoice",
{ checkedList: values });
}
This post the values of any checkboxes that are checked inside a third party Grid component (Telerik). The Action method receives the array fine and loops through each value rendering a pdf report and putting the report into a ZipStream which is attached to the Response. After the loop the zipstream is closed and I return View();
When the Action is invoked through the $.post it runs through the action method but nothing happens in the browser.
If I call the Action through an action link (with a couple of hard coded value instead of passing the checked boxes values) the zip file with all the pdfs is downloaded.
What am I doing wrong or how can I post the checked values with an ActionLink?
Thanks in Advance!
Toby.
The difference is that your ActionLink is emitting an <a> tag, which is performing a GET operation. The browser interprets the contents of the response and opens the PDF.
Your jQuery method is performing a POST, but does nothing with the response, and thus silently throws it away in the background.
You need to actually do something with the return contents, like write it out to another window.
var w = window.open('', '', 'width=800,height=600,resizeable,scrollbars');
$.post("/UnregisteredUserPreview/DownloadPdfInvoice",
{ checkedList: values },
function(content){
w.document.write(content);
w.document.close(); // needed for chrome and safari
});
You are making an Ajax call to the server there and client side code should receive the returned result which seems that you are not doing there. It should be something like below :
$.ajax({
type: 'POST'
url: '/UnregisteredUserPreview/DownloadPdfInvoice',
data: { checkedList: values },
success: function (r) {
alert(r.result);
}
});
And assume that your controller is like below :
public ActionResult DownloadPdfInvoice() {
//do you stuff here
return Json(new { result = "url_of_your_created_pdf_might_be_the_return_result_here"});
}
NOTE
If you are posting your data with anchor tag, it is better to
prevent the default action of this tag so that it won't do anything
else but the thing you're telling it to do. You can do that by adding the
following code at the end of your click event function :
$("#myLink").click(function(e) {
//do the logic here
//ajax call, etc.
e.preventDefault();
});
Have a look at the below blog post as well. It might widen your thoughts :
http://www.tugberkugurlu.com/archive/working-with-jquery-ajax-api-on-asp-net-mvc-3-0-power-of-json-jquery-and-asp-net-mvc-partial-views

ASP.Net MVC 3 WebFormsViewEngine HTML Helpers and JSON data

I would like to know if is possible in ASP.Net MVC 3, using Web forms view engine and HTML Helpers, and the client side we are using Ext.Js to generate the grids.
The problem is when I return JSON(data) for the Ext.JS grid and the HTML Helper.
The HTML Helper is not able to render the JSON element.
It pops-up a window asking "What firefox should do with this file?".
I've tried to use:
return this.Json(new { objectJson = object}, "text/html", JsonRequestBehavior.AllowGet);
And it returned a new page with the HMTML Code, didn't bind to the HTML Helpers. I also tried without the JsonRequestBehavior.AllowGet and the result was:
This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.
And even if I change the MIME type of the Header to application/json and make the method's return as JSONResult instead of ActionResult it still doesn't recognize the file.
return this.Json(new { IssueInventoryPartModel = issueInventoryPartmodel, success = true }, "application/json", JsonRequestBehavior.AllowGet);
Briefly the question is: The HTML Helper for Web Form View Engine binds with JSON?
Best regards,
Tito
I had this problem while sending html data via json, and solved it by adding contenttype to the jsonresult, in the server side action method (called via js in client side), there should be something like :
return Json(dataToReturn, "text/html")
it sounds like the content-type for the action result is not being set properly
how about including JsonRequestBehavior.AllowGet on the return of the JSON as in:
return Json(new
{
data = components,
success = true
}, JsonRequestBehavior.AllowGet);

Prevent user from submitting if a field is not unique in an MVC form using AJAX

You know those fields you see on forms which indicate that a value can't be used because its already used? Like a username for a membership site.
I'd like to do this for an MVC form via jquery. What is the recommendation for this?
You could create a JsonResult action that you can call from your javascript code. Eg
public JsonResult IsUsernameAvailable(string username) {
// return result
return Json(true);
}
And then hook it up to your username-field like so using jQuery
$("#username").blur(function() { checkAvailability($(this).val()); });
function checkAvailability(username) {
$.getJSON("/User/IsUsernameAvailable", { username: username }, function(result) {
alert("Is available: " + result);
});
}
If you are using MVC 3 there is a new Remote attribute which you can use. You specify a route or controller/action for the attribute and return "true" or "false" (or any string != "true", which could be 'result' in your case. You will get a client side validation error similar to the errors you get if a required field is left blank etc.

Resources