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

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");
    }
}

问题原因

  1. EF Core默认校验规则:EF Core会自动为非可空引用类型的导航属性(如Order中的Customer)添加[Required]校验规则。但表单提交时仅传递了CustomerId外键值,并未提交完整的Customer对象,因此ModelState会判定Customer字段缺失,导致校验失败。
  2. 代码语法错误:
    • 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 09:53:21