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

Blazor中DataAnnotationsValidator生成RequiredAttribute错误信息及本地化方案咨询

Blazor中DataAnnotationsValidator生成RequiredAttribute错误提示的逻辑及本地化解决方案

一、DataAnnotationsValidator生成RequiredAttribute错误提示的原理

Blazor的DataAnnotationsValidator依赖.NET原生的System.ComponentModel.DataAnnotations验证体系:

  • 默认情况下,RequiredAttribute自带的错误消息模板是"{0}字段是必填项",其中{0}会被替换为属性的显示名称(优先取[Display(Name = "...")]的设置,没有的话用属性名)。
  • 验证时,DataAnnotationsValidator会为每个属性创建ValidationContext,通过这个上下文读取属性的元数据和注解配置,格式化错误消息后返回给UI显示。
  • 如果RequiredAttribute指定了ErrorMessageResourceName和ErrorMessageResourceType,则会从对应的资源文件中读取本地化消息,而非默认模板。

二、你之前的方法无效的原因

你用AddControllers配置ModelMetadataDetailsProviders的方式只对MVC/Razor Pages的控制器验证生效,Blazor的表单验证是独立体系,不依赖MVC的控制器验证服务,所以这套配置无法影响Blazor的DataAnnotationsValidator。

三、可行的本地化解决方案

1. 自定义ValidationMessageProvider(灵活可控,推荐)

Blazor的DataAnnotationsValidator允许通过ValidationMessageProvider替换默认的消息生成逻辑,结合IStringLocalizer实现本地化:

步骤1:自定义ValidationMessageProvider

public class LocalizedValidationMessageProvider : ValidationMessageProvider
{
    private readonly IStringLocalizer _localizer;

    public LocalizedValidationMessageProvider(IStringLocalizer localizer)
    {
        _localizer = localizer;
    }

    // 重写RequiredAttribute的错误消息生成方法
    public override string GetRequiredErrorMessage(string fieldName)
    {
        // 从本地化资源中获取消息,{0}替换为字段名
        return _localizer["RequiredField", fieldName];
    }

    // 可按需重写其他注解的消息方法,比如GetStringLengthErrorMessage等
}

步骤2:注册服务

在Program.cs中注册自定义的ValidationMessageProvider和本地化服务:

// 注册本地化资源(假设资源文件存放在Resources文件夹下)
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

// 注册自定义ValidationMessageProvider
builder.Services.AddSingleton<ValidationMessageProvider>(sp =>
{
    var localizer = sp.GetRequiredService<IStringLocalizer<SharedResources>>();
    return new LocalizedValidationMessageProvider(localizer);
});

步骤3:创建本地化资源文件

在项目中创建Resources文件夹,添加SharedResources.resx(默认语言)和SharedResources.zh-CN.resx(中文):

  • 在SharedResources.zh-CN.resx中添加键RequiredField,值为"{0}是必填项"

2. 直接给RequiredAttribute指定资源文件(原生DataAnnotations方式)

无需额外编写逻辑,直接在属性注解中指定本地化资源:

using System.ComponentModel.DataAnnotations;
using YourProject.Resources;

public class YourModel
{
    [Display(Name = "UserName", ResourceType = typeof(SharedResources))]
    [Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(SharedResources))]
    public string Name { get; set; }
}

然后在SharedResources.resx和对应本地化文件中添加UserName(显示名称)和RequiredField(错误消息)的键值对即可。

3. 自定义ModelMetadataProvider(类似你之前的思路)

如果需要统一处理所有属性的显示名称和错误消息本地化,可以自定义IModelMetadataProvider:

public class LocalizedModelMetadataProvider : DefaultModelMetadataProvider
{
    private readonly IStringLocalizer _localizer;

    public LocalizedModelMetadataProvider(IStringLocalizer localizer, IOptions<MvcOptions> options) : base(options)
    {
        _localizer = localizer;
    }

    protected override ModelMetadata CreateMetadata(ModelMetadataIdentity identity, ModelMetadata parent, Type modelType, string propertyName)
    {
        var metadata = base.CreateMetadata(identity, parent, modelType, propertyName);
        
        // 本地化显示名称
        if (!string.IsNullOrEmpty(metadata.DisplayName))
        {
            metadata.DisplayName = () => _localizer[metadata.DisplayName];
        }

        return metadata;
    }
}

然后在Program.cs中注册:

builder.Services.AddSingleton<IModelMetadataProvider, LocalizedModelMetadataProvider>();

这种方式可以统一处理所有属性的显示名称本地化,配合RequiredAttribute的资源配置一起使用效果更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 01:47:34