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

ASP.NET 7.0 Razor Pages中DataType与Range数据注解本地化失效问题

ASP.NET 7.0 Razor Pages 数据注解本地化问题解决

问题概述

在ASP.NET 7.0 Razor Pages应用中,数据注解的错误消息本地化对多数属性生效,但存在以下异常:

  • DataType属性对应的错误消息始终显示为英文
  • 非可空值类型字段(如int YearGo)为空时,Range注解会触发与DataType相同的英文错误消息
  • 使用ErrorMessageResourceName和ErrorMessageResourceType属性对DataType注解做本地化配置无效

已配置ValidationMessages.resx(默认语言)和ValidationMessages.it.resx(意大利语)两个资源文件,包含所有错误消息的本地化内容。

相关代码示例

数据模型

[Display(Name = "Year go")]
[Required(ErrorMessage = "Required")]
[Range(2000, 2100, ErrorMessage = "Range")]
//[Range(2000, 2100, ErrorMessageResourceName = nameof(ValidationMessages.Range), ErrorMessageResourceType = typeof(ValidationMessages))]
public int YearGo { get; set; }

//[DataType(DataType.Date, ErrorMessage = "DataType")]
[DataType(DataType.Date, ErrorMessageResourceName = nameof(ValidationMessages.DataType), ErrorMessageResourceType = typeof(ValidationMessages))]
public DateTime ReleaseDate { get; set; }

[Range(1, 10, ErrorMessage = "Range")]
//[DataType(DataType.Currency, ErrorMessage = "DataType")]
[DataType(DataType.Currency, ErrorMessageResourceName = nameof(ValidationMessages.DataType), ErrorMessageResourceType = typeof(ValidationMessages))]
[Column(TypeName = "decimal(18, 2)")]
public decimal? Price { get; set; } 

Program.cs 核心配置

public static void Main(string[] args)
{
    string culture = "it";
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);

    var builder = WebApplication.CreateBuilder(args);

    builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

    var supportedCultures = new[] { new CultureInfo("it"), new CultureInfo("en-US") };
    builder.Services.Configure<RequestLocalizationOptions>(options =>
    {
        options.DefaultRequestCulture = new RequestCulture(culture);
        options.SupportedCultures = supportedCultures;
        options.SupportedUICultures = supportedCultures;
    });

    builder.Services.AddDbContext<OWsefaWebContext>(options =>
        options.UseSqlServer(builder.Configuration.GetConnectionString("OWsefaWebContext") ?? throw new InvalidOperationException("Connection string 'OWsefaWebContext' not found.")));

    builder.Services.AddRazorPages()
        .AddDataAnnotationsLocalization(opts =>
        {
            opts.DataAnnotationLocalizerProvider = (type, factory) =>
            {
                var assemblyName = new AssemblyName(typeof(SharedResource).GetTypeInfo().Assembly.FullName!);
                return factory.Create(nameof(SharedResource), assemblyName.Name!);
            };
        })
        .AddViewLocalization();

    // ... 其余中间件配置
    app.UseRequestLocalization();
    app.Run();
}

原因分析

  1. DataType注解的本质:DataType本身不提供验证逻辑,页面显示的"Invalid date"等错误是模型绑定阶段的类型转换错误,而非DataType注解的验证错误,因此直接给DataType设置ErrorMessageResourceName不会生效。
  2. 值类型空值绑定问题:非可空值类型(如int YearGo)无法绑定空值,会触发默认的类型转换错误,显示英文消息,而非Range或Required注解的自定义错误。
  3. 资源文件配置不匹配:当前DataAnnotationsLocalization指向的是SharedResource资源,而本地化错误消息存放在ValidationMessages资源文件中,导致无法读取对应本地化内容。

解决方案

1. 修正数据注解本地化的资源指向

修改AddDataAnnotationsLocalization的配置,将资源提供器指向ValidationMessages资源文件:

builder.Services.AddRazorPages()
    .AddDataAnnotationsLocalization(opts =>
    {
        opts.DataAnnotationLocalizerProvider = (type, factory) =>
        {
            var assemblyName = new AssemblyName(typeof(ValidationMessages).GetTypeInfo().Assembly.FullName!);
            return factory.Create(nameof(ValidationMessages), assemblyName.Name!);
        };
    })
    .AddViewLocalization();

2. 本地化模型绑定错误消息

在ValidationMessages.it.resx中添加模型绑定错误对应的键值对(示例):

键意大利语值
The field {0} must be a date.Il campo {0} deve essere una data.
The field {0} must be a number.Il campo {0} deve essere un numero.

这些键是ASP.NET Core模型绑定错误的默认消息键,添加后会自动替换对应的英文错误。

3. 处理值类型空值问题

将非可空值类型改为可空类型,配合Required注解,让空值触发Required的本地化错误,而非类型转换错误:

[Display(Name = "Year go")]
[Required(ErrorMessageResourceName = nameof(ValidationMessages.Required), ErrorMessageResourceType = typeof(ValidationMessages))]
[Range(2000, 2100, ErrorMessageResourceName = nameof(ValidationMessages.Range), ErrorMessageResourceType = typeof(ValidationMessages))]
public int? YearGo { get; set; } // 改为可空int

4. 确保资源文件的访问修饰符为Public

在资源文件的属性设置中,将“自定义工具”改为PublicResXFileCodeGenerator,并将“访问修饰符”设置为Public,确保代码能正确访问资源内容。

验证效果

完成上述修改后:

  • DataType对应的模型绑定错误会显示本地化后的消息
  • 空值字段会触发Required的本地化错误,而非类型转换错误
  • Range等注解的本地化消息正常生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:45:58