.NET Core中带AllowNull导航属性的模型提交时ModelState无效问题
EF脚手架生成的分类/产品控制器创建/编辑时ModelState校验失败问题
分类(Categories)与产品(Product)为一对多关系,使用Entity Framework脚手架生成默认控制器和视图创建/编辑分类时,ModelState始终失效,产品控制器也存在同样问题。表单仅提交CategoryName和url两个字段,但ModelState会检查Products导航属性,报错:"The Products field is required."
模型代码
public class Product { [Key] public int ProductId { get; set; } // Foreign Key [ForeignKey("CategoryId")] public int CategoryID { get; set; } public Categories Category { get; set; } public string Name { get; set; } public string Description { get; set; } public string url { get; set; } public decimal Price { get; set; } } public class Categories { [Key] public int CategoryID { get; set; } public string CategoryName { get; set; } public string url { get; set; } // Navigation Property for Products (optional but recommended) [AllowNull] public ICollection<Product> Products { get; set; } } // In your Models folder (or create a ViewModels folder) public class ProductsCategoriesViewModel { public List<Categories> Categories { get; set; } public List<Product> Products { get; set; } }
默认Create控制器代码
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("CategoryID,CategoryName,url")] Categories categories) { if (ModelState.IsValid) { _context.Add(categories); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(categories); }
Create.cshtml视图代码
@model MyKartV2.Models.Categories @{ ViewData["Title"] = "Create"; } <h1>Create</h1> <h4>Categories</h4> <hr /> <div class="row"> <div class="col-md-4"> <form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="CategoryName" class="control-label"></label> <input asp-for="CategoryName" class="form-control" /> <span asp-validation-for="CategoryName" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="url" class="control-label"></label> <input asp-for="url" class="form-control" /> <span asp-validation-for="url" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-action="Index">Back to List</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
补充说明
表单仅提交两个字段,但ModelState仍为导航属性Products添加校验条目,导致ModelState无效,错误信息为*"The Products field is required."*
解决思路及方案
方案1:给导航属性添加忽略绑定特性
在Categories类的Products属性上添加[BindNever],告诉模型绑定器忽略该属性,不参与校验:
[BindNever] public ICollection<Product> Products { get; set; }
方案2:初始化导航属性集合
在Categories类中给Products属性赋默认空集合,避免属性为null触发校验:
public ICollection<Product> Products { get; set; } = new List<Product>();
方案3:使用ViewModel接收表单数据
创建仅包含表单所需字段的ViewModel,避免实体类的导航属性干扰校验:
public class CategoryCreateViewModel { public string CategoryName { get; set; } public string url { get; set; } }
修改控制器接收ViewModel并映射到实体:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(CategoryCreateViewModel model) { if (ModelState.IsValid) { var category = new Categories { CategoryName = model.CategoryName, url = model.url }; _context.Add(category); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(new Categories { CategoryName = model.CategoryName, url = model.url }); }
同时将视图的@model改为MyKartV2.Models.CategoryCreateViewModel。
方案4:手动移除ModelState中的错误
在控制器中手动移除Products属性的校验错误:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("CategoryID,CategoryName,url")] Categories categories) { ModelState.Remove("Products"); if (ModelState.IsValid) { _context.Add(categories); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(categories); }
内容的提问来源于stack exchange,提问作者Ishav Gupta
相关产品推荐
相关产品推荐

