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

Blazor Server中Fluent Validation如何校验输入值是否在外部列表中

解决方案

a) 将浏览器存储的列表传入验证器校验

首先修改SaveViewValidator,让它通过构造函数接收已存在的名称列表,新增重复校验规则:

namespace ITT_OneTeam.ViewModels
{
    public class SaveView
    {
        public string? ViewName { get; set; }
    }

    public class SaveViewValidator : AbstractValidator<SaveView>
    {
        private readonly IEnumerable<string> _existingNames;

        // 构造函数注入已存在的视图名称列表
        public SaveViewValidator(IEnumerable<string> existingNames)
        {
            _existingNames = existingNames;

            RuleFor(x => x.ViewName)
                .NotEmpty().WithMessage("Please enter the Name to be used.")
                // 校验输入名称是否不在已有列表中(忽略大小写)
                .Must(name => string.IsNullOrEmpty(name) || !_existingNames.Contains(name, StringComparer.OrdinalIgnoreCase))
                .WithMessage("This view name already exists.");
        }
    }
}

然后在Blazor组件中,通过JS互操作从浏览器localStorage获取列表,实例化验证器并关联到EditContext:

@inject IJSRuntime JSRuntime
@using FluentValidation
@using ITT_OneTeam.ViewModels
@using System.Text.Json

<EditForm EditContext="@editContext" OnValidSubmit="@HandleSubmit">
    <ValidationSummary />
    <div class="mb-3">
        <label class="form-label">View Name</label>
        <InputText @bind-Value="model.ViewName" class="form-control" />
        <ValidationMessage For="@(() => model.ViewName)" class="text-danger" />
    </div>
    <button type="submit" class="btn btn-primary">Save</button>
</EditForm>

@code {
    private SaveView model = new();
    private EditContext? editContext;
    private ValidationMessageStore? messageStore;

    protected override async Task OnInitializedAsync()
    {
        editContext = new EditContext(model);
        messageStore = new ValidationMessageStore(editContext);

        // 从localStorage读取已保存的视图名称列表
        var storedNamesJson = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "existingViewNames");
        var existingNames = string.IsNullOrEmpty(storedNamesJson) 
            ? new List<string>() 
            : JsonSerializer.Deserialize<List<string>>(storedNamesJson)!;

        // 实例化验证器并绑定到EditContext
        var validator = new SaveViewValidator(existingNames);
        editContext.AddFluentValidation(validator);
    }
}

b) 提交时动态添加错误并阻止提交

在提交方法中,使用ValidationMessageStore手动添加错误,触发验证状态变更来阻止提交:

private async Task HandleSubmit()
{
    if (editContext == null) return;

    // 先执行已有验证规则
    editContext.Validate();

    // 动态获取最新的浏览器存储列表(防止提交前有其他操作修改了列表)
    var latestStoredJson = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "existingViewNames");
    var latestNames = string.IsNullOrEmpty(latestStoredJson) 
        ? new List<string>() 
        : JsonSerializer.Deserialize<List<string>>(latestStoredJson)!;

    // 检查当前输入是否已存在
    if (!string.IsNullOrEmpty(model.ViewName) && latestNames.Contains(model.ViewName, StringComparer.OrdinalIgnoreCase))
    {
        // 清空之前的自定义错误,添加新错误
        messageStore?.Clear();
        messageStore?.Add(editContext.Field(nameof(SaveView.ViewName)), "This view name is already taken.");
        // 通知验证状态变更,让UI显示错误
        editContext.NotifyValidationStateChanged();
        return; // 直接返回,阻止提交逻辑执行
    }

    // 验证通过,执行提交逻辑
    if (editContext.IsValid)
    {
        // 将新名称添加到列表并保存回localStorage
        latestNames.Add(model.ViewName!);
        await JSRuntime.InvokeVoidAsync("localStorage.setItem", "existingViewNames", JsonSerializer.Serialize(latestNames));

        // 重置表单
        model = new SaveView();
        editContext = new EditContext(model);
        messageStore = new ValidationMessageStore(editContext);
        var validator = new SaveViewValidator(latestNames);
        editContext.AddFluentValidation(validator);
    }
}

额外注意事项

  • 确保已安装FluentValidation.Blazor NuGet包,并且在Program.cs中添加服务注册:
    builder.Services.AddFluentValidationAutoValidation();
    builder.Services.AddFluentValidationClientsideAdapters();
    
  • 如果需要大小写敏感校验,去掉StringComparer.OrdinalIgnoreCase即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:47:46