You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server中如何将列表传入Fluent Validation验证器检查重复值

Blazor Server中验证输入值是否存在于列表的最优实现

为什么你最初的UI判断方案不生效

你直接用@if判断后显示CustomValidationMessage的方式无效,因为ValidationMessage组件依赖于EditContext中的验证错误集合,手动渲染不会触发验证状态更新,所以组件无法识别到错误并正确显示。

最优方案:直接将外部列表传入FluentValidation验证器

不需要修改模型,通过给验证器添加带参数的构造函数,直接把现有名称列表传入验证逻辑,这是最直接的实现方式:

1. 修改ResourceValidator验证器

添加构造函数接收现有名称列表,并编写正确的验证规则:

public class ResourceValidator : AbstractValidator<ResourceModel>
{
    private readonly IEnumerable<string> _existingResourceNames;

    // 通过构造函数注入需要对比的名称列表
    public ResourceValidator(IEnumerable<string> existingResourceNames)
    {
        _existingResourceNames = existingResourceNames;

        RuleFor(model => model.Name)
            .Must(name => !_existingResourceNames.Contains(name))
            .WithMessage("该资源名称已存在");
    }
}

2. 在组件中手动创建验证器实例

放弃ValidatorType属性,改用Validator属性直接绑定带参数的验证器实例,传入你的resourcesSortedCollection名称列表:

<EditForm Model="@resourceToBeCreated">
    <!-- 传入现有资源名称列表创建验证器 -->
    <FluentValidationValidator Validator="@(new ResourceValidator(resourcesSortedCollection.Select(x => x.Name)))" />
    
    <!-- 使用标准ValidationMessage显示错误 -->
    <ValidationMessage For="() => resourceToBeCreated.Name" />
    
    <InputTextOnInput @bind-Value="@resourceToBeCreated.Name" class="form-control" placeholder="名称..." />
</EditForm>

改进你的临时方案(若需保留ValidatorType)

如果坚持使用ValidatorType无参构造的方式,可优化你的模型和验证规则(注意你原规则逻辑有误):

修正验证规则逻辑

原规则中Null().When(...)逻辑错误,正确规则应该是判断名称是否存在于列表中:

RuleFor(x => x.Name)
    .Must(name => !x.ResourceNames.Contains(name))
    .WithMessage("重复的资源名称");

同时确保在组件中及时将resourcesSortedCollection的名称列表赋值给模型的ResourceNames属性,比如在初始化或集合更新时同步:

protected override void OnInitialized()
{
    resourceToBeCreated.ResourceNames = resourcesSortedCollection.Select(x => x.Name).ToList();
}

// 若resourcesSortedCollection是动态更新的,需在集合变化时同步
private void OnResourcesCollectionChanged()
{
    resourceToBeCreated.ResourceNames = resourcesSortedCollection.Select(x => x.Name).ToList();
    // 通知验证器重新验证
    _editContext?.Validate();
}

手动实现验证(不依赖FluentValidation)

如果不想用FluentValidation,可通过操作EditContext手动添加验证错误,让ValidationMessage正确显示:

<EditForm EditContext="@_editContext">
    <ValidationMessage For="() => resourceToBeCreated.Name" />
    
    <InputTextOnInput @bind-Value="@resourceToBeCreated.Name" class="form-control" placeholder="名称..." />
</EditForm>

@code {
    private EditContext _editContext;
    private ResourceModel resourceToBeCreated = new();
    private List<ResourceModel> resourcesSortedCollection = new();

    protected override void OnInitialized()
    {
        _editContext = new EditContext(resourceToBeCreated);
        // 订阅模型属性变化事件,实时验证名称
        ((INotifyPropertyChanged)resourceToBeCreated).PropertyChanged += OnModelPropertyChanged;
    }

    private void OnModelPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(ResourceModel.Name))
        {
            ValidateResourceName();
        }
    }

    private void ValidateResourceName()
    {
        var field = _editContext.Field(nameof(ResourceModel.Name));
        _editContext.ClearValidationMessages(field);

        if (resourcesSortedCollection.Any(x => x.Name == resourceToBeCreated.Name))
        {
            _editContext.AddValidationMessage(field, "该资源名称已存在");
        }

        _editContext.NotifyValidationStateChanged();
    }
}

内容的提问来源于stack exchange,提问作者BobbyB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 19:09:22