Blazor Server中OnValidSubmit异常触发及EditContext.Validate始终返回true问题
问题背景
我在Blazor Server项目中使用带EditContext和OnValidSubmit的EditForm:
<EditForm EditContext="@EditContext" OnValidSubmit="@UpdateProject">
声明并初始化EditContext的代码如下:
private EditContext EditContext; protected override async Task OnInitializedAsync() { EditContext = new(supplementedProjectModel); }
模型实例化代码:
SupplementedProjectModel supplementedProjectModel = new();
提交按钮代码:
<button type="submit" class="btn button-primary">Spara</button>
问题1:无效模型仍触发OnValidSubmit
即使模型因输入为空(模型里有[Required]特性)明显无效,点击提交时OnValidSubmit事件还是会触发,这是为什么?
模型结构如下:
public class SupplementedProjectModel { public CinodeDataModel CinodeDataModel = new(); } public class CinodeDataModel { public Webhook webhook { get; set; } } public class Webhook { public WebhookModel WebhookModel { get; set; } } public class WebhookModel { public Payload Payload { get; set; } } public class Payload { [Required(ErrorMessage = "Uppdragsnamn obligatorisk")] public string Title { get; set; } }
问题2:EditContext.Validate()始终返回true
在OnValidSubmit方法里,EditContext.Validate()一直返回true,原因是什么?
protected async Task UpdateProject() { bool IsValid = EditContext.Validate(); EditContext = new(supplementedProjectModel); bool isreallyvalid = EditContext.Validate(); if (IsValid) { // 更新模型逻辑 } }
我已经尝试使用以下验证器,输入无效数据时页面能正常显示错误提示:
@*<ObjectGraphDataAnnotationsValidator />*@ <DataAnnotationsValidator /> <ValidationSummary />
另外还有个疑问:UpdateProject方法里的EditContext应该包含当前模型值吧?我默认是这么认为但没找到明确说明,所以在重新初始化前后都测试了Validate方法。
问题原因及解决方案
核心问题:嵌套模型验证未生效
你的模型是多层嵌套结构,但当前使用的DataAnnotationsValidator只能验证顶层模型的直接属性,无法递归验证嵌套对象的属性。而OnValidSubmit触发的前提是EditContext认为模型有效,因为默认验证没检测到深层的[Required]错误,所以会触发提交事件,且Validate()返回true。
具体问题分析
- 模型字段定义错误:
SupplementedProjectModel里的CinodeDataModel是用字段(public CinodeDataModel CinodeDataModel = new();)而不是属性定义的,验证器无法识别字段,只能验证带get/set的属性。 - 嵌套验证缺失:即使把字段改成属性,
DataAnnotationsValidator也不支持递归验证嵌套对象,必须使用ObjectGraphDataAnnotationsValidator来启用对象图验证。 - 不必要的EditContext重建:提交方法里重新创建
EditContext是多余的,原EditContext已经绑定了当前模型的最新值,重新创建会丢失当前的验证状态和用户输入上下文。
修复步骤
将模型字段改为属性:
修正SupplementedProjectModel的定义,把字段改成自动属性,同时确保所有嵌套对象都正确初始化:public class SupplementedProjectModel { public CinodeDataModel CinodeDataModel { get; set; } = new(); } public class CinodeDataModel { public Webhook webhook { get; set; } = new(); } public class Webhook { public WebhookModel WebhookModel { get; set; } = new(); } public class WebhookModel { public Payload Payload { get; set; } = new(); }启用对象图验证:
替换DataAnnotationsValidator为ObjectGraphDataAnnotationsValidator,它会递归验证所有嵌套对象的特性:<ObjectGraphDataAnnotationsValidator /> <ValidationSummary />简化UpdateProject方法:
移除不必要的EditContext重建逻辑,直接使用原有实例验证:protected async Task UpdateProject() { bool IsValid = EditContext.Validate(); if (IsValid) { // 执行模型更新逻辑 } }
内容的提问来源于stack exchange,提问作者Hallonq

