Answered by:
__requestverificationtoken error in javascript vue, MVC 5

Question
-
User955080112 posted
I am attempting to use the ValidateAntiForgeryToken to prevent cross site forgery on my application. Keep getting the error
the required anti-forgery form field __requestverificationtoken is not present
Been seeing a lot of chatter on this but I have been unable to come up with a solution.
The code:
in my Index.cshtml, setting the AntiForgeryToken:
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
@Html.AntiForgeryToken()
}in my ajax.utilities post method, setting the token:
var post = function (options, callbacks) {
// set default POST options
options.type = "POST";
options.dataType = options.dataType !== undefined ? options.dataType : "json";
options.contentType = options.contentType !== undefined ? options.contentType : "application/json; charset=utf-8";
var form = $('#__AjaxAntiForgeryForm');
var token = $('input[name="__RequestVerificationToken"]', form).val();if (options.data !== undefined && options.data !== null && !isJson(options.data)) {
options.data = $.extend({ __RequestVerificationToken: token }, options.data);
options.data = JSON.stringify(options.data);
}return sendRequest(options, callbacks);
};my jquery sets the header properly i.e. "X-Requested-With":
if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
headers[ "X-Requested-With" ] = "XMLHttpRequest";
}finally in my controller I designate the HttpPost and ValidateAntiForgery attributes:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateComposite(string name, int compositeTypeId, int componentTypeId, DateTime inceptionDate){
return DispatchCommandWithJsonReturn(new CompositeCommands.CreateComposite(name, compositeTypeId, componentTypeId));
}I still get the error the required anti-forgery form field __requestverificationtoken is not present
Using MVC 5, I don't know if that is relevant
Any ideas what is wrong?
Monday, September 21, 2020 1:42 PM
Answers
-
User-821857111 posted
The ValidateAntiForgery attribute expects the token to be present as a form field. You are sending the post data as JSON so it's sent as a string in the request body, not as name/value pairs. Therefore the token value cannot be found by the model binder.
You could send the request without using JSON, or you could send two parameters - the token value and the rest as JSON:
options.data: { __RequestVerificationToken: token , json: JSON.stringify(options.data)};
There are some other suggestions here: https://stackoverflow.com/questions/2906754/how-can-i-supply-an-antiforgerytoken-when-posting-json-data-using-ajax
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, September 22, 2020 6:18 AM -
User-1330468790 posted
Hi mndotnetdev,
There is another option that you could manually post the data as a form within the header to be "headers: { 'Content-Type': 'application/x-www-form-urlencoded' }" and 'contentType : "application/x-www-form-urlencoded; charset=utf-8"'
You could refer to below codes to see how it works.
cshtml:
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" })) { @Html.AntiForgeryToken() @Html.TextBoxFor(model => model.name) @Html.TextBoxFor(model => model.componentTypeId) @Html.TextBoxFor(model => model.compositeTypeId) @Html.TextBoxFor(model => model.inceptionDate) <input type="submit" value="Submit" /> } <input type="button" onclick="sendPost()" value="Send Post" /> @section scripts { <script> var post = function (options, callbacks) { // set default POST options options.type = "POST"; options.dataType = options.dataType !== undefined ? options.dataType : "json"; options.contentType = options.contentType !== undefined ? options.contentType : "application/x-www-form-urlencoded; charset=utf-8"; return sendRequest(options, callbacks); }; var sendRequest = function (options, callbacks) { console.log(options); $.ajax(options).done(function (data) { callbacks(data)}); } function sendPost() { var form = $('#__AjaxAntiForgeryForm'); post({ url: "CreateComposite", headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, data: form.serialize() }, function (data) { alert(JSON.stringify(data)); }) } function isJson(str) { try { JSON.parse(str); } catch (e) { return false; } return true; } </script> }
Controller:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult CreateComposite(string name, int compositeTypeId, int componentTypeId, DateTime inceptionDate) { return Json(new { name, compositeTypeId, componentTypeId, inceptionDate }); }
model:
public class AboutViewModel { public string name { get; set; } public int compositeTypeId { get; set; } public int componentTypeId { get; set; } public DateTime inceptionDate { get; set; } }
Demo:
Hope this can help you.
Best regards,
Sean
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, September 22, 2020 8:02 AM
All replies
-
User-821857111 posted
The ValidateAntiForgery attribute expects the token to be present as a form field. You are sending the post data as JSON so it's sent as a string in the request body, not as name/value pairs. Therefore the token value cannot be found by the model binder.
You could send the request without using JSON, or you could send two parameters - the token value and the rest as JSON:
options.data: { __RequestVerificationToken: token , json: JSON.stringify(options.data)};
There are some other suggestions here: https://stackoverflow.com/questions/2906754/how-can-i-supply-an-antiforgerytoken-when-posting-json-data-using-ajax
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, September 22, 2020 6:18 AM -
User-1330468790 posted
Hi mndotnetdev,
There is another option that you could manually post the data as a form within the header to be "headers: { 'Content-Type': 'application/x-www-form-urlencoded' }" and 'contentType : "application/x-www-form-urlencoded; charset=utf-8"'
You could refer to below codes to see how it works.
cshtml:
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" })) { @Html.AntiForgeryToken() @Html.TextBoxFor(model => model.name) @Html.TextBoxFor(model => model.componentTypeId) @Html.TextBoxFor(model => model.compositeTypeId) @Html.TextBoxFor(model => model.inceptionDate) <input type="submit" value="Submit" /> } <input type="button" onclick="sendPost()" value="Send Post" /> @section scripts { <script> var post = function (options, callbacks) { // set default POST options options.type = "POST"; options.dataType = options.dataType !== undefined ? options.dataType : "json"; options.contentType = options.contentType !== undefined ? options.contentType : "application/x-www-form-urlencoded; charset=utf-8"; return sendRequest(options, callbacks); }; var sendRequest = function (options, callbacks) { console.log(options); $.ajax(options).done(function (data) { callbacks(data)}); } function sendPost() { var form = $('#__AjaxAntiForgeryForm'); post({ url: "CreateComposite", headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, data: form.serialize() }, function (data) { alert(JSON.stringify(data)); }) } function isJson(str) { try { JSON.parse(str); } catch (e) { return false; } return true; } </script> }
Controller:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult CreateComposite(string name, int compositeTypeId, int componentTypeId, DateTime inceptionDate) { return Json(new { name, compositeTypeId, componentTypeId, inceptionDate }); }
model:
public class AboutViewModel { public string name { get; set; } public int compositeTypeId { get; set; } public int componentTypeId { get; set; } public DateTime inceptionDate { get; set; } }
Demo:
Hope this can help you.
Best regards,
Sean
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, September 22, 2020 8:02 AM