在 Blazor 中,EditForm 的验证机制默认是基于数据注解(Data Annotations)的,但你可以通过以下三种主流方式自定义验证规则,以适应更复杂的业务逻辑:
✅ 方式一:自定义验证特性(继承 ValidationAttribute)
适合:字段级验证、复用性高的规则。
public class EvenNumberAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext context)
{
if (value is int number && number % 2 != 0)
{
return new ValidationResult("必须是偶数", new[] { context.MemberName });
}
return ValidationResult.Success;
}
}
public class MyModel
{
[EvenNumber(ErrorMessage = "请输入偶数")]
public int Count { get; set; }
}
使用方式与内置特性一致,直接标记在模型属性上即可。
✅ 方式二:自定义验证组件(使用 ValidationMessageStore)
适合:跨字段验证、复杂逻辑、动态错误注入。
步骤如下:
1. 创建自定义验证器组件
@using System.ComponentModel.DataAnnotations
@inherits ComponentBase
@code {
[CascadingParameter] private EditContext EditContext { get; set; }
private ValidationMessageStore _messageStore;
protected override void OnInitialized()
{
_messageStore = new ValidationMessageStore(EditContext);
EditContext.OnValidationRequested += ValidateModel;
}
private void ValidateModel(object sender, ValidationRequestedEventArgs args)
{
_messageStore.Clear();
var model = (MyModel)EditContext.Model;
if (model.Email != null && !model.Email.EndsWith("@qq.com"))
{
var field = new FieldIdentifier(model, nameof(model.Email));
_messageStore.Add(field, "必须使用QQ邮箱");
}
EditContext.NotifyValidationStateChanged();
}
}
2. 使用方式
<EditForm Model="@model">
<DataAnnotationsValidator />
<CustomValidator />
<InputText @bind-Value="model.Email" />
<ValidationMessage For="() => model.Email" />
</EditForm>
这种方式允许你在运行时动态添加错误,适用于跨字段或依赖外部服务的验证。
✅ 方式三:使用 FluentValidation(推荐用于复杂模型)
适合:复杂验证逻辑、链式规则、支持异步验证。
1. 安装 NuGet 包
dotnet add package FluentValidation
2. 创建验证器类
public class MyModelValidator : AbstractValidator<MyModel>
{
public MyModelValidator()
{
RuleFor(x => x.Email)
.Must(email => email.EndsWith("@qq.com"))
.WithMessage("必须使用QQ邮箱");
}
}
3. 创建验证器组件(适配 FluentValidation)
@inherits ComponentBase
@using FluentValidation
@inject IServiceProvider Services
@code {
[CascadingParameter] private EditContext EditContext { get; set; }
private ValidationMessageStore _messageStore;
protected override void OnInitialized()
{
_messageStore = new ValidationMessageStore(EditContext);
EditContext.OnValidationRequested += ValidateModel;
}
private async void ValidateModel(object sender, ValidationRequestedEventArgs args)
{
_messageStore.Clear();
var validator = Services.GetService<IValidator<MyModel>>();
var result = await validator.ValidateAsync((MyModel)EditContext.Model);
foreach (var error in result.Errors)
{
var field = new FieldIdentifier(EditContext.Model, error.PropertyName);
_messageStore.Add(field, error.ErrorMessage);
}
EditContext.NotifyValidationStateChanged();
}
}
4. 注册服务
builder.Services.AddScoped<IValidator<MyModel>, MyModelValidator>();
结合 FluentValidation 后,Blazor 表单验证可以变得非常强大且易于维护。
✅ 总结对比表
| 方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 自定义特性 | 字段级验证 | 简洁、可复用 | 不适用于跨字段逻辑 |
| ValidationMessageStore | 复杂逻辑、跨字段 | 灵活、可动态注入错误 | 需手动管理错误状态 |
| FluentValidation | 复杂模型、链式规则 | 可读性强、支持异步 | 需引入第三方库 |
如需进一步扩展,还可结合 OnFieldChanged 实现实时验证,或使用 OnValidSubmit 控制提交流程。根据你的项目复杂度和团队技术栈选择最适合的方式即可。