ASP.NET Core 模型验证消息的本地化新姿势

最近在研究系统本地化的问题,不可避免要实现模型类的验证消息本地化。毕竟这些错误消息是要返回给用户的。

疑问产生

在MVC模型下,我们会使用模型类对请求参数进行绑定和验证。举个例子:

复制代码
public class UserDto
{
    [Required(ErrorMessage = "姓名不能为空")]
    public string Name{get; set;}

    [Required(ErrorMessage = "年龄不能为空")]
    [Range(1, 120, ErrorMessage = "年龄必须在1到120之间")]
    public int? Age {get; set; }

}

这样本身没有什么问题,但如果有大量模型要做本地化改造,那可就是个大工程了。

我们不禁要问,为什么要指定ErrorMessage,默认的错误消息不能用吗?毕竟我们人工指定的错误消息除了字段名之外,其它都完全一样,实在没有必要逐个指定。

默认消息

我们来改造一下看看,删除掉指定的ErrorMessage。

复制代码
public class UserDto
{
    [Required]
    public string Name{get; set;}

    [Required]
    [Range(1, 120)]
    public int? Age {get; set; }

}

如果没有传入参数导致验证不通过,会得到如下消息:

复制代码
"The Name field is required."
"The Age field is required."

没错,默认消息是英文的,这对我们来说完全不可用------这对用户很不友好,难怪要人工设置 ErrorMessage。

查找默认消息

那有没有可能直接把默认消息本地化呢?如果可以,那就不用再麻烦地设置 ErrorMessage了。

通过查看**官方源码**我们发现,默认消息来自 SR 类,以RequiredAttribute举例:

复制代码
public RequiredAttribute()
      : base(() => SR.RequiredAttribute_ValidationError)
{
}

SR 类的内容简略如下:

复制代码
internal static partial class SR
{
    internal static global::System.Resources.ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new global::System.Resources.ResourceManager(typeof(FxResources.System.ComponentModel.Annotations.SR)));

    internal static string @RequiredAttribute_ValidationError => GetResourceString("RequiredAttribute_ValidationError", @"The {0} field is required.");
}

上面的代码中,GetResourceString 最终会调用内部声明的 ResourceManager。而 ResourceManager 会根据传入的类型参数查找本地化资源。

本地化默认消息

通过上面的分析,如果要使用中文内容,我们只要把本地化的消息放入 FxResources.System.ComponentModel.Annotations.SR.zh-CN.resources 即可。动手之前,我们再确认一下。

ILSpy 打开 System.ComponentModel.Annotations.dll,确实可以看到默认的资源 FxResources.System.ComponentModel.Annotations.SR.resources,证明我们的分析没错。

默认(中立语言)资源里面包含了错误消息,也包含了内部的异常消息。我们可以全部或者选择地本地化它们。

建立语言扩展包

我们建立一个项目,名为 FxResources.System.ComponentModel.Annotations。根据默认规则,在项目中建立的资源会自动添加命名空间作为前缀。

因此我们只需要再创建名为 SR 的资源即可。

如图,我们建立了对应的中文简体中文繁体资源,这样就大功告成了!

说明:zh-Hans 兼容 zh-CN、zh-SG;zh-Hant 兼容 zh-TW、zh-MO、zh-HK。严格讲港澳台繁体略有差异,但在一般场景可以忽略。

最终效果

同样是之前的例子,我们不需要再指定 ErrorMessage。

复制代码
public class UserDto
{
    [Required]
    public string Name{get; set;}

    [Required]
    [Range(1, 120)]
    public int? Age {get; set; }

}

现在我们得到的消息是这样,看起来还不错。

复制代码
"Name 字段为必填项。"
"Age 字段为必填项。"

注意:如果你的项目没有启用国际化功能,你需要设置默认的文化为中文:CultureInfo.DefaultThreadUICulture = CultureInfo.GetCultureInfo("zh-Hans")

Nuget 包

为方便大家使用,已经将语言资源打包为语言包,大家直接安装到项目即可。

复制代码
Install-Package FxResources.System.ComponentModel.Annotations.zh-Hans -Version 9.0.0

.NET 不同版本的资源之间有略微差异,大家选择对应的版本安装即可。

相关推荐
绿荫阿广16 天前
使用.NET开发并上线一个小智AI对话机器人的MCP服务转接平台
.net·asp.net core·mcp
dephixf1 个月前
工业级部署指南:在西门子IOT2050(Debian 12)上搭建.NET 9.0环境与应用部署(进阶篇)
asp.net core·iot·设备管理系统·.net 9·能源管理监控系统
绿荫阿广1 个月前
.NET开发上手Microsoft Agent Framework(一)从开发一个AI美女聊天群组开始
.net·asp.net core·agent framework
wangbin55422 个月前
使用Scalar.AspNetCore来管理你的OpenApi
asp.net core
ArabySide2 个月前
【ASP.NET Core】分布式场景下ASP.NET Core中JWT应用教程
分布式·后端·asp.net core
绿荫阿广2 个月前
用纯.NET开发并制作一个智能桌面机器人(六):使用.NET开发一个跨平台功能完善的小智AI客户端
c#·.net·asp.net core·maui·winui
冷冷的菜哥3 个月前
ASP.NET Core文件分片上传
c#·asp.net·asp.net core·文件分片上传
冷冷的菜哥3 个月前
ASP.NET Core上传文件到minio
后端·asp.net·上传·asp.net core·minio
ArabySide3 个月前
【ASP.NET Core】双Token机制在ASP.NET Core中的实现
后端·asp.net core
ArabySide4 个月前
【ASP.NET Core】探讨注入EF Core的DbContext在HTTP请求中的生命周期
后端·http·asp.net·asp.net core·efcore