Enable Antiforgery token using ASP.NET Core and jQuery

I am using jQuery with ASP.NET Core 1.0.1, and I have an Ajax call:

$("#send-message").on("submit", function (event) { event.preventDefault(); var $form = $(this); $.ajax({ url: "api/messages", data: JSON.stringify($form.serializeToJSON()), dataType: "json", headers: { Accept: "application/json", "Content-Type": "application/json" }, type: "post" }) .done(function (data, status, xhr) { }) .fail(function (xhr, status, error) { }); 

To ASP.NET Core Action:

 [HttpPost("messages")] public async Task<IActionResult> Post([FromBody]MessagePostApiModelModel model) { // Send message } 

The form is in general view, and it looks like this:

 <form id="send-question" method="post"> <textarea name="content"></textarea> <button class="button" type="submit">Enviar</button> </form> 

When I submit the form, I get an error message:

 Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The required antiforgery header value "RequestVerificationToken" is not present. 

How to enable ASP.NET Core AntiForgeryToken using jQuery Ajax calls?

UPDATE

I need to add the following asp-controller and asp-action to the form:

 <form asp-controller="QuestionApi" asp-action="Post" id="send-question" method="post"> </form> 

This will create an antiforgery token. And I needed to manually add the token to the jQuery call headers as follows:

  headers: { "Accept": "application/json", "Content-Type": "application/json", "RequestVerificationToken": $form.find("input[name='af_token']").val() }, 

Is there a better way to do this?

How to solve this problem when there is no form, and I only have the A tag, which when clicked causes an Ajax call? Can I generate a common anti-corrosion token on my page to use all ajax calls from this page?

+7
jquery ajax asp.net-core antiforgerytoken
source share
3 answers

The mode777 answer just needs a little extra to do this job (I tried):

 $(document).ajaxSend(function(e, xhr, options) { if (options.type.toUpperCase() == "POST") { var token = $form.find("input[name='af_token']").val(); xhr.setRequestHeader("RequestVerificationToken", token); } }); 

Actually, if you also submit using Ajax, you do not need to use the form at all. Put this in your _layout:

  <span class="AntiForge"> @Html.AntiForgeryToken() </span> 

Then you select the token by adding it to your javascript:

 $(document) .ajaxSend(function (event, jqxhr, settings) { if (settings.type.toUpperCase() != "POST") return; jqxhr.setRequestHeader('RequestVerificationToken', $(".AntiForge" + " input").val()) }) 

@HtmlAntiForgeryToken generates a hidden input field with an antiforgery token, just like when using a form. The above code finds it using the class selector to select the range, then gets the input field inside it to collect the token and add it as a header.

+10
source share

Note. This answer applies to ASP.NET Core 2.0. This may not correspond to older versions.

Here is what I did after I briefly copied the aspnet source code:

 public static class HttpContextExtensions { public static string GetAntiforgeryToken(this HttpContext httpContext) { var antiforgery = (IAntiforgery)httpContext.RequestServices.GetService(typeof(IAntiforgery)); var tokenSet = antiforgery.GetAndStoreTokens(httpContext); string fieldName = tokenSet.FormFieldName; string requestToken = tokenSet.RequestToken; return requestToken; } } 

You can use it in the following form:

 <script> var data = { yourData: "bla", "__RequestVerificationToken": "@Context.GetAntiforgeryToken()" }; $.post("@Url.Action("ActionName")", data); </script> 

You can change the extension method to also return the field name in any form, for example. d fragment JSON.

+3
source share

You can register ajax global event that will add a header to all ajax calls that are not GET:

 $(document).ajaxSend(function(e, xhr, options) { if (options.type.toUpperCase() != "GET") { xhr.setRequestHeader("RequestVerificationToken", token); } }); 
0
source share

All Articles