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

疑问产生

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

ASP.NET Core 模型验证消息的本地化新姿势的更多相关文章

  1. ASP.NET Core 模型验证的一个小小坑

    今天在我们的一个项目中遇到一个 asp.net core 模型验证(model validation)的小问题.当模型属性的类型是 bool ,而提交上来的该属性值是 null ,asp.net co ...

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

    默认错误消息: MissingBindRequiredValueAccessor A value for the '{0}' property was not provided. MissingKey ...

  3. ASP.NET MVC - 模型验证

    ASP.NET MVC - 模型验证(Model verification) 模型验证原理浅析 模型验证用到了模型绑定器.模型验证器(System.Web.Mvc.DataAnnotationsMod ...

  4. ASP.NET Core Identity 验证特性 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Identity 验证特性 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Identity 验证特性 上一章节我们简单介绍了 ...

  5. asp.net mvc 模型验证组件——FluentValidation

    asp.net mvc 模型验证组件——FluentValidation 示例 using FluentValidation; public class CustomerValidator: Abst ...

  6. ASP.NET与ASP.NET Core用户验证Cookie并存解决方案

    在你将现有的用户登录(Sign In)站点从ASP.NET迁移至ASP.NET Core时,你将面临这样一个问题——如何让ASP.NET与ASP.NET Core用户验证Cookie并存,让ASP.N ...

  7. ASP.NET Core身份验证

    asp.net core 身份验证 本文旨在演示如果使用内置的 identity 实现 asp.net core 的身份验证,不会进行其它扩展.本文将通过最简单的代码演示如何进行登录和身份验证操作. ...

  8. 学习ASP.NET Core Razor 编程系列十一——把新字段更新到数据库

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  9. 理解ASP.NET Core - 模型绑定&验证(Model Binding and Validation)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 模型绑定 什么是模型绑定?简单说就是将HTTP请求参数绑定到程序方法入参上,该变量可以是简单类 ...

  10. Asp.Net Core 客户端验证和远程验证

    我们先来看这样一个注册页面和它的后台Model @model RegisterViewModel @{ ViewBag.Title = "用户注册"; } <h1>用户 ...

随机推荐

  1. [转]Spring+SpringMVC+MyBatis+easyUI整合基础篇(一)项目简述及技术选型介绍

    原文链接: Spring+SpringMVC+MyBatis+easyUI整合基础篇(一)项目简述及技术选型介绍

  2. 即时通讯技术文集(第14期):WebSocket精华文章合集 [共15篇]

    为了更好地分类阅读52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第14 期. [- 1 -] 新手快速入门:WebSocket简明教程 [链接] http://w ...

  3. IM通讯协议专题学习(八):金蝶随手记团队的Protobuf应用实践(原理篇)

    本文由金蝶随手记技术团队丁同舟分享. 1.引言 跟移动端IM中追求数据传输效率.网络流量消耗等需求一样,随手记客户端与服务端交互的过程中,对部分数据的传输大小和效率也有较高的要求,普通的数据格式如 J ...

  4. spark (六) RDD算子(operator)

    目录 1 转换算子(transformer)(将旧的RDD包装成新RDD) 1.1 单值类型 1.1.1 map 1.1.2 mapPartition 1.1.3 mapPartitionsWithI ...

  5. Royal Elementor Addons Pro v1.3.987 + v1.5.0 elementor网页设计元素组件插件下载

    Royal Elementor Addons Pro elementor网页设计元素组件插件破解版简介&下载 Royal Elementor Addons Pro Nulled Element ...

  6. Optional的使用与解析

    引言 今天在项目中看到了大量Optional的使用,之前我也了解过Optional,是Java8中的新特性,并且便利地为空指针问题提供了处理方法,可以避免繁琐的if/else. 但是并没有真正在项目中 ...

  7. [LC793]阶乘函数后 K 个零

    题目描述 f(x) 是 x! 末尾是 0 的数量.(回想一下 x! = 1 * 2 * 3 * ... * x,且 0! = 1 ) 例如, f(3) = 0 ,因为 3! = 6 的末尾没有 0 : ...

  8. Pulsar客户端如何控制内存使用

    摘要 本文围绕一个常见的使用场景深入分析在高吞吐场景下,使用Pulsar客户端收发消息可能会遇到的若干问题.并以此为切入点,梳理一下Pulsar客户端在内存控制上所做的优化改进. 使用场景 假设这样一 ...

  9. .NET 开发的分流抢票软件,不做广告、不收集隐私

    前言 每年春节大家必备的抢票工具Bypass-分流抢票.分流抢票是一款免费无广适用于PC端的自动分流抢票软件. 分流抢票,是以用户为中心.人性化的抢票软件.不做广告.不做推广.不携带病毒.不收集隐私信 ...

  10. net core 中的[FromBody]

    一.针对.net core中post类型的api注意的地方(前提是Controller上加[ApiController]特性).默认是这个. 1.如果客户端Content-Type是applicati ...