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

疑问产生

在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. 【Java 温故而知新系列】基础知识-02 数据基本类型

    1.Java基本数据类型 Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同大小的内存空间. 基本数据类型 数值型:整数类型(byte,short,int,lon ...

  2. 在 Vercel 部署随机图 API

    在本文中,将详细介绍如何在 Vercel 平台上部署一个具有分类功能的随机图片 API.通过这个 API,用户可以根据不同的分类获取随机图片链接,并且还可以从所有分类中随机获取一张图片. 项目结构 首 ...

  3. Linux服务器环境安装mysql

    背景 1.安装环境:kvm虚拟机 2.运行环境:linux 3.架构:x86 4.安装mysql版本:mysql-5.7 1.安装准备 # Mysql官网 https://downloads.mysq ...

  4. Solution -「NOI 2017」「洛谷 P3825」游戏

    \(\mathscr{Description}\)   Link.   给大家看个乐子: link, 懒得概括题意啦. \(\mathscr{Solution}\)   对于没有 X 的情况, 显然可 ...

  5. TbSchedule任务调度管理框架的整合部署

    一.前言 任务调度管理作为基础架构通常会出现于我们的业务系统中,目的是让各种任务能够按计划有序执行.比如定时给用户发送邮件.将数据表中的数据同步到另一个数据表都是一个任务,这些相对耗时的操作通过任务调 ...

  6. OS:RAID

    什么是RAID? 独立磁盘冗余阵列[磁盘阵列](Redundant Arrays of Independent Disks,RAID) 磁盘阵列: 由很多块独立的磁盘,组合成一个容量巨大的磁盘组,利用 ...

  7. Kotlin:反引号中的函数命名、匿名函数、函数类型与隐式返回

  8. C/C++ 以及 Rust 中的 getch() 实现

    getch 是一个在 C 语言编程中常用的函数,用于从键盘读取一个字符,但不回显到屏幕上. 在 Windows 环境下,getch 实现通常包含在 <conio.h> 头文件中.需要注意的 ...

  9. manim边学边做--通用变换

    在 Manim 动画制作中,Transform.TransformFromCopy.ReplacementTransform和Restore是四个通用的对象变换动画类. 这几个类能够实现从一个对象到另 ...

  10. V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库

    前言 今天大姚给大家分享一个基于 .NET MAUI 的开源免费.开箱即用的UI组件库:V-Control. V-Control项目介绍 V-Control 是一个适用于 .NET MAUI 的开源( ...