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

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
: ""

原因分析

  1. Angular 接口定义错误:TypeScript接口中不能使用public修饰符,也不能为属性设置默认值(如forwarders: number[] = []),这会导致对象序列化异常;
  2. 请求Content-Type缺失:注释掉httpOptions后,虽然HttpClient默认会发送JSON格式数据,但部分场景下可能未正确设置Content-Type: application/json,导致后端无法识别请求体格式;
  3. 后端请求体读取方式错误:使用ReadFormAsync()是读取表单格式数据,但前端发送的是JSON格式,因此会出现读取阻塞或无法获取有效数据的情况;
  4. .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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:47:51