jQuery Ajax calls and the Html.AntiForgeryToken() jQuery Ajax calls and the Html.AntiForgeryToken() ajax ajax

jQuery Ajax calls and the Html.AntiForgeryToken()


I use a simple js function like this

AddAntiForgeryToken = function(data) {    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();    return data;};

Since every form on a page will have the same value for the token, just put something like this in your top-most master page

<%-- used for ajax in AddAntiForgeryToken() --%><form id="__AjaxAntiForgeryForm" action="#" method="post"><%= Html.AntiForgeryToken()%></form>  

Then in your ajax call do (edited to match your second example)

$.ajax({    type: "post",    dataType: "html",    url: $(this).attr("rel"),    data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),    success: function (response) {        // ....    }});


I like the solution provided by 360Airwalk, but it may be improved a bit.

The first problem is that if you make $.post() with empty data, jQuery doesn't add a Content-Type header, and in this case ASP.NET MVC fails to receive and check the token. So you have to ensure the header is always there.

Another improvement is support of all HTTP verbs with content: POST, PUT, DELETE etc. Though you may use only POSTs in your application, it's better to have a generic solution and verify that all data you receive with any verb has an anti-forgery token.

$(document).ready(function () {    var securityToken = $('[name=__RequestVerificationToken]').val();    $(document).ajaxSend(function (event, request, opt) {        if (opt.hasContent && securityToken) {   // handle all verbs with content            var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);            opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;            // ensure Content-Type header is present!            if (opt.contentType !== false || event.contentType) {                request.setRequestHeader( "Content-Type", opt.contentType);            }        }    });});


I know there are a lot of other answers, but this article is nice and concise and forces you to check all of your HttpPosts, not just some of them:

http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/

It uses HTTP headers instead of trying to modify the form collection.

Server

//make sure to add this to your global action filters[AttributeUsage(AttributeTargets.Class)]public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute{    public override void OnAuthorization( AuthorizationContext filterContext )    {        var request = filterContext.HttpContext.Request;        //  Only validate POSTs        if (request.HttpMethod == WebRequestMethods.Http.Post)        {            //  Ajax POSTs and normal form posts have to be treated differently when it comes            //  to validating the AntiForgeryToken            if (request.IsAjaxRequest())            {                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];                var cookieValue = antiForgeryCookie != null                    ? antiForgeryCookie.Value                     : null;                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);            }            else            {                new ValidateAntiForgeryTokenAttribute()                    .OnAuthorization(filterContext);            }        }    }}

Client

var token = $('[name=__RequestVerificationToken]').val();var headers = {};headers["__RequestVerificationToken"] = token;$.ajax({    type: 'POST',    url: '/Home/Ajax',    cache: false,    headers: headers,    contentType: 'application/json; charset=utf-8',    data: { title: "This is my title", contents: "These are my contents" },    success: function () {        ...    },    error: function () {        ...    }});