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

如何为Blazor动态生成字段实现远程验证?

Blazor动态生成字段的远程验证实现方案

针对动态生成的邮箱输入框实现远程验证,核心是通过自定义异步验证属性结合EditContext的字段级验证来实现,以下是完整的落地方案:

1. 定义带验证的模型类

首先创建一个包装单个邮箱的模型,集成内置验证和自定义远程验证规则:

public class EmailItem
{
    [Required(ErrorMessage = "邮箱不能为空")]
    [EmailAddress(ErrorMessage = "请输入有效的邮箱格式")]
    [RemoteEmailExists(ErrorMessage = "该邮箱已存在")]
    public string Email { get; set; }
}

2. 实现自定义异步远程验证属性

继承ValidationAttribute并实现IAsyncValidator接口,完成后端API调用逻辑:

using Microsoft.AspNetCore.Components.Forms;
using System.Net.Http.Json;

public class RemoteEmailExistsAttribute : ValidationAttribute, IAsyncValidator
{
    public async Task<IEnumerable<ValidationResult>> ValidateAsync(
        ValidationContext validationContext, 
        CancellationToken cancellationToken)
    {
        var emailItem = validationContext.ObjectInstance as EmailItem;
        if (emailItem == null || string.IsNullOrWhiteSpace(emailItem.Email))
            return Enumerable.Empty<ValidationResult>();

        // 从验证上下文注入HttpClient
        var httpClient = validationContext.GetRequiredService<HttpClient>();
        // 调用后端API检查邮箱是否存在
        var exists = await httpClient.GetFromJsonAsync<bool>(
            $"api/emails/check-exists?email={Uri.EscapeDataString(emailItem.Email)}",
            cancellationToken);

        return exists ? 
            new[] { new ValidationResult(ErrorMessage, new[] { nameof(EmailItem.Email) }) } : 
            Enumerable.Empty<ValidationResult>();
    }
}

3. 封装动态输入组件

创建可复用的动态输入组件,绑定单个EmailItem并处理验证触发:

@using Microsoft.AspNetCore.Components.Forms

<div class="mb-3">
    <InputText @bind-Value="Item.Email" class="form-control" @oninput="TriggerValidation" />
    <ValidationMessage For="@FieldIdentifier" class="text-danger mt-1" />
</div>

@code {
    [Parameter, Required]
    public EmailItem Item { get; set; }

    [CascadingParameter]
    private EditContext EditContext { get; set; }

    private FieldIdentifier FieldIdentifier => FieldIdentifier.Create(Item, nameof(Item.Email));

    private async Task TriggerValidation(ChangeEventArgs e)
    {
        // 触发当前字段的异步验证
        await EditContext.ValidateFieldAsync(FieldIdentifier);
        // 通知字段状态变更,更新UI
        EditContext.NotifyFieldChanged(FieldIdentifier);
    }
}

4. 页面集成与提交控制

在主页面中渲染动态字段,绑定EditForm并控制提交状态:

@page "/dynamic-email-validation"
@inject HttpClient HttpClient

<EditForm Model="@EmailItems" OnValidSubmit="HandleSubmit" class="container mt-4">
    <DataAnnotationsValidator />
    <ValidationSummary class="alert alert-warning mb-3" />

    @foreach (var item in EmailItems)
    {
        <DynamicEmailInput Item="@item" />
    }

    <button type="button" class="btn btn-secondary me-2" @onclick="AddEmailField">添加邮箱</button>
    <button type="submit" class="btn btn-primary" disabled="@(!IsFormValid)">提交</button>
</EditForm>

@code {
    private List<EmailItem> EmailItems { get; set; } = new();
    private bool IsFormValid => EditContext?.Validate() ?? false;

    protected override void OnInitialized()
    {
        // 初始化一个默认输入框
        EmailItems.Add(new EmailItem());
    }

    private void AddEmailField()
    {
        EmailItems.Add(new EmailItem());
        StateHasChanged();
    }

    private async Task HandleSubmit()
    {
        // 提交所有邮箱到后端
        var emails = EmailItems.Select(x => x.Email).ToList();
        await HttpClient.PostAsJsonAsync("api/emails/save", emails);
        
        // 提交后的逻辑,比如清空或提示
        EmailItems.Clear();
        EmailItems.Add(new EmailItem());
    }
}

后端API示例(可选)

对应的后端检查接口可以这样实现(ASP.NET Core控制器):

[ApiController]
[Route("api/emails")]
public class EmailsController : ControllerBase
{
    // 模拟数据库存储的邮箱列表
    private static readonly List<string> ExistingEmails = new() { "test@example.com", "user@domain.com" };

    [HttpGet("check-exists")]
    public IActionResult CheckExists(string email)
    {
        var exists = ExistingEmails.Contains(email, StringComparer.OrdinalIgnoreCase);
        return Ok(exists);
    }

    [HttpPost("save")]
    public IActionResult Save([FromBody] List<string> emails)
    {
        // 处理保存逻辑
        return Ok();
    }
}

关键说明

  • 每个动态字段绑定独立的EmailItem实例,确保验证状态互不干扰;
  • 通过EditContext.ValidateFieldAsync触发单个字段的异步验证,避免全表单重验证;
  • 提交按钮的禁用状态通过EditContext.Validate()实时判断,确保表单无效时无法提交。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:05:28