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

为何Ajax请求可正常绑定模型,XMLHttpRequest需加[FromBody]?

问题

我有如下简单的.NET Core后端接口:

[HttpPost]
[AllowAnonymous]
public JsonResult Test(TestRequestModel requestModel)
{
    //do stuff
    return Json(new { result.Success });
}

对应的请求模型:

public class TestRequestModel
{
    public string Email { get; set; } = string.Empty;
}

我需要通过POST请求调用该接口,但因特殊原因必须使用XMLHttpRequest而非$.ajax。以下是两种调用方式:

调用入口函数:

function MyTestFunction() {
   let parameters = {
       Email: "test@test.com"
   }

    CallServer(function () {
        //Do stuff
    }, function () {
        //Do other stuff
    }, "/Home/Test", parameters)
}

Ajax方式(可正常工作):

function CallServer(resolve, reject, path, parameters) {
    $.ajax({
        type: "POST",
        url: path,
        data: AddAntiForgeryToken(parameters),
        success: function (response) {
            //do stuff
        },
        error: function (xhr) {
            //do stuff
        },
        complete: function () {
            //do more stuff
        }
    });
}

XMLHttpRequest方式(模型创建但Email字段未填充,添加[FromBody]后正常):

function CallServer(resolve, reject, path, parameters) {
    let xhr = new XMLHttpRequest();

    xhr.open("POST", path, true);
    xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    xhr.setRequestHeader('RequestVerificationToken', GetMyToken());
    xhr.onreadystatechange = function (e) {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status === 200 || xhr.status === 201) {
                //do stuff
            }
            else {
                //do other stuff
            }
        }
    };
    
    xhr.send(JSON.stringify(parameters));
}

已知$.ajax底层基于XMLHttpRequest,请问为何XMLHttpRequest请求需添加[FromBody]才能正确绑定模型?是否可修改XMLHttpRequest代码,无需添加[FromBody]即可正常请求?

解答

为什么XMLHttpRequest请求需要[FromBody]

两种请求的Content-Type和数据格式完全不同,.NET Core的模型绑定规则会根据这两点决定数据源:

  • $.ajax默认会把parameters序列化为application/x-www-form-urlencoded格式(类似Email=test%40test.com&__RequestVerificationToken=xxx),并自动设置对应Content-Type。.NET Core默认优先从**请求表单(Form)**或URL查询字符串绑定模型,不需要额外标记。
  • 你写的XMLHttpRequest代码主动设置了Content-Type为application/json,且发送JSON字符串。这种情况下,.NET Core不会自动读取请求体中的JSON绑定模型,必须通过[FromBody]显式告知框架:从请求体的JSON数据中绑定该模型。

修改XMLHttpRequest代码,无需[FromBody]即可正常请求

要和$.ajax行为一致,只需将数据序列化为application/x-www-form-urlencoded格式,匹配.NET Core默认的模型绑定规则:

方式1:使用FormData(最贴近$.ajax默认逻辑)

function CallServer(resolve, reject, path, parameters) {
    let xhr = new XMLHttpRequest();

    // 构建FormData,模拟$.ajax的参数序列化逻辑
    let formData = new FormData();
    for (let key in parameters) {
        if (parameters.hasOwnProperty(key)) {
            formData.append(key, parameters[key]);
        }
    }
    // 添加防伪令牌
    formData.append('__RequestVerificationToken', GetMyToken());

    xhr.open("POST", path, true);
    // 无需手动设置Content-Type,XMLHttpRequest会自动为FormData配置正确的请求头
    xhr.onreadystatechange = function (e) {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status === 200 || xhr.status === 201) {
                //do stuff
            }
            else {
                //do other stuff
            }
        }
    };
    
    xhr.send(formData);
}

方式2:手动拼接urlencoded字符串

function CallServer(resolve, reject, path, parameters) {
    let xhr = new XMLHttpRequest();

    // 手动将参数转为urlencoded格式
    let urlEncodedParams = new URLSearchParams(parameters);
    urlEncodedParams.append('__RequestVerificationToken', GetMyToken());
    let paramsString = urlEncodedParams.toString();

    xhr.open("POST", path, true);
    // 设置对应Content-Type
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
    xhr.onreadystatechange = function (e) {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status === 200 || xhr.status === 201) {
                //do stuff
            }
            else {
                //do other stuff
            }
        }
    };
    
    xhr.send(paramsString);
}

以上两种写法都和$.ajax的默认请求格式一致,.NET Core会自动从表单数据中绑定模型,无需添加[FromBody]。

内容的提问来源于stack exchange,提问作者Bagzli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:57:08