在 Blazor 中,EditForm 的验证机制默认是基于数据注解(Data Annotations)的,但你可以通过以下三种主流方式自定义验证规则

60 阅读2分钟

在 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 控制提交流程。根据你的项目复杂度和团队技术栈选择最适合的方式即可。