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
相关产品推荐
相关产品推荐

