You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Fetch API携带__RequestVerificationToken调用带[ValidateAntiForgeryToken]接口失败求助

问题:使用Fetch API提交带防伪令牌的ASP.NET表单时返回400错误

我在ASP.NET后端的Action上使用了[ValidateAntiForgeryToken]特性,代码如下:

[HttpPost("new")]
[ValidateAntiForgeryToken]
public JsonResult NewUser(NewUserViewModel user) {
    // 业务逻辑代码
}

用jQuery AJAX提交时可以成功:

$.ajax({
    url: window.location.pathname,
    type: 'POST',
    data: {
        Id: "1",
        UserName: "ajax",
        Password: "ajax",
        ConfirmPassword: "ajax",
        FullName: "ajax",
        Email: "ajax@ajax.is",
        Client: "ajax",
        Roles: ["ajax"],
        __RequestVerificationToken: document.querySelector('[name=__RequestVerificationToken]').value
    },
    success: function (response) {
        alert('Tókst');
    },
    error: function () {
        alert('tókst ekki');
    }
});

但换成Fetch API提交就收到400错误,移除[ValidateAntiForgeryToken]后就能正常运行:

let response = await fetch(window.location.pathname, {
    method: 'POST',
    body: {
        Id: "1",
        UserName: "fetch",
        Password: "fetch",
        ConfirmPassword: "fetch",
        FullName: "fetch",
        Email: "fetch@fetch.is",
        Client: "fetch",
        Roles: ["fetch"],
        __RequestVerificationToken: document.querySelector('[name=__RequestVerificationToken]').value
    }
});

请问需要补充什么才能让Fetch请求成功提交?


解决方案

这个问题我之前也碰到过,核心原因是Fetch API和jQuery AJAX在处理请求数据的方式上有本质差异:

  • jQuery的$.ajax默认会把对象数据序列化为application/x-www-form-urlencoded格式,自动设置对应的请求头,还能正确处理数组类型的参数(比如Roles: ["ajax"]会被转成Roles[]=ajax这种后端能识别的格式)。
  • 而你直接把JS对象传给Fetch的body时,浏览器会把它转换成字符串[object Object],后端完全无法解析,加上防伪令牌的传递不符合ASP.NET的预期,就触发了[ValidateAntiForgeryToken]的验证失败,返回400错误。

下面给你两种不需要修改后端的解决方案:

方法1:使用URLSearchParams序列化表单数据

这种方式和jQuery的默认行为一致,适合普通表单数据:

// 构建表单参数
const formParams = new URLSearchParams();
formParams.append('Id', '1');
formParams.append('UserName', 'fetch');
formParams.append('Password', 'fetch');
formParams.append('ConfirmPassword', 'fetch');
formParams.append('FullName', 'fetch');
formParams.append('Email', 'fetch@fetch.is');
formParams.append('Client', 'fetch');
// 数组参数需要逐个append,后缀加[]让后端识别
formParams.append('Roles[]', 'fetch');
// 添加防伪令牌
formParams.append('__RequestVerificationToken', document.querySelector('[name=__RequestVerificationToken]').value);

// 发起Fetch请求
const response = await fetch(window.location.pathname, {
    method: 'POST',
    body: formParams
    // URLSearchParams会自动设置Content-Type为application/x-www-form-urlencoded,无需手动添加
});

方法2:使用FormData对象

如果你的表单包含文件上传或者更复杂的字段,用FormData更合适,后端同样能兼容:

const formData = new FormData();
formData.append('Id', '1');
formData.append('UserName', 'fetch');
formData.append('Password', 'fetch');
formData.append('ConfirmPassword', 'fetch');
formData.append('FullName', 'fetch');
formData.append('Email', 'fetch@fetch.is');
formData.append('Client', 'fetch');
formData.append('Roles[]', 'fetch');
formData.append('__RequestVerificationToken', document.querySelector('[name=__RequestVerificationToken]').value);

const response = await fetch(window.location.pathname, {
    method: 'POST',
    body: formData
    // FormData会自动设置Content-Type为multipart/form-data,后端可正常解析
});

可选:用JSON格式提交(需修改后端)

如果你想改用JSON格式传递数据,需要同时修改前端和后端:

前端代码

const requestData = {
    Id: "1",
    UserName: "fetch",
    Password: "fetch",
    ConfirmPassword: "fetch",
    FullName: "fetch",
    Email: "fetch@fetch.is",
    Client: "fetch",
    Roles: ["fetch"]
};

const response = await fetch(window.location.pathname, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        // 把防伪令牌放在请求头里,ASP.NET会自动读取这个头
        'RequestVerificationToken': document.querySelector('[name=__RequestVerificationToken]').value
    },
    body: JSON.stringify(requestData)
});

后端修改

需要给Action的参数加上[FromBody]特性,告诉ASP.NET从请求体的JSON中解析数据:

[HttpPost("new")]
[ValidateAntiForgeryToken]
public JsonResult NewUser([FromBody] NewUserViewModel user) {
    // 业务逻辑代码
}

内容的提问来源于stack exchange,提问作者ðorvarður

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:15:25