0
votes

I do not know how I use the AntiForgeryToken in ajax.

I found the following answers on SO but they're not working for me:

This is my code Html:

@using (Html.BeginForm())
                    {
                        @Html.AntiForgeryToken()
                        @Html.TextBoxFor(model => model.UserName, new { @class = "form-control", id = "UserName", placeholder = @CMS.Resources.Resource.UserName })
                        @Html.PasswordFor(model => model.Password, new { @class = "form-control", id = "Password", placeholder = @CMS.Resources.Resource.Password })

                        <button id="LoginButton" class="k-button" type="submit">@CMS.Resources.Resource.Signin</button>
                    }

JavaScript:

$('#LoginButton').click(function (e) {
        if ($('form').valid()) {

            var data = { UserName: $('#UserName').val(), Password: $('#Password').val() };
            var token = $('[name=__RequestVerificationToken]').val();
            var headers = {};
            headers["__RequestVerificationToken"] = token;

            $.ajax({
                type: 'POST',
                traditional: true,
                data: JSON.stringify(data),
                cache: false,
                headers: headers,
                dataType: 'json',
                url: '@Url.Action("LoginPanel", "Account")',
                contentType: "application/json; charset=utf-8",
                success: function (status) {
                },
                error: function (status) {
                    alert(status);
                }
            });
        }
        e.preventDefault();
    });

Controller:

        [HttpPost, ValidateAntiForgeryToken]
    public JsonResult LoginPanel(LoginModel model)
    {
        LoginStatus status = new LoginStatus();
        if (HttpContext.Request.IsAjaxRequest())
        {
            if (ModelState.IsValid)
            {
                ....
            }
        }
        return Json(status, JsonRequestBehavior.AllowGet);
    }

And other modes of JavaScript code that tried. By placing the value __RequestVerificationToken in the header, or in data. The error is always the same:

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

Thank.

2

2 Answers

1
votes

This works for me.

Provide the right namespace and references and save the code below to something like ValidateJsonAntiForgeryTokenAttribute.cs And in the controller action that accept AJAX POST request just decorate it w/ that attribute like so:

[HttpPost]
[ValidateJsonAntiForgeryToken]
public Task<ActionResult> HandleAjaxCall(string blah) {
}

And in your client side script just include @Html.AntiForgeryToken() somewhere. And when doing the AJAX call pass the value from that hidden field into the AJAX Request header... The example below is using angular, so adjust to whatever client side thing you are using...

var details = angular.toJson(...);
var antiForgeryToken = $('input[name="__RequestVerificationToken"]').val();
     return $http({
            method: 'POST',
            headers: { '__RequestVerificationToken': antiForgeryToken },
            url: '/ControllerName/HandleAjaxCall',
            data: details
     });

The ValidateJsonAntiForgeryTokenAttribute.cs file content:

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
    {
       public void OnAuthorization(AuthorizationContext filterContext)
        {
            var request = filterContext.HttpContext.Request;
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            var httpContext = new JsonAntiForgeryHttpContextWrapper(HttpContext.Current);

            try
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
                var cookieValue = antiForgeryCookie != null
                       ? antiForgeryCookie.Value
                       : null;
                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
            }
            catch (HttpAntiForgeryException ex)
            {
                //Append where the request url.
                var msg = string.Format("{0} from {1}", ex.Message, httpContext.Request.Url);
                throw new HttpAntiForgeryException(msg);
            }
        }

        private class JsonAntiForgeryHttpContextWrapper : HttpContextWrapper
        {
            readonly HttpRequestBase _request;
            public JsonAntiForgeryHttpContextWrapper(HttpContext httpContext)
                : base(httpContext)
            {
                _request = new JsonAntiForgeryHttpRequestWrapper(httpContext.Request);
            }

            public override HttpRequestBase Request
            {
                get
                {
                    return _request;
                }
            }
        }

        private class JsonAntiForgeryHttpRequestWrapper : HttpRequestWrapper
        {
            readonly NameValueCollection _form;

            public JsonAntiForgeryHttpRequestWrapper(HttpRequest request)
                : base(request)
            {
                _form = new NameValueCollection(request.Form);
                if (request.Headers["__RequestVerificationToken"] != null)
                {
                    _form["__RequestVerificationToken"] = request.Headers["__RequestVerificationToken"];
                }
            }

            public override NameValueCollection Form
            {
                get
                {
                    return _form;
                }
            }
        }
    }
-1
votes

Simply , You can make an Ajax call (a post) to the server,

Sample Ajax Call:

<script>
function SendData() {
    var token = $("[name='__RequestVerificationToken']").val();
    var options = {
        url: '@Url.Action("Create","Car")',
        type: "post",
        data: {
            __RequestVerificationToken: token,
            regNumber: $("#regNumber").val(),
            make: $("#make").val(),
            model: $("#model").val()
        }
    };
    $.ajax(options);
}

just simple, try it...