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

EF Core一对多编辑Asset时ModelState.IsValid为False问题求助

编辑Asset时AssetsAliases导致ModelState.IsValid=False的问题

我有一个包含多个AssetsAlias的Asset模型类,编辑Asset时,AssetsAliases关联属性导致ModelState.IsValid返回false。

Asset模型类

public partial class Asset
{
    public int AssetId { get; set; }

    [Display(Name = "Asset Name")]
    public string? AssetName { get; set; }

    [Display(Name = "Assets Aliases")]
    public virtual List<AssetsAlias> AssetsAliases { get; set; }
                                   = new List<AssetsAlias>();

    //... 更多属性
}

AssetsAlias模型类

public partial class AssetsAlias
{
    public int AssetAliasId { get; set; }
    public int AssetId { get; set; }

    public string AssetAliasName { get; set; } = null!;

    public virtual Asset Asset { get; set; } = null!;
}

相关DBContext代码

public virtual DbSet<Asset> Assets { get; set; }
public virtual DbSet<AssetsAlias> AssetsAliases { get; set; }

modelBuilder.Entity<AssetsAlias>(entity =>
        {
            entity.HasKey(e => e.AssetAliasId).HasName("PK_Asset_Aliases");

            entity.ToTable("Assets_Aliases");

            entity.Property(e => e.AssetAliasId).HasColumnName("AssetAliasID");
            entity.Property(e => e.AssetAliasName)
                .HasColumnName("AssetAlias"); ;
            entity.Property(e => e.AssetId).HasColumnName("AssetID");

            entity.HasOne(d => d.Asset).WithMany(p => p.AssetsAliases)
                .HasForeignKey(d => d.AssetId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_Assets_Aliases_Assets");
        }
    );

Edit.cshtml.cs代码

public async Task<IActionResult> OnGetAsync(int? id)
{
    if (id == null || _context.Assets == null)
    {
        return NotFound();
    }

    var asset = await _context.Assets
                              .Where(m => m.AssetId == id)
                              .Include(m => m.AssetsAliases)
                              .FirstOrDefaultAsync();

    if (asset == null)
    {
        return NotFound();
    }

    Asset = asset;

    return Page();
}

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Attach(Asset).State = EntityState.Modified;

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!AssetExists(Asset.AssetId))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return RedirectToPage("/");
}

private bool AssetExists(int id)
{
    return (_context.Assets?.Any(e => e.AssetId == id)).GetValueOrDefault();
}

ModelState错误信息

AssetsAliases[0].Asset字段存在值不能为空的验证错误。


解决方法

方法1:移除子实体的ModelState验证错误

在OnPostAsync方法中,手动移除AssetsAliases相关的验证条目,因为编辑Asset时无需验证关联实体的导航属性:

public async Task<IActionResult> OnPostAsync()
{
    // 清理AssetsAliases相关的ModelState错误
    foreach (var key in ModelState.Keys.Where(k => k.StartsWith("AssetsAliases")).ToList())
    {
        ModelState.Remove(key);
    }

    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Attach(Asset).State = EntityState.Modified;

    // 手动处理别名的增改逻辑(如果需要编辑别名)
    foreach (var alias in Asset.AssetsAliases)
    {
        if (alias.AssetAliasId == 0)
        {
            _context.Add(alias);
        }
        else
        {
            _context.Attach(alias).State = EntityState.Modified;
        }
    }

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!AssetExists(Asset.AssetId))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return RedirectToPage("/");
}

方法2:排除导航属性的模型绑定

如果编辑页面不需要修改别名,可在Asset模型的AssetsAliases属性上添加[BindNever]特性,禁止模型绑定尝试设置该属性:

[Display(Name = "Assets Aliases")]
[BindNever]
public virtual List<AssetsAlias> AssetsAliases { get; set; }
                               = new List<AssetsAlias>();

方法3:调整表单绑定字段

在编辑页面的表单中,仅绑定需要修改的Asset字段,以及别名的基础字段(如AssetAliasName),避免绑定AssetsAliases[x].Asset这类导航属性。


内容的提问来源于stack exchange,提问作者s15199d

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 10:07:02