Angular向.NET Core 3.1控制器传参为null/值异常的问题及解决
.NET Core 3.1 + Angular 9 接口参数绑定异常解决
问题描述
环境:.NET Core 3.1、Angular 9
前端请求Payload显示数据完全正常,但后端控制器接收时出现异常:
- 控制器参数加
[FromBody]修饰时,接收的对象为null; - 移除
[FromBody]后能获取到对象实例,但所有属性值均为null或默认false;
已核对前后端属性名称完全匹配,尝试过以下操作: - Angular端将类改为
ClientInfoRequestModel接口,构建请求对象后控制台和Network均显示数据正常; - 后端尝试移除
[FromBody]后直接读取请求体,但代码执行到读取请求体后无法继续后续步骤。
代码片段
Angular 请求函数
getData(forwArray: number[], gac: string, sort: string, isGroupby: boolean, isFCCode: boolean): Observable<any> { //edited per suggestion const requestData:ClientInfoRequestModel ={ forwarders:forwArray, gac:gac, sort:sort, isGroupby:isGroupby, isFCCode:isFCCode, } //removed per suggestion //const httpOptions = { // headers: new HttpHeaders({ // 'Content-Type': 'application/json' // }) //}; console.log('requestData=', requestData); return this.http.post(this._ClientInfoURL, requestData ,httpOptions); }
Angular 接口定义
//edited the angular class to an interface export interface ClientInfoRequestModel { public forwarders: number[] = []; public isGroupby: boolean; public isFCCode: boolean; public gac: string; public sort: string; }
C# 控制器代码
//I removed [FromBody] below and can now see the object, but the values of each property are either null or default to false [HttpPost] public IActionResult GetClientInfo([FromBody] ClientInfoRequestModel requestData) { //requestData is an object but values of each property are null or default ... why? and how to fix? } //后端尝试的另一种写法 [HttpPost] public async Task<IActionResult> GetClientInfo() { //var requestForm = await Request.Form.ReadAsStringAsync();//no definition for ReadAsStringAsync var form = await Request.ReadFormAsync(); //the code executed this line but it never makes it to next line var requestBody = form.ToString(); }
C# 模型类
public class ClientInfoRequestModel { public int[] forwarders { get; set; } public string gac { get; set; } public bool isGroupby { get; set; } public bool isFCCode { get; set; } public string sort { get; set; } }
调试信息
Angular 控制台输出
requestData= {forwarders: Array(152), gac: 'TA', sort: '', isGroupby: false, isFCCode: true}
Network 请求Payload
forwarders : [3845, 3847, 3992, …] gac : "TA" isFCCode : true isGroupby : false sort : ""
原因分析
- Angular 接口定义错误:TypeScript接口中不能使用
public修饰符,也不能为属性设置默认值(如forwarders: number[] = []),这会导致对象序列化异常; - 请求Content-Type缺失:注释掉
httpOptions后,虽然HttpClient默认会发送JSON格式数据,但部分场景下可能未正确设置Content-Type: application/json,导致后端无法识别请求体格式; - 后端请求体读取方式错误:使用
ReadFormAsync()是读取表单格式数据,但前端发送的是JSON格式,因此会出现读取阻塞或无法获取有效数据的情况; - .NET Core JSON序列化配置问题:.NET Core 3.1默认使用
System.Text.Json,若未配置驼峰命名匹配,可能导致属性映射失败(虽本次前后端属性都是小驼峰,但需确认配置)。
解决办法
1. 修复Angular接口定义
去掉接口中的public修饰符和属性默认值,接口仅用于类型约束:
export interface ClientInfoRequestModel { forwarders: number[]; isGroupby: boolean; isFCCode: boolean; gac: string; sort: string; }
2. 恢复请求的Content-Type配置
确保请求携带正确的Content-Type头,避免后端无法识别JSON格式:
const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }; return this.http.post(this._ClientInfoURL, requestData, httpOptions);
3. 保留控制器的[FromBody]修饰符
[FromBody]是.NET Core接收JSON请求体的必要标识,必须保留,确保控制器方法如下:
[HttpPost] public IActionResult GetClientInfo([FromBody] ClientInfoRequestModel requestData) { // 正常处理逻辑 }
4. 配置.NET Core JSON序列化(可选)
若存在属性命名映射问题,在Startup.cs的ConfigureServices中配置System.Text.Json支持驼峰命名:
services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; });
或者切换为Newtonsoft.Json(若项目已引入):
services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); });
5. 正确读取请求体(调试用)
若需要手动读取JSON请求体,应使用ReadAsStringAsync()而非ReadFormAsync():
[HttpPost] public async Task<IActionResult> GetClientInfo() { var requestBody = await Request.Body.ReadAsStringAsync(); var requestData = JsonSerializer.Deserialize<ClientInfoRequestModel>(requestBody); // 后续处理 }
内容的提问来源于stack exchange,提问作者greg
相关产品推荐
相关产品推荐

