簡體   English   中英

使用 Ajax 和 Html.AntiForgeryToken() 時,所需的防偽表單字段“__RequestVerificationToken”不存在

[英]The required anti-forgery form field "__RequestVerificationToken" is not present when using Ajax and Html.AntiForgeryToken()

我有一個控制器,它有兩種操作方法。 它們都用[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”不存在。

終於在做了一些更多的研究之后,我得到了解決方案。 我只需要在 AJAX 調用中刪除contentType選項,所以它使用默認的'application/x-www-form-urlencoded; charset=UTF-8' '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”

由於您使用的是劍道,您還可以使用速記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);
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM