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 不同版本的资源之间有略微差异,大家选择对应的版本安装即可。

相关推荐
lixww.cn1 个月前
ASP.NET Core用MediatR实现领域事件
ddd·asp.net core·mediatr
lixww.cn1 个月前
ASP.NET Core SignalR向部分客户端发消息
javascript·websocket·vue·asp.net core·signalr
lixww.cn1 个月前
ASP.NET Core SignalR的协议协商
asp.net core·signalr
lixww.cn1 个月前
ASP.NET Core SignalR的分布式部署
redis·消息队列·asp.net core·signalr
lixww.cn1 个月前
ASP.NET Core对JWT的封装
asp.net core·jwt·authorize
lixww.cn1 个月前
ASP.NET Core JWT Version
asp.net core·jwt·filter·identity
lixww.cn2 个月前
ASP.NET Core JWT
asp.net core·jwt
lixww.cn2 个月前
ASP.NET Core标识框架Identity
asp.net core·rbac·identity
lixww.cn2 个月前
ASP.NET Core中间件Markdown转换器
中间件·markdown·asp.net core