![](/img/trans.png)
[英]asp.net mvc “The required anti-forgery form field”__RequestVerificationToken“ is not present.”
[英]Posting a JSON model to ASP.Net MVC3 with Anti-forgery token
因此,我一直在用这种方法把头撞在墙上,而我找不到任何好的来源。 也许我忘记了模型绑定东西在MVC3中是如何工作的,但这是我想要做的:我有一些与Knockout绑定在一起的编辑器来处理模型的编辑。 该模型没有太多内容:
public class SetupTemplate
{
public int Id { get; set; }
public string Name { get; set; }
public string Template { get; set; }
}
我尝试调用的动作的签名是:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateTemplate(SetupTemplate template)
从这里的另一个问题中,我获得了这个非常有用的代码片段以获取防伪令牌:
window.addAntiForgeryToken = function(data) {
data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
return data;
};
这一切与我一起尝试通过ajax发布更新:
payload = window.addAntiForgeryToken(ko.mapping.toJS(self.data));
$.ajax({
type: "post",
url: endpoint,
data: payload,
success: function(data) {
//Handle success
}});
这导致了Chrome开发者工具的表单数据部分
Id:1
Name:Greeting
Template: [Template Text]
__RequestVerificationToken: [The really long anti-forgery token]
提取了防伪令牌,但是我的模型为null。 我看到的大多数示例都只使用传递的单个参数,而不是模型。
我确定我缺少明显的东西,对它可能有什么见解?
编辑:响应@Mark,更改对此的调用:
$.ajax({
type: "post",
dataType: "json",
contentType: 'application/json',
url: endpoint,
data: JSON.stringify(payload),
success: function(data) {
//Do some stuff
}});
导致以下请求有效负载:
{"Id":1,"Name":"Greeting","Template":"...","__RequestVerificationToken":"..."}:
并且服务器未提取防伪令牌。 尝试使用$.ajax()
的contentType
参数是否有此方法。
映射不适用于作为模板的参数,因为它与具有相同名称(轴承大小写)的属性之一发生冲突。 如果您使用模板以外的其他任何东西,则对于该控制器参数将非常有效。
有一个如此详细的链接解释细节,我现在不容易找到它。
public class SetupTemplate
{
public int Id { get; set; }
public string Name { get; set; }
public string Template { get; set; }
}
这是我的解决方案。 定义一个jQuery函数,如下所示:
(function ($) {
$.getAntiForgeryToken = function () {
return $('input[name="__RequestVerificationToken"]').val();
};
// (!) use ValidateJsonAntiForgeryToken attribute in your controller
$.ajaxJsonAntiforgery = function (settings) {
var headers = {};
headers['__RequestVerificationToken'] = $.getAntiForgeryToken();
settings.dataType = 'json';
settings.contentType = 'application/json; charset=utf-8';
settings.type = 'POST';
settings.cache = false;
settings.headers = headers;
return $.ajax(settings);
};
})(jQuery);
它只是将您的验证令牌放在标题中。 您还需要过滤器属性来检查您的防伪令牌。 这里是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
namespace MyProject.Web.Infrastructure.Filters
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
AllowMultiple = false, Inherited = true)]
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"]);
}
}
}
在您的控制器中,这非常简单,只需用新属性(ValidateJsonAntiForgeryToken)对其进行标记:
[Authorize, HttpPost, ValidateJsonAntiForgeryToken]
public ActionResult Index(MyViewModel viewModel)
在客户端:
$.ajaxJsonAntiforgery({
data: dataToSave,
success: function() { alert("success"); },
error: function () { alert("error"); }
});
这个对我有用。 请享用!
您可以尝试使用JSON.stringify
吗?
$.ajax({
type: "post",
url: endpoint,
data: JSON.stringify(payload),
success: function(data) {
//Handle success
}
});
@Mark因引导我走上正确的道路而获得称赞,并指出了一些链接,这些链接现在使我可以相当透明地处理防伪令牌。 但是,解决问题的方法正在改变:
public ActionResult UpdateTemplate(SetupTemplate template)
至:
public ActionResult UpdateTemplate(SetupTemplate model)
现在,它可以正确地填充值。 我真的很想知道为什么可以解决这个问题,但是现在,它可以工作了。
实际上,以下内容对我来说很复杂。
var application = {
Criteria: {
ReferenceNumber: $("input[name='Criteria.ReferenceNumber'").val()
},
AppliedVia: "Office"
};
// get the next step
$.ajax({
url: form.attr("action"),
dataType: "html",
type: "POST",
data: {
__RequestVerificationToken: $("input[name=__RequestVerificationToken]").val(),
application: application
},
}
但是,需要注意的一件事是要确保data
剩余的application
应该是您的方法/操作中的实际参数名称。 从MVC 5(.NET Core之前的版本)开始运行
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.