Mefhisto1
Mefhisto1

Reputation: 2228

Supplying AntiForgeryToken in a JSON post request

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.

Upvotes: 2

Views: 1903

Answers (2)

Amin K
Amin K

Reputation: 106

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
}

Upvotes: 2

JacobS
JacobS

Reputation: 606

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) 

Upvotes: 1

Related Questions