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

Blazor Server中双属性自定义ValidationAttribute联动验证问题

Blazor Server跨字段验证同步更新错误状态的解决办法

问题根源

你的问题在于Blazor的DataAnnotationsValidator默认仅在被修改的属性上触发验证,而自定义LessThan10Attribute是字段级验证逻辑。当修改SampleIntB降低总和时,系统不会自动重新验证SampleIntA,导致旧的错误提示残留。

方案一:通过INotifyPropertyChanged同步触发关联字段验证

让ViewModel实现INotifyPropertyChanged接口,在修改一个属性时,主动触发另一个属性的PropertyChanged事件,迫使Blazor重新验证两个字段。

修改后的SampleClass代码:

using Sample.ValidationAttributes;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Sample.ViewModels
{
    public class SampleClass : INotifyPropertyChanged
    {
        private int _sampleIntA;
        private int _sampleIntB;

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        [Required]
        [DisplayName("Sample A")]
        [LessThan10(ErrorMessage = "Sample A + Sample B Must be less than 10")]
        public int SampleIntA
        {
            get => _sampleIntA;
            set
            {
                if (_sampleIntA != value)
                {
                    _sampleIntA = value;
                    OnPropertyChanged(nameof(SampleIntA));
                    // 修改A时触发B的属性变更,强制重新验证B
                    OnPropertyChanged(nameof(SampleIntB));
                }
            }
        }

        [Required]
        [DisplayName("Sample B")]
        [LessThan10(ErrorMessage = "Sample A + Sample B Must be less than 10")]
        public int SampleIntB
        {
            get => _sampleIntB;
            set
            {
                if (_sampleIntB != value)
                {
                    _sampleIntB = value;
                    OnPropertyChanged(nameof(SampleIntB));
                    // 修改B时触发A的属性变更,强制重新验证A
                    OnPropertyChanged(nameof(SampleIntA));
                }
            }
        }
    }
}

此方案无需修改页面代码,仅通过ViewModel内部逻辑实现验证同步,保持了字段级验证的原有结构。

方案二:使用类级验证+手动触发整体验证

改用IValidatableObject接口实现类级别的跨字段验证,同时在页面中订阅字段变化事件,触发整个模型的验证,确保所有字段的错误状态同步更新。

第一步:修改ViewModel实现IValidatableObject

using System.ComponentModel.DataAnnotations;

namespace Sample.ViewModels
{
    public class SampleClass : IValidatableObject
    {
        [Required]
        [DisplayName("Sample A")]
        public int SampleIntA { get; set; }

        [Required]
        [DisplayName("Sample B")]
        public int SampleIntB { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (SampleIntA + SampleIntB > 10)
            {
                // 将错误关联到两个字段,确保两个<ValidationMessage>都显示提示
                yield return new ValidationResult(
                    "Sample A + Sample B Must be less than 10",
                    new[] { nameof(SampleIntA), nameof(SampleIntB) });
            }
        }
    }
}

第二步:修改Razor页面订阅字段变化事件

@page "/SamplePage"
@using Sample.Data;
@using Sample.ViewModels;
@inject SampleService sampleService

<h3>SamplePage</h3>

<EditForm Model="@sampleClass" EditContext="@_editContext">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <InputNumber id="SampleIntA" @bind-Value="sampleClass.SampleIntA" class="form-control" autocomplete="off" />
    <ValidationMessage For="() => sampleClass.SampleIntA" class="help-block text-danger" />

    <InputNumber id="SampleIntB" @bind-Value="sampleClass.SampleIntB" class="form-control" autocomplete="off" />
    <ValidationMessage For="() => sampleClass.SampleIntB" class="help-block text-danger" />

</EditForm>

@code {
    private SampleClass sampleClass;
    private EditContext _editContext;

    protected override async Task OnInitializedAsync()
    {
        sampleClass = sampleService.GetSampleClass();
        _editContext = new EditContext(sampleClass);
        // 任何字段修改时,触发整个模型的验证
        _editContext.FieldChanged += (sender, e) => _editContext.Validate();
    }
}

此方案更适合复杂的跨字段验证场景,错误信息可以统一管理,且无需维护字段级的验证属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:10:56