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

ASP.NET Core HttpPost同时使用FromBody和FromQuery返回400错误

结论

HttpPost完全支持同时使用[FromBody]和[FromQuery]特性,你遇到的400错误和两个特性共存无关,是参数绑定格式错误、参数名不匹配导致的。

错误原因
  • [FromBody] string data绑定失败:ASP.NET Core默认的JSON反序列化器要求,当用string类型接收Body内容时,请求体必须是双引号包裹的合法JSON字符串值。你当前Angular端直接传入未序列化的data作为请求体,内容不符合JSON字符串格式,解析器遇到非法起始字符就会返回你看到的's' is an invalid start of a value错误。
  • [FromQuery] ICollection<int> list绑定不匹配:后端声明的查询参数名为list,但Angular传参时用的键名是scopes,名称不对应会导致集合无法接收值;同时你对数组做了JSON.stringify处理,把数组转成了字符串格式的数组文本,默认模型绑定器无法将其解析为int类型集合。
修正方案

方案1:保留后端现有string类型接收Body

调整Angular请求代码,对齐参数名、修正传参格式:

postAction(data: any, list: number[]): Observable<any> {
  let params = new HttpParams();
  // 对齐后端参数名list,逐个追加集合元素,无需序列化
  list.forEach(num => {
    params = params.append('list', num.toString());
  });
  // 将data序列化为标准JSON字符串作为请求体,指定正确Content-Type
  return this.httpClient.post(`${this.apiUri}/Save`, JSON.stringify(data), {
    params,
    headers: { 'Content-Type': 'application/json' }
  });
}

方案2:使用DTO接收结构化Body参数(推荐)

如果data是结构化业务对象,不要用string类型接收,定义对应结构的DTO类做模型绑定,稳定性更高:

  1. 后端代码调整:
// 按前端data的实际字段定义传输类
public class SaveDataDto
{
    // 替换为实际业务字段
    public string Content { get; set; }
    public int UserId { get; set; }
}

[HttpPost]
public bool Save([FromBody] SaveDataDto data, [FromQuery] ICollection<int> list)
{
    var result = true;
    return result;
}
  1. 对应Angular端仅需修正查询参数部分,Body直接传对象即可,HttpClient会自动完成JSON序列化:
postAction(data: any, list: number[]): Observable<any> {
  let params = new HttpParams();
  list.forEach(num => {
    params = params.append('list', num.toString());
  });
  return this.httpClient.post(`${this.apiUri}/Save`, data, { params });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:57:33