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类做模型绑定,稳定性更高:
- 后端代码调整:
// 按前端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; }
- 对应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
相关产品推荐
相关产品推荐

