27

I have problem with below details from MVC project.

When I am trying to use jquery ajax request with loading panel like spinning gif (or even text), I am getting error, observed from fiddler that

The required anti-forgery form field "__RequestVerificationToken" is not present.

If I comment [ValidateAntiForgeryToken] attribute at POST action method and use loading panel it is working fine.I want to know why I am getting this error.

I have even used the query string serialized with

__RequestVerificationToken= $('input[name="__RequestVerificationToken"').val()

still I am getting error

The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the <machineKey> configuration specifies explicit encryption and validation keys.

AutoGenerate cannot be used in a cluster

What should I use?

Here it updated question code

var token = $('input[name="__RequestVerificationToken"]').val();
$('#submitaddress').click(function subaddr(event) {
    event.preventDefault();
    event.stopPropagation();
  //$('#addAddress').html('<img src="/img/animated-overlay.gif"> Sending...');
   // $('#addAddress').blur();
    //  $(this).bl
    if ($('#Jobid').val()!="") {
        $('#TransportJobId').val(parseInt($('#Jobid').val()));
        $.ajax(
              {
                  url: '/TransportJobAddress/create',
                  type: 'POST',
                  data: "__RequestVerificationToken=" + token + "" + $('form[action="/TransportJobAddress/Create"]').serialize(),
                  success: function poste(data, textStatus, jqXHR) { $('#addAddress').html(data); return false; },
                  error: function err(jqXHR, textStatus, errorThrown) { alert('error at address :' + errorThrown); }
              });
    }
    else {
        var transportid = 2;
        $.ajax({
            url: '/TransportJob/create',
            type: 'POST',
            data: "__RequestVerificationToken=" + token + "" + $('form[action="/TransportJob/Create"]').serialize(),
            success: function sfn(data, textStatus, jqXHR) {
                transportid = parseInt(data);
                $('#Jobid').val(data);
               // alert('inserted id :' + data);
                $('#TransportJobId').val((transportid));
                $.ajax(
         {

             url: '/TransportJobAddress/create',
             type: 'POST',
             //beforeSend: function myintserver(xhr){  
             //        $('#addAddress').html('<div id="temp_load" style="text-align:center">please wait ...</div>');
             //}, 
             data: "__RequestVerificationToken=" + token + "" + $('form[action="/TransportJobAddress/Create"]').serialize(),
             success: function poste(data, textStatus, jqXHR) {
                 $('#addAddress').html(data);

             },
             error: function err(jqXHR, textStatus, errorThrown) {
                 alert('error at address :' + errorThrown);
             }

         });
            },
            error: function myfunction(jqXHR, textStatus, errorThrown) {
                alert("error at transport :" + jqXHR.textStatus);
            },
            complete: function completefunc() {
              //  alert('ajax completed all requests');
                return false;
            }

        });
    }
});

form tags

<form action="/TransportJob/Create" method="post"><input     name="__RequestVerificationToken" type="hidden"   value="ydYSei0_RfyBf619dQrhDwwoCM7OwWkJQQEMNvNdAkefiFfYvRQ0MJYYu0zkktNxlJk_y1ZJO9-yb-  COap8mqd0cvh8cDYYik4HJ0pZXTgE1" />   

TransportJob form tag 2 on same page

<form action="/TransportJobAddress/Create" method="post" novalidate="novalidate"><input name="__RequestVerificationToken" type="hidden"    value="Np2vUZJPk1TJlv846oPSU6hg4SjMHRcCk1CacaqZbpHOg8WbV4GZv06noRDl7F_iT9qQf3BIXo3n9wGW68sU mki7g3-ku_BSHBDN-g2aaKc1"> 

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
Ravi Hanok
  • 405
  • 1
  • 12
  • 23
  • 1
    Have you added the token to your View? Like this: `@Html.AntiForgeryToken()` – hofnarwillie Nov 05 '13 at 12:28
  • By default it is added before fieldset tag after form tag – Ravi Hanok Nov 05 '13 at 12:30
  • 1
    Add your AntiForgeryToken to header of ajax call, not in data – freshbm Nov 05 '13 at 12:45
  • Just saw your update. Could you show us the data + header fields inside your ajax request? – Kippie Nov 05 '13 at 12:48
  • I have two forms in one click it will submit one form and second form will submit with id of first form – Ravi Hanok Nov 05 '13 at 12:48
  • 1
    I solved my self the issue because of my mistake is ,I have used loading panel id before ajax collecting the details(should not used loading panel under button click event,we should use before send ajax event) other than my mistake solution was given by @freshbm – Ravi Hanok Nov 06 '13 at 07:54

5 Answers5

37

Rather than manually adding it to each request, I usually do something like this:

var token = $('input[name="__RequestVerificationToken"]').val();
$.ajaxPrefilter(function (options, originalOptions) {
  if (options.type.toUpperCase() == "POST") {
    options.data = $.param($.extend(originalOptions.data, { __RequestVerificationToken: token }));
  }
});

This will automatically add your token to any ajax POST you do.

Kippie
  • 3,760
  • 3
  • 23
  • 38
  • Great workaround! Just a small remark: if what you're using as the 'data' of the ajax call is a FormData (like showed in @hofnarwillie answer), you have to use **.append**: `options.data.append("__RequestVerificationToken", token);` – Silvestre May 30 '15 at 04:00
18

Have you added your token to the header of the ajax call?

You need to add AntiForgeryToken in your message header in the ajax call:

var token = $('input[name="__RequestVerificationToken"]').val();

var headers = {};

headers['__RequestVerificationToken'] = token;

$.ajax({
        url: ... some url,
        headers: headers,
        ....
});

Try this in your code:

var token = $('input[name="__RequestVerificationToken"]').val();
var tokenadr = $('form[action="/TransportJobAddress/Create"] input[name="__RequestVerificationToken"]').val(); 

var headers = {};
var headersadr = {};
headers['__RequestVerificationToken'] = token;
headersadr['__RequestVerificationToken'] = tokenadr;

$('#submitaddress').click(function subaddr(event) {
    event.preventDefault();
    event.stopPropagation();
  //$('#addAddress').html('<img src="/img/animated-overlay.gif"> Sending...');
   // $('#addAddress').blur();
    //  $(this).bl
    if ($('#Jobid').val()!="") {
        $('#TransportJobId').val(parseInt($('#Jobid').val()));
        $.ajax(
              {
                  url: '/TransportJobAddress/create',
                  type: 'POST',
                  headers:headersadr, 
                  data: "__RequestVerificationToken=" + token + "" + $('form[action="/TransportJobAddress/Create"]').serialize(),
                  success: function poste(data, textStatus, jqXHR) { $('#addAddress').html(data); return false; },
                  error: function err(jqXHR, textStatus, errorThrown) { alert('error at address :' + errorThrown); }
              });
    }
    else {
        var transportid = 2;
        $.ajax({
            url: '/TransportJob/create',
            type: 'POST',
            headers:headers, 
            data: $('form[action="/TransportJob/Create"]').serialize(),
            success: function sfn(data, textStatus, jqXHR) {
                transportid = parseInt(data);
                $('#Jobid').val(data);
               // alert('inserted id :' + data);
                $('#TransportJobId').val((transportid));
                $.ajax(
         {

             url: '/TransportJobAddress/create',
             type: 'POST',
             //beforeSend: function myintserver(xhr){  
             //        $('#addAddress').html('<div id="temp_load" style="text-align:center">please wait ...</div>');
             //},
             headers:headers, 
             data: $('form[action="/TransportJobAddress/Create"]').serialize(),
             success: function poste(data, textStatus, jqXHR) {
                 $('#addAddress').html(data);

             },
             error: function err(jqXHR, textStatus, errorThrown) {
                 alert('error at address :' + errorThrown);
             }

         });
            },
            error: function myfunction(jqXHR, textStatus, errorThrown) {
                alert("error at transport :" + jqXHR.textStatus);
            },
            complete: function completefunc() {
              //  alert('ajax completed all requests');
                return false;
            }

        });
    }
});

Added headers line in your ajax call.

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
freshbm
  • 5,540
  • 5
  • 46
  • 75
  • Hi freshbm, Adding header to first form worked,but while submitting second it is not worked how to add header to second one also differentiating from first form? I have used different header like var tokenaddr = $('form[action="/TransportJobAddress/create"] input[name="__RequestVerificationToken"]').val(); headers['__RequestVerificationToken'] = tokenaddr; – Ravi Hanok Nov 05 '13 at 13:44
  • I have added the two form tags on same page how to take two tokens and use in headers – Ravi Hanok Nov 05 '13 at 14:29
  • Maybe you misspeled your form action: $('form[action="/TransportJobAddress/Create"] In your comment Create is small letters. Whati is value of tokenaddr? – freshbm Nov 05 '13 at 18:34
  • If I use var tokenaddr =('form[action="/TransportJobAddress/create"] input[name="__RequestVerificationToken"]').val(); headers['__RequestVerificationToken'] = tokenaddr; above as second form header in fiddler getting response RequestVerificationToken is not present.don't know how i missed header for second form . – Ravi Hanok Nov 06 '13 at 05:55
3

Have you added the token to your View? Like this:

<form method="post" action="/my-controller/my-action">
    @Html.AntiForgeryToken()
</form>

Since your controller receiving the post is looking for the anti forgery token, you need to ensure that you add it to your form in the view.

EDIT:

Try building your data in json first:

var formData = $('form[action="/TransportJobAddress/Create"]').serialize();
$.extend(formData, {'__RequestVerificationToken': token });

//and then in your ajax call:
$.ajax({
    //...
    data:formData
    //...
});
hofnarwillie
  • 3,563
  • 10
  • 49
  • 73
2

View or Layout:

< form id='_id' method='POST'> @html.antiforgeryToken(); < /form>

The ajax call function:

var data={...};
var token=$('#_id').serializeObject();
var dataWithAntiforgeryToken = $.extend(data,token);

$.ajax(
{
....,
data: dataWithAntiforgeryToken;
}
)
0

I wanted to secure both Ajax and normal request, so here is what I came out with:

First using the excellent blog from haacked.com I Created the ConditionalFilterProvider as described.

Then I created all the classes as described on the blog from codethinked.

On my _layout page I added the piece with the $.ajaxPrefilter as described in the blog... This assures that all my Ajax-callback now send the Antiforgery token through header.

To glue all together I added this piece of code on my global.asax / Application_Start

(c, a) =>
                    (c.HttpContext.Request.IsAjaxRequest() &&
                     !string.Equals(c.HttpContext.Request.HttpMethod, "GET"))
                        ? new AjaxValidateAntiForgeryTokenAttribute()
                        : null,
(c, a) =>
                    (!c.HttpContext.Request.IsAjaxRequest() &&
                     string.Equals(c.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase))
                        ? new ValidateAntiForgeryTokenAttribute()
                        : null

Basically.. inject the attribute to all my Controllers that are not GET.

After that I just had to go to all my (Very few) forms and add the @Html.AntiForgeryToken().

To proof that all worked I just try to dens things with a form without the AntiForgeryToken and get the expected exception. And remove the $.ajaxPrefilter and create Ajax requests and the expected exception was received.

CodeHacker
  • 2,127
  • 1
  • 22
  • 35