ASP.NET Core FormData接收对象列表参数为空的解决方法
ASP.NET Core FormData无法接收对象列表问题解决方案
问题根因
ASP.NET Core 默认表单模型绑定不支持直接识别FormData中传入的JSON格式对象集合,其对复杂类型集合的绑定遵循专属的字段命名规则,直接传入JSON数组字符串时,绑定器无法解析结构,最终导致接收到的集合参数为空。
涉及的实体定义
Stavka(商品项)实体
public class Stavka { public string naziv { get; set; } public double cenaPoJedinici { get; set; } public string jedinicaMere { get; set; } public int kolicina { get; set; } public Stavka(string naziv, double cenaPoJedinici, string jedinicaMere, int kolicina) { this.naziv = naziv; this.cenaPoJedinici = cenaPoJedinici; this.jedinicaMere = jedinicaMere; this.kolicina = kolicina; } public Stavka() { } }
Faktura(账单)实体
public class Faktura { public int Id { get; set; } public string pibStart { get; set; } public string pibEnd { get; set; } public DateTime datumGen { get; set; } public DateTime datumRok { get; set; } public List<Stavka> stavke { get; set;} public double cena { get; set; } public string tip { get; set; } public Faktura(int id, string pibStart, string pibEnd, DateTime datumGen, DateTime datumRok, List<Stavka> stavke, string tip) { Id = id; this.pibStart = pibStart; this.pibEnd = pibEnd; this.datumGen = datumGen; this.datumRok = datumRok; this.stavke = stavke; this.tip = tip; double sumCena = 0; // 增加空判断,避免stavke为null时抛出空引用异常 foreach(Stavka s in stavke ?? new List<Stavka>()) { sumCena += s.kolicina * s.cenaPoJedinici; } this.cena = sumCena; } public Faktura() { } }
原接口实现(存在绑定问题)
[HttpPost("dodajFakturu")] public IActionResult dodajFakturu([FromForm]string pibStart, [FromForm]string pibEnd,[FromForm]DateTime datumStart, [FromForm]DateTime datumEnd,[FromForm]List<Stavka> stavkeLis, [FromForm]string tip) { int id = lst.OrderByDescending(p => p.Id).First().Id + 1; Faktura f = new Faktura(id, pibStart,pibEnd, datumStart,datumEnd,stavkeLis,tip); lst.Add(f); return Ok(SveFakture()); }
可行修复方案
方案1:遵循表单绑定规则传参(无需修改接口签名)
ASP.NET Core 表单绑定复杂类型集合时,要求字段名遵循 [参数名].[索引].[属性名] 的平铺格式,索引从0开始连续、不可跳号,不需要传入JSON字符串,直接在FormData中添加对应字段即可。
例如传递2个商品项时,FormData字段如下:
stavkeLis[0].naziv= 第一个商品名称stavkeLis[0].cenaPoJedinici= 120.5stavkeLis[0].jedinicaMere= komstavkeLis[0].kolicina= 2stavkeLis[1].naziv= 第二个商品名称stavkeLis[1].cenaPoJedinici= 45stavkeLis[1].jedinicaMere= kgstavkeLis[1].kolicina= 3
方案2:直接绑定整体实体(推荐)
无需拆分零散参数,直接使用Faktura实体作为FormData绑定对象,模型绑定器会自动匹配所有字段,包括嵌套的商品集合,修改后接口如下:
[HttpPost("dodajFakturu")] public IActionResult dodajFakturu([FromForm]Faktura model) { int id = lst.OrderByDescending(p => p.Id).First().Id + 1; model.Id = id; // 重新计算总价 double sumCena = 0; foreach(Stavka s in model.stavke ?? new List<Stavka>()) { sumCena += s.kolicina * s.cenaPoJedinici; } model.cena = sumCena; lst.Add(model); return Ok(SveFakture()); }
使用该方案时,Swagger会自动生成所有字段(包括嵌套集合)的表单输入项,无需手动拼接字段名,传参时集合字段按stavke[0].naziv、stavke[0].kolicina的格式填写即可。
方案3:手动反序列化JSON字符串(适配前端固定传JSON的场景)
如果前端逻辑固定要把整个商品集合序列化为JSON字符串作为单个FormData字段传递,需要将集合参数类型改为string,手动执行反序列化,修改后接口如下:
[HttpPost("dodajFakturu")] public IActionResult dodajFakturu([FromForm]string pibStart, [FromForm]string pibEnd,[FromForm]DateTime datumStart, [FromForm]DateTime datumEnd,[FromForm]string stavkeLis, [FromForm]string tip) { // 手动反序列化JSON字符串为商品集合 var stavke = JsonSerializer.Deserialize<List<Stavka>>(stavkeLis); int id = lst.OrderByDescending(p => p.Id).First().Id + 1; Faktura f = new Faktura(id, pibStart,pibEnd, datumStart,datumEnd,stavke,tip); lst.Add(f); return Ok(SveFakture()); }
该方案下传参时,直接把完整的JSON数组字符串作为stavkeLis字段的值传入即可,无需拆分多个表单字段。
问题复现操作演示

内容的提问来源于stack exchange,提问作者Bogdan
相关产品推荐
相关产品推荐

