0

I am using MVC 5 with jQuery and am having difficulties with posting the anti forgery token using Ajax. i have looked on SO at various fixes, but nothing appears to work.

I have the following code within my view.

@using (Html.BeginForm("None", "None", FormMethod.Post, new { @id = "js-form" }))
{
    @Html.AntiForgeryToken()
    ....
    other code  
    ....
    <button class="button-primary button expand js-button-search" type="button">Search</button>
}

Then using jQuery I have added an event handler to the button above by selecting the element via the class: js-button-search. The main Ajax call is as per below

$.ajax({
        url: url,
        method: 'POST',
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(_self.JsonData),
        success: function (result) {
            // Success code
        },
        error: function (jqXHR, textStatus, errorThrown) {
            // Failure code
        }
    });

Where my confusion is, is around the data parameter. I have an object which is populated on demand that contains a large amount of elements that can be used for searching.

The object takes the form of (shortened as we current have over 40 search fields):

_self.JsonData = { "searchData": {"DocIdFrom" : "426737", "DocIdTo" : "753675", "DocIdTypeSearch" : "between", "DocDateFrom" : "06/02/2017", "DocDateTo" : "", "DocDateTypeSearch" : "greater than", .....
       etc...  
}}

As you can see, the data is parsed using JSON.stringify. All of this work as long as the [ValidateAntiForgeryToken] attribute is commented out on the controller function.

Controller as follows:

[HttpPost]
//[ValidateAntiForgeryToken]
public JsonResult GetSearchResultsJson(SearchCriteria searchCriteria, int? page) 
{
    // code in here
}

When I uncomment the anti forgery attribute, the page stops working.

Now i know about the need to pass the token across with the post and have tried the following without success:

how-can-i-supply-an-antiforgerytoken-when-posting-json-data-using-ajax asp-net-mvc-5-ajax-request-on-edit-page-error-requestverificationtoken-is-not

The main difference between what I have appears to be a complex object, but i think that is a red herring as Stringify converts the object into a string.

Sorry, forgot to add. Fiddler return the following message when the [ValidateAntiForgeryToken] is enabled

[Fiddler] ReadResponse() failed: The server did not return a complete response for this request. Server returned 0 bytes. 
Community
  • 1
  • 1
gilesrpa
  • 969
  • 1
  • 12
  • 35
  • Still working on this. I have added the token within the header of the ajax call and Chrome reports the following message: "Unexpected token < in JSON at position 4" – gilesrpa Feb 06 '17 at 14:51
  • I cannot add the code with any formatting, here is the basis of it: get_searchInputs: function () { this.JsonData = { "searchData": { "docIdFrom": docSearch.elem.inputs.txtDocIdFrom.val(), "docIdTo": docSearch.elem.inputs.txtDocIdTo.val(), "ticketSearchTextTo": docSearch.elem.inputs.searchTextTo.val(), etc.... – gilesrpa Feb 06 '17 at 15:28
  • Now i have tried the following still with no success. https://weblogs.asp.net/dixin/anti-forgery-request-recipes-for-asp-net-mvc-and-ajax – gilesrpa Feb 06 '17 at 15:59
  • Did you try this?: http://stackoverflow.com/questions/16793516/anti-forgery-form-field-requestverificationtoken-is-not-present-when-using-j/29745788 – Ben Osborne Feb 06 '17 at 16:47
  • Why are you stringifying the data? Just add the token in your object - `var data = { DocIdFrom : '426737, DocIdTo : '753675', ..... ,__RequestVerificationToken: $('[name=__RequestVerificationToken]').val() }` and use `data: data,` and delete the `contentType` option. –  Feb 06 '17 at 23:19

2 Answers2

0

I would like to thank Stephen Muecke for providing the solution to the problem.

Firstly my Json object was converted to the following:

var data = { "__RequestVerificationToken":$('[name=__RequestVerificationToken]').val(),
             "searchData":
             {
                 "DocIdFrom" : "426737", 
                 "DocIdTo" : "753675",
                 ..............
                 etc
             }
           }

Then, I removed the contentType parameter from the Ajax call and stopped stingifying the Json data.

This has had the desired effect and now i can call the MVC controller using the [ValidateAntiForgeryToken] attribute.

gilesrpa
  • 969
  • 1
  • 12
  • 35
0

You might pass RequestVerificationToken (AntiForgeryToken) on Ajax call by using one of the methods below:

Method I: When using serialize() or FormData() methods, it is not necessary to add the token to the data parameters separately (it will be included id the formdata parameter):

//Send the values of all form controls within the <form> tags including the token:
var formdata = $('#frmCreate').serialize();
//or
var formdata = new FormData($('#frmCreate').get(0));

Method II:

var token = $('[name=__RequestVerificationToken]').val();
$.post(url, { comment: comment, IssueID: postId, __RequestVerificationToken: token }, 
    function (data) { … })

Then you can use the Controller as shown below:

[HttpPost] 
[ValidateAntiForgeryToken]
public JsonResult AddComment(string comment, int IssueID){
    //...
}
Murat Yıldız
  • 11,299
  • 6
  • 63
  • 63