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

基于DevExpress Blazor Scheduler的Blazor WASM表单自定义异步验证问题求助

解决Blazor WASM中DevExpress Scheduler自定义表单的异步验证问题

我完全理解你的困扰——Blazor的表单验证对异步场景的支持确实有不少限制,再结合第三方组件的表单逻辑,很容易陷入两难。针对你的情况,我有两个直接可行的方案,避开你遇到的那些坑:

方案一:拦截表单提交,手动执行异步验证(最贴合DevExpress场景)

DevExpress的Scheduler自定义表单允许我们拦截提交事件,先完成异步验证再决定是否提交。这种方式不需要依赖框架的自动验证管道,完全由我们控制验证时机:

<DxSchedulerAppointmentForm @ref="_appointmentForm" 
                            AppointmentInfo="@currentAppointment"
                            OnSubmit="HandleFormSubmit">
    <!-- 你的自定义表单字段 -->
    <DxTextBox @bind-Text="@currentAppointment.EndUser" 
               Caption="End User" />
    
    <!-- 显示异步验证错误 -->
    @if (!string.IsNullOrEmpty(_validationError))
    {
        <div class="text-danger mt-2">@_validationError</div>
    }
</DxSchedulerAppointmentForm>

@code {
    private DxSchedulerAppointmentForm _appointmentForm;
    private TlSchedulerAppointmentFormInfo currentAppointment = new();
    private string _validationError = string.Empty;
    
    // 直接注入你需要的服务
    [Inject] private HttpClient HttpClient { get; set; }

    private async Task HandleFormSubmit()
    {
        // 先清空之前的错误信息
        _validationError = string.Empty;

        // 执行异步验证逻辑
        bool isEndUserValid = await ValidateEndUserRequirement(currentAppointment.EndUser);
        if (!isEndUserValid)
        {
            _validationError = "End User is required based on system setup";
            return; // 验证不通过,阻止表单提交
        }

        // 验证通过,提交表单
        await _appointmentForm.SubmitAsync();
    }

    private async Task<bool> ValidateEndUserRequirement(string endUser)
    {
        var setup = await HttpClient.GetFromJsonAsync<Setup>("Setup/Requirements");
        bool isRequired = setup?.EndUserObbligatorio ?? false;
        // 逻辑:如果不需要则直接通过;需要的话则字段不能为空
        return !isRequired || !string.IsNullOrEmpty(endUser);
    }
}

方案二:用Blazor原生EditForm封装,手动管理异步验证状态

如果你愿意调整表单结构,用Blazor原生的EditForm包裹自定义字段,可以更灵活地结合同步+异步验证:

<EditForm Model="@currentAppointment" 
          EditContext="@_editContext"
          OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator /> <!-- 处理数据注解的同步验证 -->
    <ValidationSummary /> <!-- 显示同步验证错误 -->

    <!-- 你的表单字段 -->
    <DxTextBox @bind-Text="@currentAppointment.EndUser" 
               Caption="End User" />
    
    <!-- 异步验证错误单独显示 -->
    @if (!string.IsNullOrEmpty(_endUserAsyncError))
    {
        <div class="text-danger mt-2">@_endUserAsyncError</div>
    }

    <DxButton Text="Save" Type="ButtonType.Submit" />
</EditForm>

@code {
    private EditContext _editContext;
    private TlSchedulerAppointmentFormInfo currentAppointment = new();
    private string _endUserAsyncError = string.Empty;
    
    [Inject] private HttpClient HttpClient { get; set; }

    protected override void OnInitialized()
    {
        _editContext = new EditContext(currentAppointment);
        // 可选:监听字段变化,实时触发异步验证
        _editContext.OnFieldChanged += async (sender, args) =>
        {
            if (args.FieldIdentifier.FieldName == nameof(TlSchedulerAppointmentFormInfo.EndUser))
            {
                await ValidateEndUserAsync();
            }
        };
    }

    private async Task HandleValidSubmit()
    {
        // 提交前再确认异步验证状态
        await ValidateEndUserAsync();
        if (!string.IsNullOrEmpty(_endUserAsyncError)) return;

        // 这里执行保存逻辑,比如更新Scheduler的预约
        // ...
    }

    private async Task ValidateEndUserAsync()
    {
        _endUserAsyncError = string.Empty;
        var endUser = currentAppointment.EndUser;
        var setup = await HttpClient.GetFromJsonAsync<Setup>("Setup/Requirements");
        bool isRequired = setup?.EndUserObbligatorio ?? false;
        
        if (isRequired && string.IsNullOrEmpty(endUser))
        {
            _endUserAsyncError = "End User is required based on system setup";
        }
        
        // 通知EditContext更新验证状态
        _editContext.NotifyValidationStateChanged();
    }
}

为什么你之前的方案会失败?

  • 自定义验证器无法注入服务:Blazor的ValidationContext默认不提供依赖注入的访问入口,所以没法直接在验证器里获取HttpClient这类服务。
  • FluentValidation异步规则失效:正如文档所说,ASP.NET的自动验证管道是同步的,异步规则要么被强制同步执行(旧版本),要么直接抛出异常(新版本),而且DevExpress的表单提交逻辑不会等待异步验证完成就会关闭。
  • 同步阻塞GetAwaiter().GetResult():Blazor WASM是单线程模型,阻塞调用会直接导致运行时死锁,所以会触发异常。

这两个方案都避开了框架层面的异步验证限制,完全由我们手动控制验证流程,更适合你的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 01:33:11