Blazor中EditForm针对模型列表而非单个模型的验证问题
在Blazor中创建EditForm时,单个模型的验证实现非常顺利:只需在表单中配置OnValidSubmit,并在顶部添加DataAnnotationsValidator和ValidationSummary组件即可:
<EditForm FormName="CriminalConvictions" Model="criminalConvictions" OnValidSubmit="SubmitMany"> <DataAnnotationsValidator /> <ValidationSummary />
单个模型的声明与初始化代码如下:
[SupplyParameterFromForm] public CriminalConvictionModel? criminalConviction { get; set; } protected override async Task OnInitializedAsync() { criminalConviction ??= new(); }
还可以在字段下方添加对应字段的验证消息:
<InputTextArea @bind-Value="criminalConviction!.Offence" class="form-control" /> <ValidationMessage For="@(() => criminalConviction!.Offence)" />
同时在模型类中通过[Required]特性标记必填字段:
public class CriminalConvictionModel { public int CriminalConvictionID { get; set; } public DateTime? DateOfOffence { get; set; } [Required(ErrorMessage = "请填写犯罪详情")] public string? Offence { get; set; } // 其他属性... }
所有功能正常运行,字段验证符合预期:
浏览器中表单运行时必填字段为空的截图
现在需要支持提交多个条目,因此将模型声明改为模型对象列表:
public CriminalConvictionModel? criminalConviction { get; set; } [SupplyParameterFromForm] public List<CriminalConvictionModel>? criminalConvictions { get; set; } protected override async Task OnInitializedAsync() { criminalConviction ??= new(); criminalConvictions = new List<CriminalConvictionModel>(); criminalConvictions?.Add(criminalConviction); }
修改提交函数后,列表数据可以正常保存到SQL数据库,但验证功能完全失效:必填字段可以留空不填,无论列表中的模型是否有效,OnValidSubmit都会执行。
如果将EditForm的Model设置为单个criminalConviction,则仅会验证第一组表单元素,后续添加的元素无法触发验证;如果设置为列表criminalConvictions,则完全不会触发任何验证,目前无法确定需要修改哪些内容来解决该问题。
以下是用于向模型列表添加新模型、生成新表单字段的函数:
private void AddMoreConvictions() { formSubmitted = false; CriminalConvictionModel newConviction = new CriminalConvictionModel(); criminalConvictions = new List<CriminalConvictionModel>(); criminalConvictions?.Add(newConviction); }
所有功能均可正常运行,能将多条记录保存到数据库,但List<Model>的验证问题始终无法解决(单个Model的验证功能正常)。理想情况下,验证摘要能对应到每组字段,明确提示哪一组存在缺失字段。
查阅资料后发现最直观的方案是使用ObjectGraphDataAnnotationsValidator,它可以验证子元素,完全符合需求,但该组件已被弃用且无官方替代方案。
尝试编写自定义验证逻辑,遍历列表对象检查字段是否为空,但表单仍会正常提交。
考虑使用FluentValidation,但无法生效,报错No pending ValidationResult found。不确定是否需要创建一个包含该模型列表的父类,但实际需求仅需将列表中的模型插入数据库即可。
内容的提问来源于stack exchange,提问作者Robin Wilson

