首页 > 解决方案 > 使用 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种方法:

  1. 在 AJAX 的 headers 参数中传递令牌,例如: headers: { '__RequestVerificationToken': token }

  2. 在 AJAX 的数据参数中传递令牌,例如: data: JSON.stringify({ vendorId: vId, orderIds: oIds, __RequestVerificationToken: token })

  3. 附加令牌值并将其传递给 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”不存在。

标签: c#jqueryajaxasp.net-mvcrazor

解决方案


最后在做了更多的研究之后,我得到了解决方案。我只需要删除contentTypeAJAX 调用中的选项,因此它使用默认值'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);
    }
});

参考:ajax调用中不存在所需的防伪表单字段“__RequestVerificationToken”


推荐阅读