ASP.NET MVC:定制Numeric属性验证消息

简介:

对于一个Numeric属性/字段,ASP.NET MVC会自动进行数据类型的验证(客户端验证),以确保输入的是一个有效的数字,但是呈现在页面上的错误消息总是一段固定的文本:“The field {0} must be a number”,本篇提供一种解决方案使我们可以对此验证消息进行定制。

  目录

  一、针对Numeric属性/字段默认验证消息

  二、默认的验证消息来源于何处?

  三、通过自定义ModelValidatorProvider替换NumericModelValidator

  四、注册自定义ModelValidatorProvider

  一、针对Numeric属性/字段默认验证消息

  我们先来通过一个简单的例子来验证这个问题,为此我们定义了如下一个表示员工信息的Employee类型,其中代表年龄的Age属性类型为整型。

1: public class Employee

  2: {

  3: [Display(Name = "姓名")]

  4: public string Name { get; set; }

  5:

  6: [Display(Name = "性别")]

  7: public string Gender { get; set; }

  8:

  9: [Display(Name = "年龄")]

  10: public int Age { get; set; }

  11: }


 

  我们创建一个Model类型为Employee的View对某个元员工的信息进行修改。如下图所示,当我们输入一个非数字字符串作为Age字段的时候,验证错误信息显示为“The field 年龄 must be a number”,值得一提的是:当前线程的CurrentUICulture为zh-CN。

 

  二、默认的验证消息来源于何处?

  针对数字类型字段进行验证的是一个名称为NumericModelValidator的ModelValidator,不过这是个定义在System.Web.Mvc程序集中俄内部类型。如果采用Reflector查看其定义,可以发现用于返回错误消息的方法是一个名为MakeErrorString的静态方法。如下面的代码所示,作为错误消息的字符串来源于内嵌于程序集中的资源文件。

 1: internal sealed class NumericModelValidator : ModelValidator

  2: {

  3: //其他成员

  4: private static string MakeErrorString(string displayName)

  5: {

  6: return string.Format(CultureInfo.CurrentCulture, MvcResources.ClientDataTypeModelValidatorProvider_FieldMustBeNumeric, new object[] { displayName });

  7: }

  8: }


 

   NumericModelValidator最终是通过ClientDataTypeModelValidatorProvider这个一个ModelValidatorProvider提供的。

  三、通过自定义ModelValidatorProvider替换NumericModelValidator

  如果我们想改变内部类型NumericModelValidator的错误消息,可以通过将ClientDataTypeModelValidatorProvider提供的NumericModelValidator替换成另一个ModelValidator。在这里我们替换的是一个DataAnnotationsModelValidator,而它基于的ValidationAttribute是我们自定义的NumericAttribute。

  如下面的代码片断所示,内部类型NumericAttribute是ValidationAttribute的子类,并且实现了IClientValidatable接口。在这里我么只考虑客户端验证,所以重写的IsValid方法直接返回True,而GetClientValidationRules方法则返回一个包含一个验证类型为“number”的ModelClientValidationRule对象的集合。我们使用FormatErrorMessage方法格式化后的字符串作为ModelClientValidationRule的ErrorMessage属性。

1: internal class NumericAttribute : ValidationAttribute, IClientValidatable

  2: {

  3: public override bool IsValid(object value)

  4: {

  5: return true;

  6: }

  7: public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)

  8: {

  9: yield return new ModelClientValidationRule { ValidationType = "number", ErrorMessage = this.FormatErrorMessage(metadata.DisplayName)};

  10: }

  11: }


 

  现在我们需要做的就是通过一个自定义ModelValidatorProvider将ClientDataTypeModelValidatorProvider提供的NumericModelValidator替换成基于NumericAttribute的DataAnnotationsModelValidator,所以我们定义了一个直接继承自ClientDataTypeModelValidatorProvider的FilterableClientDataTypeModelValidatorProvider。如下面的代码所示,在重写的GetValidators方法中我们完成了针对NumericModelValidator的替换。对于被创建的NumericAttribute来说,我们指定的错误消息也定义在Resource文件中(为了提供多语言的支持),而基于zh的内容为“{0}必须是一个数字!”。

1: public class FilterableClientDataTypeModelValidatorProvider : ClientDataTypeModelValidatorProvider

  2: {

  3: public override IEnumerable GetValidators(ModelMetadata metadata, ControllerContext context)

  4: {

  5: var allValidators = base.GetValidators(metadata, context);

  6: var validators = new List();

  7: foreach (var v in allValidators)

  8: {

  9: if (v.GetType().Name != "NumericModelValidator")

  10: {

  11: validators.Add(v);

  12: }

  13: else

  14: {

  15: NumericAttribute attribute = new NumericAttribute{ ErrorMessage = Resources.FieldMustBeNumeric};

  16: DataAnnotationsModelValidator validator = new DataAnnotationsModelValidator(metadata, context, attribute);

  17: validators.Add(validator);

  18: }

  19: }

  20: return validators;

  21: }

  22: }


 

  四、注册自定义ModelValidatorProvider

  现在我们只需要通过ModelValidatorProvider的注册让我们自定义的FilterableClientDataTypeModelValidatorProvider替换默认的ClientDataTypeModelValidatorProvider。在Global.asax中,针对FilterableClientDataTypeModelValidatorProvider的注册可以通过如下的代码来完成。

1: public class MvcApplication : System.Web.HttpApplication

  2: {

  3: //其他成员

  4: protected void Application_Start()

  5: {

  6: //其他操作

  7: var clientDataTypeValidator = ModelValidatorProviders.Providers.OfType().FirstOrDefault();

  8: if (null != clientDataTypeValidator)

  9: {

  10: ModelValidatorProviders.Providers.Remove(clientDataTypeValidator);

  11: }

  12: ModelValidatorProviders.Providers.Add(new FilterableClientDataTypeModelValidatorProvider());

  13: }

  14: }


现在运行我们的程序就可以得到我们定制的错误消息了。










本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/781103,如需转载请自行联系原作者
目录
相关文章
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
528 5
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
320 7
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
328 0
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
270 0
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
445 0
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
592 0
|
开发框架 JSON .NET
|
SQL 开发框架 .NET
(20)ASP.NET Core EF创建模型(必需属性和可选属性、最大长度、并发标记、阴影属性)
(20)ASP.NET Core EF创建模型(必需属性和可选属性、最大长度、并发标记、阴影属性)
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
634 5
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
221 0