1

I checked:

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

how can i use AntiForgeryToken with JSON post in mvc 4

http://forums.asp.net/t/1561850.aspx?How+can+i+supply+a+antiforgerytoken+when+posting+JSON+data+using+ajax+

and tried everything mentioned. Sadly, nothing proposed worked.

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

var headers = {};

headers['__RequestVerificationToken'] = token;

var data = serializeData(token);

$.ajax(
{
    cache: false,
    async: false,
    type: 'POST'
    url: url
    data: data,
    dataType: 'json',
    contentType: 'application/json; charset=utf-8',
    headers: headers,
    success: function (result) {
    },
    error: function () {
        e.stopPropagation();
    }
});

function serializeData(token) {   
var data = {
    __RequestVerificationToken: token,
    MyJsonData : JSON.stringify(myFormData),
};

return data;   
}

I always get the exception that the RequestVerificationToken is not present.

However, if I exclude contentType parameter from the ajax call, it successfully verifies the token, but the MyJsonData is null in the controller, and it comes with the exception:

{"The parameter conversion from type 'System.String' to type 'MyJsonData' failed because no type converter can convert between these types."}

I also try to send the token as part of the header of the request, but that also does not work.

Community
  • 1
  • 1
Mefhisto1
  • 1,990
  • 6
  • 28
  • 64
  • 1
    Need to stringify the data yourself if want to send as json. **NEVER* use `async: false` it is a terrible practice and is deprecated. Look at warnings thrown in browser console – charlietfl Mar 25 '16 at 12:17
  • but what's the difference than just using json.stringify? I post the 'data' object, it looks ok when serialized this way – Mefhisto1 Mar 25 '16 at 12:23
  • 1
    You are stringifying the wrong object to send the whole thing as `application/json`. Would be `return JSON.stringify(data)` in function if that's what you expect at server – charlietfl Mar 25 '16 at 12:25
  • my bad didnt provide enough details, it still fails even the way you suggested (token not present) – Mefhisto1 Mar 25 '16 at 13:06
  • I think you are expecting regular POST at server if removing `contentType` works and that your problem is with server code – charlietfl Mar 25 '16 at 13:07
  • can you take a look at the provided edit? How can I bypass this? Properties and the type name are equal on both ends – Mefhisto1 Mar 25 '16 at 13:14
  • Are you calling @Html.AntiForgeryToken in the view to output the token into the DOM? Try passing the data parameter like this: "data: { __RequestVerificationToken: token; }, and remove the "contentType" and "dataType" parameters. – thiag0 Mar 25 '16 at 20:49

2 Answers2

1

I would suggest AJAX Form submit. This library will stringify and send your data as if it's a regular form submit - using ajax. I've used it with validation tokens with no issues.

Options: Full options list here Example:

options = {
    url: "url",
    type: "post",
    success: handler,
    error: handler,
    complete: handler
}

This will submit the form immediately upon calling.

$("#myFormId").ajaxSubmit(options)

This will wait until the form submit button is clicked and use an ajax submit instead.

$("#myFormId").ajaxForm(options) 
JacobS
  • 562
  • 4
  • 10
1

According to This Approach, i think using a custom attribute would be a better solution. so instead of serializing token with data, let this attribute do the job.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public sealed 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"]);
        }
    }

and decorate your controller with

[HttpPost] 
[ValidateJsonAntiForgeryToken]
public ActionResult DoSomething(Foo foo) {
    //Do something
}
Amin K
  • 86
  • 1
  • 9