ASP.NET Core+EF Core+Razor Pages中ModelState.IsValid导航键校验失败
问题:创建订单时ModelState.IsValid因导航属性校验失败
开发基于ASP.NET Core、EF Core和Razor Pages的客户订单管理应用,使用脚手架生成的创建订单代码时,出现ModelState.IsValid校验失败的问题,调试发现是导航属性Customer被提示为“必填项”。但移除ModelState.IsValid校验后,表单数据可正常提交并存入数据库。
相关代码
Order类(Order.cs)
public class Order { public int OrderId { get; set; } public string OrderNumber { get; set; } public int CustomerId { get; set; } public Customer Customer { get; set; } }
Customer类(Customer.cs)
public class Customer { public int CustomerId { get; set; } public string Name { get; set; } public ICollection<Order> Orders { get; set; } }
DbContext类(MyDbContext.cs)
public class MyDbContext : DbContext { public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { } public DbSet<Order> Orders { get; set; } = default!; public DbSet<Customer> Customers { get; set; } = default!; }
创建订单Razor页面(Orders.cshtml)
@page @model OrdersModel @{ ViewData["Title"] = "Orders"; } <h1>Orders</h1> <form method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Order.OrderNumber" class="control-label"></label> <input asp-for="Order.OrderNumber" class="form-control" /> <span asp-validation-for="Order.OrderNumber" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Order.Customer" class="control-label"></label> <select asp-for="Order.CustomerId" asp-items="ViewBag.CustomerId" class="form-control"></select> <span asp-validation-for="Order.CustomerId" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form>
Razor页面代码后置文件(Orders.cshtml.cs)
public class OrdersModel : PageModel { private readonly MyDbContext _dbContext; public OrdersModel(MyDbContext dbContext) { _dbContext = dbContext; } [BindProperty] public Order Order { get; set; } = default!; public IActionResult OnGet() { ViewData["CustomerId"] = new SelectList(_dbContext.Customer, "CustomerId", "Name"); return Page(); } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid || _context.Order == null || Order == null) { return Page(); } _dbContext.Order.Add(Order); await _dbContext.SaveChangesAsync(); return RedirectToPage("./Index"); } }
问题原因
- EF Core默认校验规则:EF Core会自动为非可空引用类型的导航属性(如
Order中的Customer)添加[Required]校验规则。但表单提交时仅传递了CustomerId外键值,并未提交完整的Customer对象,因此ModelState会判定Customer字段缺失,导致校验失败。 - 代码语法错误:
OnGet方法中,_dbContext.Customer应为_dbContext.Customers(DbContext中定义的DbSet是Customers);OnPostAsync方法中,_context未定义,应改为_dbContext,且_dbContext.Order应为_dbContext.Orders。
解决方案
方案1:将导航属性改为可空类型
修改Order类中的Customer属性,使其成为可空引用类型,EF Core便不会自动添加必填校验:
public class Order { public int OrderId { get; set; } public string OrderNumber { get; set; } public int CustomerId { get; set; } // 改为可空引用类型 public Customer? Customer { get; set; } }
方案2:移除ModelState中导航属性的校验错误
在OnPostAsync方法中,手动移除Customer导航属性的校验条目,再检查ModelState.IsValid:
public async Task<IActionResult> OnPostAsync() { // 移除导航属性的校验错误 ModelState.Remove("Order.Customer"); if (!ModelState.IsValid || _dbContext.Orders == null || Order == null) { return Page(); } _dbContext.Orders.Add(Order); await _dbContext.SaveChangesAsync(); return RedirectToPage("./Index"); }
方案3:修正代码中的语法错误
同时需要修正代码后置文件中的两处错误:
public IActionResult OnGet() { // 修正为_dbContext.Customers ViewData["CustomerId"] = new SelectList(_dbContext.Customers, "CustomerId", "Name"); return Page(); } public async Task<IActionResult> OnPostAsync() { // 移除导航属性校验错误(可选,配合方案2使用) ModelState.Remove("Order.Customer"); // 修正为_dbContext.Orders,且_context改为_dbContext if (!ModelState.IsValid || _dbContext.Orders == null || Order == null) { return Page(); } _dbContext.Orders.Add(Order); await _dbContext.SaveChangesAsync(); return RedirectToPage("./Index"); }
内容的提问来源于stack exchange,提问作者pikunimohanty
相关产品推荐
相关产品推荐

