c# - 使用 Ajax 和 Html.AntiForgeryToken() 时,所需的防伪表单字段“__RequestVerificationToken”不存在
问题描述
我有一个控制器,它有两种操作方法。它们都带有注释[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: 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”不存在。
解决方案
最后在做了更多的研究之后,我得到了解决方案。我只需要删除contentType
AJAX 调用中的选项,因此它使用默认值'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);
}
});
推荐阅读
- php - 检查数组键并替换是否存在 PHP
- google-cloud-platform - 如何找到具有 COS 映像的 Compute Engine 实例数与具有非 COS 映像的实例数?
- node.js - 在猫鼬中仅获取具有相同标题的记录之一
- ssh - 使用 gulp-ssh 部署文件
- c# - C# RestSharp 返回空白请求
- angular - 是否可以在 Angular 9 运行时观察或记录操作变量/数组的内容?
- c# - 如何检测 Quartz.net 中的作业何时取消?
- javascript - 如何在html中使用屏幕大小修复元素大小
- apache-commons - 从 commons-lang-2.6 迁移到 commons-lang3.12.0,面临错误:NestableException
- python - 什么会导致 xgboost 比 scikit-learn 梯度提升运行得慢?