You need to add the token to the request headers, not to the form. Like this:
if (form.valid()) { var formData = new FormData(form); formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); $.ajax({ type: 'POST', url: '/RX/Upload', data: formData, contentType: 'multipart/form-data', processData: false, headers: { '__RequestVerificationToken': fnGetToken() } }) }
Edit Looking back, as I myself solved this problem, I remember that the standard ValidateAntiForgeryTokenAttribute file looks in the Request.Form object, which is not always populated for an AJAX request. (In your case, the content type multipart/form-data is required to download the file, whereas application/x-www-form-urlencoded is required for the form column for the CSRF token. You set contentType=false , but conflicting content types are required for two operations, which may be part of your problem). So, to check the token on the server, you will need to write a custom attribute for your action method, which checks the token in the request header:
public sealed 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"]); } }
More info (a bit dated) here .
source share