How can I supply an AntiForgeryToken when posting JSON data using $.ajax? How can I supply an AntiForgeryToken when posting JSON data using $.ajax? ajax ajax

How can I supply an AntiForgeryToken when posting JSON data using $.ajax?


You don't need the ValidationHttpRequestWrapper solution since MVC 4. According to this link.

  1. Put the token in the headers.
  2. Create a filter.
  3. Put the attribute on your method.

Here is my solution:

var token = $('input[name="__RequestVerificationToken"]').val();var headers = {};headers['__RequestVerificationToken'] = token;$.ajax({    type: 'POST',    url: '/MyTestMethod',    contentType: 'application/json; charset=utf-8',    headers: headers,    data: JSON.stringify({        Test: 'test'    }),    dataType: "json",    success: function () {},    error: function (xhr) {}});[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter{    public void OnAuthorization(AuthorizationContext filterContext)    {        if (filterContext == null)        {            throw new ArgumentNullException("filterContext");        }        var httpContext = filterContext.HttpContext;        var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];        AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);    }}[HttpPost][AllowAnonymous][ValidateJsonAntiForgeryToken]public async Task<JsonResult> MyTestMethod(string Test){    return Json(true);}


What is wrong is that the controller action that is supposed to handle this request and which is marked with the [ValidateAntiForgeryToken] expects a parameter called __RequestVerificationToken to be POSTed along with the request.

There's no such parameter POSTed as you are using JSON.stringify(data) which converts your form to its JSON representation and so the exception is thrown.

So I can see two possible solutions here:

Number 1: Use x-www-form-urlencoded instead of JSON for sending your request parameters:

data["__RequestVerificationToken"] = $('[name=__RequestVerificationToken]').val();data["fiscalyear"] = fiscalyear;// ... other data if necessary$.ajax({    url: url,    type: 'POST',    context: document.body,    data: data,    success: function() { refresh(); }});

Number 2: Separate the request into two parameters:

data["fiscalyear"] = fiscalyear;// ... other data if necessaryvar token = $('[name=__RequestVerificationToken]').val();$.ajax({    url: url,    type: 'POST',    context: document.body,    data: { __RequestVerificationToken: token, jsonRequest: JSON.stringify(data) },    success: function() { refresh(); }});

So in all cases you need to POST the __RequestVerificationToken value.


I was just implementing this actual problem in my current project. I did it for all Ajax POSTs that needed an authenticated user.

First off, I decided to hook my jQuery Ajax calls so I do not to repeat myself too often. This JavaScript snippet ensures all ajax (post) calls will add my request validation token to the request. Note: the name __RequestVerificationToken is used by the .NET framework so I can use the standard Anti-CSRF features as shown below.

$(document).ready(function () {    securityToken = $('[name=__RequestVerificationToken]').val();    $('body').bind('ajaxSend', function (elm, xhr, s) {        if (s.type == 'POST' && typeof securityToken != 'undefined') {            if (s.data.length > 0) {                s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);            }            else {                s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);            }        }    });});

In your Views where you need the token to be available to the above JavaScript code, just use the common HTML-Helper. You can basically add this code wherever you want. I placed it within a if(Request.IsAuthenticated) statement:

@Html.AntiForgeryToken() // You can provide a string as salt when needed which needs to match the one on the controller

In your controller simply use the standard ASP.NET MVC anti-CSRF mechanism. I did it like this (though I actually used a salt).

[HttpPost][Authorize][ValidateAntiForgeryToken]public JsonResult SomeMethod(string param){    // Do something    return Json(true);}

With Firebug or a similar tool you can easily see how your POST requests now have a __RequestVerificationToken parameter appended.