im experiencing a weird problem.
I work with MVC (not web api), so the controller inherits from Controller, not from ApiController.
Im calling a controller action (POST) with ajax, and the action is returning HttpResponseMessage
This is the response i get:
{"readyState":4,"responseText":"StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StringContent, Headers:\r\n{\r\n Location: /\r\n Content-Type: application/json; charset=utf-8\r\n}","status":200,"statusText":"OK"}
However, when ajax receives the data, it fires the fail method.
This is the ajax function:
$.ajax({
url: "someurl",
type: "post",
data: data,
dataType: "json",
contentType: "application/json; charset=utf-8"
}).done(function (data) {
alert(data.responseText);
window.location.href = "redirect to some url";
}).fail(function (data) {
alert("error");<-- this one is called even when i set HttpStatusCode.OK
alert(JSON.stringify(data));
}).always(function () {
});
This is a simplified controller action:
[HttpPost]
[AllowAnonymous]
public HttpResponseMessage Index(HttpRequestMessage request, Login model)
//public HttpResponseMessage Index(Login model) // i get the same with any of these 2
{
HttpResponseMessage response = new HttpResponseMessage();
string message = "";
if (something)
{
response.StatusCode = HttpStatusCode.OK;
FormsAuthentication.SetAuthCookie(model.UserName, true);
currentUser.LastLoginDate = DateTime.Now;
currentUser.FailedPasswordAttemptCount = 0;
ModelRepositories.MobileCommerceRepository.SaveChanges();
}
else
{
message = "User does not exist. The user name or password provided is incorrect.";
response.StatusCode = HttpStatusCode.BadRequest;
}
//response = request.CreateResponse(HttpStatusCode.OK);
string json = JsonSerializer.SerializeToString(message);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
}
If i do the same ajax call to web api controller instead (with the same C# code inside), it fires success. What is the difference ?
Thanks
You cannot use HttpResponseMessage with an MVC action. Web API and MVC are two different frameworks, you can't mix and match pieces of them.
Just putting my answer if anyone is still looking. I agree with previous post as MVC will not return actual content. Instead I used
public async Task<string> GetAjaxCollateralSummary(string id)
{
//your logic
return JsonConvert.SerializeObject(result);
}
and the in my js page I have following code:
$.post(url, { id: '2' })
.success(function (response) {
console.log(response);
var jsondResult = JSON.parse(response);
}
)
.error(function (err) {
console.log("Error while trying to get data from MVC controller ");
console.log(err);
})
I have an ajax call to MVC which returns a partialview. This is all fine until the session ends or the cookie expires. When I make the ajax call it displays the content inside a div that was meant to be for the partialview. How can I detect that my session has expired during the ajax call and redirect properly to a full screen/page
I would recommend encapsulating all your requests into a wrapper element:
public class JsonResponse<T>
{
public JsonResponse()
{
}
public JsonResponse(T Data)
{
this.Data = Data;
}
public T Data { get; set; }
public bool IsValid { get; set; }
public string RedirectTo { get; set; }
}
What model you want to send to your client is in Data.
To get the RedirectTo populated, I use a GlobalAuthorize attribute in the Global.Asax and added a handle for HandleUnauthorizedRequests.
public sealed class GlobalAuthorize : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest
(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new JsonResult
{
Data = new JsonResponse<bool>
{
IsValid = false,
//RedirectTo = FormsAuthentication.LoginUrl
RedirectTo = "/"
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
Additionally, I've encapsulated all my Ajax requests into a single function which checks for the RedirectTo.
function global_getJsonResult(Controller, View, data, successCallback, completeCallback, methodType)
{
if (IsString(Controller)
&& IsString(View)
&& !IsUndefinedOrNull(data))
{
var ajaxData;
var ajaxType;
if (typeof (data) == "string")
{
ajaxData = data;
ajaxType = "application/x-www-form-urlencoded"
}
else
{
ajaxData = JSON.stringify(data);
ajaxType = "application/json; charset=utf-8";
}
var method = 'POST';
if (!IsUndefinedOrNull(methodType))
{
method = methodType;
}
var jqXHR = $.ajax({
url: '/' + Controller + '/' + View,
data: ajaxData,
type: method,
contentType: ajaxType,
success: function(jsonResult)
{
if (!IsUndefinedOrNull(jsonResult)
&& jsonResult.hasOwnProperty("RedirectTo")
&& !IsUndefinedOrNull(jsonResult.RedirectTo)
&& jsonResult.RedirectTo.length > 0)
{
$.fn.notify('error', 'Login Expired', 'You have been inactive for a prolonged period of time, and have been logged out of the system.');
window.setTimeout(function() { window.location = jsonResult.RedirectTo }, 5000);
}
else if (IsFunction(successCallback))
{
successCallback(jsonResult, Controller + '/' + View);
}
},
error: function(jqXHR, textStatus, errorThrown)
{
if (errorThrown != 'abort')
{
$.fn.notify('error', 'AJAX Connection Error', textStatus + ': ' + errorThrown);
}
},
complete: function(jqXHR, textStatus)
{
if (IsFunction(completeCallback))
{
completeCallback(jqXHR, textStatus, Controller + '/' + View);
}
}
});
return jqXHR;
}
}
You could create a timer on the client with javascript that will show a dialog to the user when the session has timed out. You would just set the timer's value to whatever your session time out. Then on ajax request, it will reset the count down as well.
var g_sessionTimer = null;
function uiSessionInit() {
id = "uiTimeout";
timeout = 3600000 * 24; // 1 day timeout
uiSessionSchedulePrompt(id, timeout);
$('body').ajaxStart(function () {
// reset timer on ajax request
uiSessionSchedulePrompt(id, timeout);
});
}
function uiSessionSchedulePrompt(id, timeout) {
if (g_sessionTimer)
clearTimeout(g_sessionTimer);
g_sessionTimer = setTimeout(function () { uiSessionExpiring(id); }, timeout);
}
function uiSessionExpiring(id) {
// create a dialog div and use this to show to the user
var dialog = $('<div id="uiTimeout"></div>').text("Your session with has timed out. Please login again.");
$('body').append(dialog);
$('#uiTimeout').dialog({
autoOpen: true,
modal: true,
title: 'Expired Session',
buttons: {
"OK": function(){
$(this).dialog('close');
}
},
close: uiSessionDialogClose
});
}
function uiSessionDialogClose(){
// take user to sign in location
location = 'http://www.mypage.com';
}
It's been 8 years but I've just encountered a similar problem whereby an Ajax call to load a partial view into a modal, made after the user's authentication cookie had expired, would result in the full login page being loaded into the modal. This is how I got around it.
Firstly, I added a hidden control on my login page. The value isn't strictly required but it makes for more readable markup, I think:
<input id="isLoginPage" type="hidden" value="true" />
Then I modified the Ajax call like this. I'm using jQuery but the same principle will work in plain old Javascript too:
$.ajax({
url: `/mypartialview`,
type: "GET",
success: function (data) {
var $modal = $("#myModal");
$modal.find(".modal-content").html(data);
if ($modal.find("#isLoginPage").length > 0) {
window.location.replace("/");
}
$modal.modal("show");
}
});
This works on the basis that if the user's authentication has expired MVC's default behaviour is to return to the login page, so I "sniff" the view returned by the Ajax call for the isLoginPage hidden input and, if it's found, I know that the login page has been returned so I just redirect the user to the root of the application, which MVC will then redirect to the main login page.
If your application's root allows anonymous access you could replace window.location.replace("/") with the path to your application's login page, e.g. window.location.replace("/account/login").
With this working, I encapsulated the solution in a function to simplify things and avoid repeating myself:
function handleAjaxData($container, data) {
$container.html(data);
if ($container.find("#isLoginPage").length > 0) {
window.location.replace("/");
}
}
Which I can then use in my Ajax call like this:
$.ajax({
url: `/mypartialview`,
type: "GET",
success: function (data) {
var $modal = $("#myModal");
handleAjaxData($modal.find(".modal-content"), data);
$modal.modal("show");
}
});
You could obviously go further and include the Ajax call itself in the function, but in my case that would have involved some complicated callbacks so I didn't bother.
I have used jquery ajax function to submit a form.
The users have to be logged in else they must redirect to a login page.I have used Authorize() attribute for it.
[Authorize]
public ActionResult Creat()
{
....
}
If the user is not login the action return login page to jquery's ajax functions and it is displayed on the same page but I want to redirect the user to login page.
Is there any solution?
Working example: https://github.com/ronnieoverby/mvc-ajax-auth
Important parts:
AjaxAuthorizeAttribute:
using System.Web.Mvc;
namespace MvcApplication1
{
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
if (context.HttpContext.Request.IsAjaxRequest())
{
var urlHelper = new UrlHelper(context.RequestContext);
context.HttpContext.Response.StatusCode = 403;
context.Result = new JsonResult
{
Data = new
{
Error = "NotAuthorized",
LogOnUrl = urlHelper.Action("LogOn", "Account")
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
else
{
base.HandleUnauthorizedRequest(context);
}
}
}
}
Javascript:
$(function () {
$(document).ajaxError(function (e, xhr) {
if (xhr.status == 403) {
var response = $.parseJSON(xhr.responseText);
window.location = response.LogOnUrl;
}
});
});
Use the attribute in a controller:
[AjaxAuthorize]
public ActionResult Secret()
{
return PartialView();
}
Do some ajax:
#Ajax.ActionLink("Get Secret", "Secret", new AjaxOptions { UpdateTargetId = "secretArea", })
<div id="secretArea"></div>
Just a handy addition to #Ronnie's answer
if you want to keep the page url on redirect.
var pathname = window.location.pathname;
if (xhr.status == 403) {
var response = $.parseJSON(xhr.responseText);
window.location = response.LogOnUrl + '?ReturnUrl=' + pathname;
}
As another extension to Ronnie Overby's answer.
His solution doesn't work with webapi, but this is fine because you can use normal Authorize
attribute instead and then handle the 401 status in the ajaxError function as follows.
$(document).ajaxError(function (e, xhr) {
//ajax error event handler that looks for either a 401 (regular authorized) or 403 (AjaxAuthorized custom actionfilter).
if (xhr.status == 403 ||xhr.status == 401) {
//code here
}
});
I am trying to change a value in a table from one view, and then redirect to another view using Flash FSCommand and Json, using the following code:
if (command == "nameClip") {
var url = '<%= Url.Action("Index", "Home") %>';
var clip = [args];
try {
$.post(url, {
MovieName: clip
}, function(data) {
;
}, 'json');
} finally {
// window.location.href = "/Demo/SWF";
}
}
In the controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(SWF movietoplay) {
var oldmovie = (from c in db.SWFs where c.ID == "1" select c).FirstOrDefault();
var data = Request.Form["MovieName"].ToString();
oldmovie.SWFName = data;
db.SubmitChanges();
return RedirectToAction("Show");
}
All works well except Redirect!!
You need to perform the redirect inside the AJAX success callback:
$.post(url, { MovieName: clip }, function(data) {
window.location.href = '/home/show';
}, 'json');
The redirect cannot be performed server side as you are calling this action with AJAX.
Also you indicate in your AJAX call that you are expecting JSON from the server side but you are sending a redirect which is not consistent. You could modify the controller action to simply return the url that the client needs to redirect to using JSON:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(SWF movietoplay)
{
...
return Json(new { redirectTo = Url.Action("show") });
}
and then:
$.post(url, { MovieName: clip }, function(data) {
window.location.href = data.redirectTo;
}, 'json');
I am using the code as below of this post:
First I will fill an array variable with the correct values for the controller action.
Using the code below I think it should be very straightforward by just adding the following line to the JavaScript code:
data["__RequestVerificationToken"] = $('[name=__RequestVerificationToken]').val();
The <%= Html.AntiForgeryToken() %> is at its right place, and the action has a [ValidateAntiForgeryToken]
But my controller action keeps saying: "Invalid forgery token"
What am I doing wrong here?
Code
data["fiscalyear"] = fiscalyear;
data["subgeography"] = $(list).parent().find('input[name=subGeography]').val();
data["territories"] = new Array();
$(items).each(function() {
data["territories"].push($(this).find('input[name=territory]').val());
});
if (url != null) {
$.ajax(
{
dataType: 'JSON',
contentType: 'application/json; charset=utf-8',
url: url,
type: 'POST',
context: document.body,
data: JSON.stringify(data),
success: function() { refresh(); }
});
}
You don't need the ValidationHttpRequestWrapper solution since MVC 4. According to this link.
Put the token in the headers.
Create a filter.
Put the attribute on your method.
Here is my solution:
var token = $('input[name="__RequestVerificationToken"]').val();
var headers = {};
headers['__RequestVerificationToken'] = token;
$.ajax({
type: 'POST',
url: '/MyTestMethod',
contentType: 'application/json; charset=utf-8',
headers: headers,
data: JSON.stringify({
Test: 'test'
}),
dataType: "json",
success: function () {},
error: function (xhr) {}
});
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public 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"]);
}
}
[HttpPost]
[AllowAnonymous]
[ValidateJsonAntiForgeryToken]
public async Task<JsonResult> MyTestMethod(string Test)
{
return Json(true);
}
What is wrong is that the controller action that is supposed to handle this request and which is marked with the [ValidateAntiForgeryToken] expects a parameter called __RequestVerificationToken to be POSTed along with the request.
There's no such parameter POSTed as you are using JSON.stringify(data) which converts your form to its JSON representation and so the exception is thrown.
So I can see two possible solutions here:
Number 1: Use x-www-form-urlencoded instead of JSON for sending your request parameters:
data["__RequestVerificationToken"] = $('[name=__RequestVerificationToken]').val();
data["fiscalyear"] = fiscalyear;
// ... other data if necessary
$.ajax({
url: url,
type: 'POST',
context: document.body,
data: data,
success: function() { refresh(); }
});
Number 2: Separate the request into two parameters:
data["fiscalyear"] = fiscalyear;
// ... other data if necessary
var token = $('[name=__RequestVerificationToken]').val();
$.ajax({
url: url,
type: 'POST',
context: document.body,
data: { __RequestVerificationToken: token, jsonRequest: JSON.stringify(data) },
success: function() { refresh(); }
});
So in all cases you need to POST the __RequestVerificationToken value.
I was just implementing this actual problem in my current project. I did it for all Ajax POSTs that needed an authenticated user.
First off, I decided to hook my jQuery Ajax calls so I do not to repeat myself too often. This JavaScript snippet ensures all ajax (post) calls will add my request validation token to the request. Note: the name __RequestVerificationToken is used by the .NET framework so I can use the standard Anti-CSRF features as shown below.
$(document).ready(function () {
securityToken = $('[name=__RequestVerificationToken]').val();
$('body').bind('ajaxSend', function (elm, xhr, s) {
if (s.type == 'POST' && typeof securityToken != 'undefined') {
if (s.data.length > 0) {
s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
}
else {
s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
}
}
});
});
In your Views where you need the token to be available to the above JavaScript code, just use the common HTML-Helper. You can basically add this code wherever you want. I placed it within a if(Request.IsAuthenticated) statement:
#Html.AntiForgeryToken() // You can provide a string as salt when needed which needs to match the one on the controller
In your controller simply use the standard ASP.NET MVC anti-CSRF mechanism. I did it like this (though I actually used a salt).
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public JsonResult SomeMethod(string param)
{
// Do something
return Json(true);
}
With Firebug or a similar tool you can easily see how your POST requests now have a __RequestVerificationToken parameter appended.
You can set $.ajax 's traditional attribute and set it to true, to send json data as url encoded form. Make sure to set type:'POST'. With this method you can even send arrays and you do not have to use JSON.stringyfy or any changes on server side (e.g. creating custom attributes to sniff header )
I have tried this on ASP.NET MVC3 and jquery 1.7 setup and it's working
following is the code snippet.
var data = { items: [1, 2, 3], someflag: true};
data.__RequestVerificationToken = $(':input[name="__RequestVerificationToken"]').val();
$.ajax({
url: 'Test/FakeAction'
type: 'POST',
data: data
dataType: 'json',
traditional: true,
success: function (data, status, jqxhr) {
// some code after succes
},
error: function () {
// alert the error
}
});
This will match with MVC action with following signature
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult FakeAction(int[] items, bool someflag)
{
}
You won't ever have to validate an AntiForgeryToken when you receive posted JSON.
The reason is that AntiForgeryToken has been created to prevent CSRF. Since you can't post AJAX data to another host and HTML forms can't submit JSON as the request body, you don't have to protect your app against posted JSON.
I have resolved it globally with RequestHeader.
$.ajaxPrefilter(function (options, originalOptions, jqXhr) {
if (options.type.toUpperCase() === "POST") {
// We need to add the verificationToken to all POSTs
if (requestVerificationTokenVariable.length > 0)
jqXhr.setRequestHeader("__RequestVerificationToken", requestVerificationTokenVariable);
}
});
where the requestVerificationTokenVariable is an variable string that contains the token value.
Then all ajax call send the token to the server, but the default ValidateAntiForgeryTokenAttribute get the Request.Form value.
I have writed and added this globalFilter that copy token from header to request.form, than i can use the default ValidateAntiForgeryTokenAttribute:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new GlobalAntiForgeryTokenAttribute(false));
}
public class GlobalAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
private readonly bool autoValidateAllPost;
public GlobalAntiForgeryTokenAttribute(bool autoValidateAllPost)
{
this.autoValidateAllPost = autoValidateAllPost;
}
private const string RequestVerificationTokenKey = "__RequestVerificationToken";
public void OnAuthorization(AuthorizationContext filterContext)
{
var req = filterContext.HttpContext.Request;
if (req.HttpMethod.ToUpperInvariant() == "POST")
{
//gestione per ValidateAntiForgeryToken che gestisce solo il recupero da Request.Form (non disponibile per le chiamate ajax json)
if (req.Form[RequestVerificationTokenKey] == null && req.IsAjaxRequest())
{
var token = req.Headers[RequestVerificationTokenKey];
if (!string.IsNullOrEmpty(token))
{
req.Form.SetReadOnly(false);
req.Form[RequestVerificationTokenKey] = token;
req.Form.SetReadOnly(true);
}
}
if (autoValidateAllPost)
AntiForgery.Validate();
}
}
}
public static class NameValueCollectionExtensions
{
private static readonly PropertyInfo NameObjectCollectionBaseIsReadOnly = typeof(NameObjectCollectionBase).GetProperty("IsReadOnly", BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance);
public static void SetReadOnly(this NameValueCollection source, bool readOnly)
{
NameObjectCollectionBaseIsReadOnly.SetValue(source, readOnly);
}
}
This work for me :)
You can't validate an content of type contentType: 'application/json; charset=utf-8' because your date will be uploaded not in the Form property of the request, but in the InputStream property, and you will never have this Request.Form["__RequestVerificationToken"].
This will be always empty and validation will fail.
I hold the token in my JSON object and I ended up modifying the ValidateAntiForgeryToken class to check the InputStream of the Request object when the post is json. I've written a blog post about it, hopefully you might find it useful.
Check out Dixin's Blog for a great post on doing exactly that.
Also, why not use $.post instead of $.ajax?
Along with the jQuery plugin on that page, you can then do something as simple as:
data = $.appendAntiForgeryToken(data,null);
$.post(url, data, function() { refresh(); }, "json");
AJAX based model posting with AntiForgerytoken can be made bit easier with Newtonsoft.JSON library
Below approach worked for me:
Keep your AJAX post like this:
$.ajax({
dataType: 'JSON',
url: url,
type: 'POST',
context: document.body,
data: {
'__RequestVerificationToken': token,
'model_json': JSON.stringify(data)
};,
success: function() {
refresh();
}
});
Then in your MVC action:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(FormCollection data) {
var model = JsonConvert.DeserializeObject < Order > (data["model_json"]);
return Json(1);
}
Hope this helps :)
I had to be a little shady to validate anti-forgery tokens when posting JSON, but it worked.
//If it's not a GET, and the data they're sending is a string (since we already had a separate solution in place for form-encoded data), then add the verification token to the URL, if it's not already there.
$.ajaxSetup({
beforeSend: function (xhr, options) {
if (options.type && options.type.toLowerCase() !== 'get' && typeof (options.data) === 'string' && options.url.indexOf("?__RequestVerificationToken=") < 0 && options.url.indexOf("&__RequestVerificationToken=") < 0) {
if (options.url.indexOf('?') < 0) {
options.url += '?';
}
else {
options.url += '&';
}
options.url += "__RequestVerificationToken=" + encodeURIComponent($('input[name=__RequestVerificationToken]').val());
}
}
});
But, as a few people already mentioned, the validation only checks the form - not JSON, and not the query string. So, we overrode the attribute's behavior. Re-implementing all of the validation would have been terrible (and probably not secure), so I just overrode the Form property to, if the token were passed in the QueryString, have the built-in validation THINK it was in the Form.
That's a little tricky because the form is read-only, but doable.
if (IsAuth(HttpContext.Current) && !IsGet(HttpContext.Current))
{
//if the token is in the params but not the form, we sneak in our own HttpContext/HttpRequest
if (HttpContext.Current.Request.Params != null && HttpContext.Current.Request.Form != null
&& HttpContext.Current.Request.Params["__RequestVerificationToken"] != null && HttpContext.Current.Request.Form["__RequestVerificationToken"] == null)
{
AntiForgery.Validate(new ValidationHttpContextWrapper(HttpContext.Current), null);
}
else
{
AntiForgery.Validate(new HttpContextWrapper(HttpContext.Current), null);
}
}
//don't validate un-authenticated requests; anyone could do it, anyway
private static bool IsAuth(HttpContext context)
{
return context.User != null && context.User.Identity != null && !string.IsNullOrEmpty(context.User.Identity.Name);
}
//only validate posts because that's what CSRF is for
private static bool IsGet(HttpContext context)
{
return context.Request.HttpMethod.ToUpper() == "GET";
}
...
internal class ValidationHttpContextWrapper : HttpContextBase
{
private HttpContext _context;
private ValidationHttpRequestWrapper _request;
public ValidationHttpContextWrapper(HttpContext context)
: base()
{
_context = context;
_request = new ValidationHttpRequestWrapper(context.Request);
}
public override HttpRequestBase Request { get { return _request; } }
public override IPrincipal User
{
get { return _context.User; }
set { _context.User = value; }
}
}
internal class ValidationHttpRequestWrapper : HttpRequestBase
{
private HttpRequest _request;
private System.Collections.Specialized.NameValueCollection _form;
public ValidationHttpRequestWrapper(HttpRequest request)
: base()
{
_request = request;
_form = new System.Collections.Specialized.NameValueCollection(request.Form);
_form.Add("__RequestVerificationToken", request.Params["__RequestVerificationToken"]);
}
public override System.Collections.Specialized.NameValueCollection Form { get { return _form; } }
public override string ApplicationPath { get { return _request.ApplicationPath; } }
public override HttpCookieCollection Cookies { get { return _request.Cookies; } }
}
There's some other stuff that's different about our solution (specifically, we're using an HttpModule so we don't have to add the attribute to every single POST) that I left out in favor of brevity. I can add it if necessary.
Unfortunately for me, the other answers rely on some request formatting handled by jquery, and none of them worked when setting the payload directly. (To be fair, putting it in the header would have worked, but I did not want to go that route.)
To accomplish this in the beforeSend function, the following works. $.params() transforms the object into the standard form / url-encoded format.
I had tried all sorts of variations of stringifying json with the token and none of them worked.
$.ajax({
...other params...,
beforeSend: function(jqXHR, settings){
var token = ''; //get token
data = {
'__RequestVerificationToken' : token,
'otherData': 'value'
};
settings.data = $.param(data);
}
});
```
You should place AntiForgeryToken in a form tag:
#using (Html.BeginForm(actionName:"", controllerName:"",routeValues:null, method: FormMethod.Get, htmlAttributes: new { #class="form-validator" }))
{
#Html.AntiForgeryToken();
}
Then in javascript modify the following code to be
var DataToSend = [];
DataToSend.push(JSON.stringify(data), $('form.form-validator').serialize());
$.ajax({
dataType: 'JSON',
contentType: 'application/json; charset=utf-8',
url: url,
type: 'POST',
context: document.body,
data: DataToSend,
success: function() {
refresh();
}
});
Then you should be able to validate the request using ActionResult annotations
[ValidateAntiForgeryToken]
[HttpPost]
I hope this helps.