![](/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.