ASP.NET Core 8 MVC中Create方法ModelState无效:conturi_sintetice必填错误
ASP.NET Core 8 MVC Create方法ModelState无效:conturi_sintetice必填字段问题
我开发了一个ASP.NET Core 8 MVC应用,执行Create方法时出现ModelState无效的问题,错误提示为“conturi_sintetice是必填字段”。相关代码如下:
实体类定义
public class rjd { [Key] public int id_registru_jurnal { get; set; } public DateTime data { get; set; } public string nr_document { get; set; } [ForeignKey("conturi_sintetice")] public int id_CS_debitor { get; set; } public decimal debit { get; set; } public decimal credit { get; set; } public conturi_sintetice conturi_sintetice { get; set; } } public class conturi_sintetice { [Key] public int id_cont_sintetic { get; set; } public string explicatie_nr_cont_sintetic { get; set; } }
控制器Create方法
public async Task<IActionResult> Create([Bind("id_registru_jurnal,data,nr_document,id_CS_debitor,debit,credit")] rjd rjd) { if (ModelState.IsValid) { _context.Add(rjd); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } ViewData["id_CS_debitor"] = new SelectList(_context.Set<conturi_sintetice>(), "id_cont_sintetic", "id_cont_sintetic", rjd.id_CS_debitor); return View(rjd); }
视图Create表单
<form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> ...... <div class="form-group"> <label asp-for="id_CS_debitor" class="control-label"></label> <select asp-for="id_CS_debitor" class="form-control" asp-items="ViewBag.id_CS_debitor"></select> </div> ....... <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form>
问题原因
问题出在EF Core的模型验证逻辑:rjd类中的conturi_sintetice是引用类型的导航属性,在C# 8及以上版本的非空引用类型规则下,该属性默认会被模型绑定器标记为必填项。但Create操作中我们只提交了外键字段id_CS_debitor,并没有传递conturi_sintetice实体本身,因此ModelState验证失败,抛出必填字段错误。
解决方案
方案一:将导航属性改为可空类型
修改rjd类中的导航属性,添加可空运算符?,明确声明该属性允许为null:
public conturi_sintetice? conturi_sintetice { get; set; }
这是最符合C#规范的做法,能从根源上让模型验证正确识别该属性的可选性。
方案二:用[BindNever]标记导航属性
在导航属性上添加[BindNever]特性,让模型绑定器忽略该属性的验证:
[BindNever] public conturi_sintetice conturi_sintetice { get; set; }
这样模型绑定过程中不会检查conturi_sintetice的值,自然不会触发必填验证错误。
方案三:手动移除ModelState中的验证错误
在控制器Create方法中,判断ModelState有效性之前,手动移除conturi_sintetice对应的验证错误:
public async Task<IActionResult> Create([Bind("id_registru_jurnal,data,nr_document,id_CS_debitor,debit,credit")] rjd rjd) { ModelState.Remove("conturi_sintetice"); if (ModelState.IsValid) { _context.Add(rjd); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } ViewData["id_CS_debitor"] = new SelectList(_context.Set<conturi_sintetice>(), "id_cont_sintetic", "id_cont_sintetic", rjd.id_CS_debitor); return View(rjd); }
该方案适合无法修改实体类的场景,通过临时跳过指定属性的验证来解决问题。
内容的提问来源于stack exchange,提问作者ivf1971
相关产品推荐
相关产品推荐

