我有一个具有两种操作方法的控制器。两者都用[ValidateAntiForgeryToken()]
注释,并且@Html.AntiForgeryToken()
包含在相应的视图中。现在,成功调用以下方法之一(GetVendorOrders
:其结果绑定到剑道网格),另一个方法(MakeVendorPayment
)引发异常"The required anti-forgery form field __RequestVerificationToken is not present" even when both are provided with __RequestVerificationToken value.
我尝试了以下3种方法:
在AJAX的headers参数中传递令牌,例如:
headers: { '__RequestVerificationToken': token }
在AJAX的data参数中传递令牌,例如:
data: JSON.stringify({ vendorId: vId, orderIds: oIds, __RequestVerificationToken: token })
附加令牌值并将其传递给AJAX,
data.__RequestVerificationToken = token;
-以下是这些操作方法:
[HttpPost]
[ValidateAntiForgeryToken()]
public virtual ActionResult GetVendorOrders(DataSourceRequest command, VendorPaymentSearchModel model)
{
var orders = _orderService.SearchOrders(vendorId: model.VendorId, createdFromUtc: model.StartDate, createdToUtc: model.EndDate);
var gridModel = new DataSourceResult
{
Data = orders.Select(x =>
{
return new OrderModel
{
CustomOrderNumber = x.CustomOrderNumber,
CustomerFullName = x.CustomerFullName,
CustomerEmail = x.CustomerEmail,
OrderTotal = x.OrderTotal,
Commission = x.Commission,
VendorPayment = x.OrderTotal - x.Commission
};
}),
};
return Json(gridModel);
}
[HttpPost]
[ValidateAntiForgeryToken()]
public virtual ActionResult MakeVendorPayment(int vendorId, string[] orderIds)
{
foreach (var orderId in orderIds)
{
var order = _orderService.GetOrderById(Convert.ToInt32(orderId));
var vendorPayment = new VendorPayment()
{
VendorId = vendorId,
OrderId = Convert.ToInt32(orderId),
OrderTotal = order.OrderTotal,
Commission = order.Commission,
Payment = order.OrderTotal - order.Commission
};
_vendorPaymentService.InsertVendorPayment(vendorPayment);
}
return Json(new { Result = true });
}
`//Following are Javascript functions:
//This Call Successful
$(document).ready(function () {
$("#orders-grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: {
url: "@Html.Raw(Url.Action("GetVendorOrders", "Vendor"))",
type: "POST",
dataType: "json",
data: additionalData
}
},
},
dataBound: onDataBound,
columns: [
{
field: "Id",
field: "Id",
width: 50
},
{
field: "CustomOrderNumber",
title: "Order #",
width: 80
},
{
field: "OrderStatus",
title: "Order Status",
width: 100
},
{
field: "OrderTotal",
title: "Order Total",
width: 100
},
{
field: "Commission",
title: "Commission",
width: 100
},
{
field: "VendorPayment",
title: "VendorPayment",
width: 100
}
]
});`
//This results into error: The required anti-forgery form field "__RequestVerificationToken" is not present.
//Commented parts are the other ways that are tried.
$('#vendor-payment').click(function (e) {
e.preventDefault();
var orderIds = [];
var data = $("#orders-grid").data("kendoGrid").dataSource._data;
for (i = 0; i < data.length; i++) {
orderIds.push(data[i].CustomOrderNumber);
}
//var token = $('input[name=__RequestVerificationToken]').val();
$.ajax({
url: '@Url.Action("MakeVendorPayment", "Vendor")',
type: 'POST',
dataType: 'json',
//cache: false,
//headers: { '__RequestVerificationToken': token },
//data: addAntiForgeryToken({ vendorId: vId, orderIds: oIds }),
data: JSON.stringify({ vendorId: vId, orderIds: oIds, __RequestVerificationToken: token })
contentType: 'application/json; charset=utf-8',
success: function (result) {
console.log(result);
var grid = $("#orders-grid").data("kendoGrid");
grid.dataSource.read();
},
error: function (objAjaxRequest, strError) {
var respText = objAjaxRequest.responseText;
console.log(respText);
}
});
});
function addAntiForgeryToken(data) {
if (!data) {
data = {};
}
var token = $('input[name=__RequestVerificationToken]');
if (token.length) {
data.__RequestVerificationToken = token.val();
}
return data;
};
});
令我感到惊讶的是,绑定网格的函数(调用GetVendorOrders)成功,但是单击按钮(调用MakeVendorPayment)引发错误:所需的防伪表单字段“ __RequestVerificationToken”不存在。
答案 0 :(得分:0)
最后,在进行了更多研究之后,我得到了解决方案。
我只需要删除AJAX调用中的 contentType
选项,因此它使用默认的 'application/x-www-form-urlencoded; charset=UTF-8'
并还删除了 JSON.stringify( )。
更改的AJAX调用如下:
$.ajax({
url: '@Url.Action("MakeVendorPayment", "Vendor")',
type: 'POST',
dataType: 'json',
data: { vendorId: vId, orderIds: oIds, __RequestVerificationToken: token },
success: function (result) {
console.log(result);
var grid = $("#orders-grid").data("kendoGrid");
grid.dataSource.read();
},
error: function (objAjaxRequest, strError) {
var respText = objAjaxRequest.responseText;
console.log(respText);
}
});
参考:The required anti-forgery form field “__RequestVerificationToken” is not present in ajax call
答案 1 :(得分:0)
由于您使用的是剑道,所以您还可以使用速记kendo.antiForgeryTokens()来简化您的工作,例如
postData('@Url.Action("MakeVendorPayment", "Vendor")', { vendorId: vId, orderIds: oIds });
...
postData: (url, data) => {
$.ajax({
method: "POST",
url: url,
data: $.extend(data, kendo.antiForgeryTokens())
}).done(() => {
viewModel.items.read();
}).fail((e) => {
error_handler(e);
});
}