If using MVC 5 read this solution!
I know the question specifically called for MVC 3, but I stumbled upon this page with MVC 5 and wanted to post a solution for anyone else in my situation. I tried the above solutions, but they did not work for me, the Action Filter was never reached and I couldn't figure out why. I am using version 5 in my project and ended up with the following action filter:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;
namespace SydHeller.Filters
{
public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
if (clientToken == null)
{
throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
}
string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
if (serverToken == null)
{
throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
}
System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
}
private const string KEY_NAME = "__RequestVerificationToken";
}
}
-- Make note of the using System.Web.Mvc
and using System.Web.Mvc.Filters
, not the http
libraries (I think that is one of the things that changed with MVC v5. --
Then just apply the filter [ValidateJSONAntiForgeryHeader]
to your action (or controller) and it should get called correctly.
In my layout page right above </body>
I have @AntiForgery.GetHtml();
Finally, in my Razor page, I do the ajax call as follows:
var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();
$.ajax({
type: "POST",
url: serviceURL,
contentType: "application/json; charset=utf-8",
dataType: "json",
data: requestData,
headers: {
"__RequestVerificationToken": formForgeryToken
},
success: crimeDataSuccessFunc,
error: crimeDataErrorFunc
});