Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AJAX Posting ValidateAntiForgeryToken without Form to MVC Action Method

Tags:

I've been looking at examples of how to do this on SO and as far as I can tell I've tried all the examples I can find with no success so far. I've tried altering some of the implementations to my scenario but this has thus far failed as well.

I have this on my page in _layout.cshtml so I always have a token available:

<form id="__AjaxAntiForgeryForm" action="#" method="post"> @Html.AntiForgeryToken()</form> 

I also have this method in my JavaScript utils file:

AddAntiForgeryToken = function (data) {     data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();     return data; }; 

This is all working as expected and I get an anti forgery token. My actual posting code is:

myPage.saveData = function() {     var saveUrl = '/exercises/PostData';      var myData = JSON.stringify(myPage.contextsArrays);      $.ajax({         type: 'POST',         async: false,         url: saveUrl,         data: AddAntiForgeryToken({ myResults: myData }),         success: function () {             alert('saved');         },         dataType: 'json',         contentType: "application/json; charset=utf-8"     }); }; 

My action method looks like this:

    [HttpPost, ValidateAntiForgeryToken, JsonExceptionFilter]     public JsonResult PostData(List<ResultsDc> myResults)     {         return Json(_apiClient.SubmitResults(myResults));     } 

I've been testing this with the various implementations I've been trying and the response is always:

{"errorMessage":"The required anti-forgery form field \"__RequestVerificationToken\" is not present."} 

I'm not posting a form it's just an array of data but checking the data that actually gets posted the Json doesn't look right (it's all encoded) but the __RequestVerificationToken parameter name is there and the token value is also present.

I'm pretty confused by all this at the moment and cannot find the correct way to send the token so that my MVC action is invoked. If I remove the ValidateAntiForgeryToken attribute and have JSON.stringify(myPage.contextsArrays); as the data the json looks correct (unencoded) and it maps fine.

How do I get this token posted properly without a form?

like image 412
Jammer Avatar asked Jul 25 '13 12:07

Jammer


People also ask

What is the use of ValidateAntiForgeryToken in MVC?

The basic purpose of ValidateAntiForgeryToken attribute is to prevent cross-site request forgery attacks. A cross-site request forgery is an attack in which a harmful script element, malicious command, or code is sent from the browser of a trusted user.

How can make Ajax request with AntiForgeryToken in MVC?

The URL for the jQuery AJAX call is set to the Controller's action method i.e. /Home/AjaxMethod. The value of the AntiForgery Token and value of the TextBox is passed as parameter and the returned response is displayed using JavaScript Alert Message Box.

What is the use of HTML AntiForgeryToken ()?

AntiForgeryToken()Generates a hidden form field (anti-forgery token) that is validated when the form is submitted.

What does AntiForgery validate do?

Validates that input data from an HTML form field comes from the user who submitted the data. Validates that input data from an HTML form field comes from the user who submitted the data.


2 Answers

Cardboard developer strikes again.

All I had to do was remove:

contentType: "application/json; charset=utf-8" 

And by doing that (which changes the kind of post request being made), to get the Json content of the actual data property to bind correctly to your T model type DO NOT JSON.stringify() the data.

like image 78
Jammer Avatar answered Sep 21 '22 08:09

Jammer


(NOTE: I know this isn't all that much different than what is already here)

I realize this has already been answered, but I've done this quite a bit and will add my answer to the pile. I have no Forms in my site, so I had to come up with ways to handle this. A lot of research here on stackoverflow and some blogs finally gave me the info I needed.

First, here's my code at the top of my "master" page (MVC Razor):

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" })) {     @Html.AntiForgeryToken() } 

Then, in all ajax calls (jQuery), I start like this:

var token = $("#__AjaxAntiForgeryForm input").val(); var dataObject = {   __RequestVerificationToken: token,   myData: "whatever" };  $.ajax({   url: '@Url.Action("action", "controller")',   type: 'POST',   dataType: 'json',   data: dataObject,   error: function (jqXHR, textStatus, errorThrown) {     console.log("ERROR!");   },   success: function (data) {     //whatever   } }); 

Finally, in the Controller side of things, this works fine:

public class controllerController : Controller {     [HttpPost]     [ValidateAntiForgeryToken]     public JsonResult action (myModel myData)     {         return Json(new { Success = "true" }, JsonRequestBehavior.DenyGet);     } } 

Hopefully this would help others in the same boat.

like image 27
ESDictor Avatar answered Sep 21 '22 08:09

ESDictor