jQuery 没有表单的 AJAX 发布 ValidateAntiForgeryToken 到 MVC 操作方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17857850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 20:06:06  来源:igfitidea点击:

AJAX Posting ValidateAntiForgeryToken without Form to MVC Action Method

jqueryasp.net-mvcjson

提问by Jammer

I've been looking at examples of how to do this on SO and as far as I can tell I've tried all the examples I can find with no success so far. I've tried altering some of the implementations to my scenario but this has thus far failed as well.

我一直在查看如何在 SO 上执行此操作的示例,据我所知,到目前为止,我已经尝试了所有可以找到的示例,但都没有成功。我已经尝试将一些实现更改为我的场景,但到目前为止这也失败了。

I have this on my page in _layout.cshtml so I always have a token available:

我在 _layout.cshtml 的页面上有这个,所以我总是有一个可用的令牌:

<form id="__AjaxAntiForgeryForm" action="#" method="post"> @Html.AntiForgeryToken()</form>

I also have this method in my JavaScript utils file:

我的 JavaScript utils 文件中也有这个方法:

AddAntiForgeryToken = function (data) {
    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
    return data;
};

This is all working as expected and I get an anti forgery token. My actual posting code is:

这一切都按预期工作,我得到了一个防伪令牌。我的实际发布代码是:

myPage.saveData = function() {
    var saveUrl = '/exercises/PostData';

    var myData = JSON.stringify(myPage.contextsArrays);

    $.ajax({
        type: 'POST',
        async: false,
        url: saveUrl,
        data: AddAntiForgeryToken({ myResults: myData }),
        success: function () {
            alert('saved');
        },
        dataType: 'json',
        contentType: "application/json; charset=utf-8"
    });
};

My action method looks like this:

我的操作方法如下所示:

    [HttpPost, ValidateAntiForgeryToken, JsonExceptionFilter]
    public JsonResult PostData(List<ResultsDc> myResults)
    {
        return Json(_apiClient.SubmitResults(myResults));
    }

I've been testing this with the various implementations I've been trying and the response is always:

我一直在用我一直在尝试的各种实现来测试这个,响应总是:

{"errorMessage":"The required anti-forgery form field \"__RequestVerificationToken\" is not present."}

I'm not posting a form it's just an array of data but checking the data that actually gets posted the Json doesn't look right (it's all encoded) but the __RequestVerificationToken parameter name is there and the token value is also present.

我不是发布表单,它只是一个数据数组,而是检查实际发布的数据,Json 看起来不正确(全部已编码),但 __RequestVerificationToken 参数名称在那里,并且令牌值也存在。

I'm pretty confused by all this at the moment and cannot find the correct way to send the token so that my MVC action is invoked. If I remove the ValidateAntiForgeryTokenattribute and have JSON.stringify(myPage.contextsArrays);as the data the json looks correct (unencoded) and it maps fine.

目前我对这一切感到非常困惑,无法找到发送令牌的正确方法,以便调用我的 MVC 操作。如果我删除该ValidateAntiForgeryToken属性并将其JSON.stringify(myPage.contextsArrays);作为数据,则 json 看起来正确(未编码)并且映射良好。

How do I get this token posted properly without a form?

如何在没有表格的情况下正确发布此令牌?

回答by Jammer

Cardboard developer strikes again.

纸板开发商再次罢工。

All I had to do was remove:

我所要做的就是删除:

contentType: "application/json; charset=utf-8"

And by doing that (which changes the kind of post request being made), to get the Json content of the actual data property to bind correctly to your Tmodel type DO NOTJSON.stringify()the data.

并且通过这样做(这会改变正在发出的发布请求的类型),以获取实际数据属性的 Json 内容以正确绑定到您的T模型类型不要JSON.stringify()数据。

回答by ESDictor

(NOTE: I know this isn't all that much different than what is already here)

(注意:我知道这与这里已有的并没有太大不同)

I realize this has already been answered, but I've done this quite a bit and will add my answer to the pile. I have no Forms in my site, so I had to come up with ways to handle this. A lot of research here on stackoverflow and some blogs finally gave me the info I needed.

我意识到这已经得到了回答,但我已经做了很多,并将我的答案添加到堆中。我的网站上没有表单,所以我必须想出办法来处理这个问题。在这里对 stackoverflow 和一些博客进行了大量研究,最终为我提供了所需的信息。

First, here's my code at the top of my "master" page (MVC Razor):

首先,这是我的“母版”页面(MVC Razor)顶部的代码:

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
    @Html.AntiForgeryToken()
}

Then, in all ajax calls (jQuery), I start like this:

然后,在所有 ajax 调用(jQuery)中,我都是这样开始的:

var token = $("#__AjaxAntiForgeryForm input").val();
var dataObject = {
  __RequestVerificationToken: token,
  myData: "whatever"
};

$.ajax({
  url: '@Url.Action("action", "controller")',
  type: 'POST',
  dataType: 'json',
  data: dataObject,
  error: function (jqXHR, textStatus, errorThrown) {
    console.log("ERROR!");
  },
  success: function (data) {
    //whatever
  }
});

Finally, in the Controller side of things, this works fine:

最后,在控制器方面,这很好用:

public class controllerController : Controller
{
    [HttpPost]
    [ValidateAntiForgeryToken]
    public JsonResult action (myModel myData)
    {
        return Json(new { Success = "true" }, JsonRequestBehavior.DenyGet);
    }
}

Hopefully this would help others in the same boat.

希望这会帮助其他人在同一条船上。

回答by user247702

The validation is hardcoded to look at form data.

验证是硬编码的以查看表单数据。

https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.WebPages/Helpers/AntiXsrf/AntiForgeryTokenStore.cs

https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.WebPages/Helpers/AntiXsrf/AntiForgeryTokenStore.cs

    public AntiForgeryToken GetFormToken(HttpContextBase httpContext)
    {
        string value = httpContext.Request.Form[_config.FormFieldName];

You can simulate a form submission by following a certain format. For that, see How to mimic an HTML form submission in a POST request?

您可以通过遵循某种格式来模拟表单提交。为此,请参阅如何在 POST 请求中模拟 HTML 表单提交?

If you want, you can also make your own validator. How to POST JSON data to an Asp.Net MVC 2 app with ValidateAntiForgeryTokenexplains how to do this. It is for MVC 2 but you can pick up some ideas from it.

如果需要,您还可以制作自己的验证器。How to POST JSON data to an Asp.Net MVC 2 app with ValidateAntiForgeryToken解释了如何做到这一点。它适用于 MVC 2,但您可以从中获得一些想法。