当前位置: 首页 > news >正文

[ASP.NET MVC]如何定制Numeric属性/字段验证消息

[ASP.NET MVC]如何定制Numeric属性/字段验证消息
原文: [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。

image

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

针对数字类型字段进行验证的是一个名称为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<ModelClientValidationRule> 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<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
   4:     {           
   5:         var allValidators = base.GetValidators(metadata, context);
   6:         var validators = new List<ModelValidator>();
   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<ClientDataTypeModelValidatorProvider>().FirstOrDefault();
   8:         if (null != clientDataTypeValidator)
   9:         {
  10:             ModelValidatorProviders.Providers.Remove(clientDataTypeValidator);
  11:         }
  12:         ModelValidatorProviders.Providers.Add(new FilterableClientDataTypeModelValidatorProvider());
  13:     }
  14: }

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

image

posted on 2014-06-28 13:40 NET未来之路 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/3813276.html

相关文章:

  • HTML中Select的使用具体解释
  • 使用Spring整合javaMail发用邮件
  • v​n​c​服​务​​安​装​与配置
  • 布局文件提示错误“No orientation specified, and the default is horizontal. This is a common so...”...
  • BZOJ-2743 采花
  • vs2012 发布网站丢失文件
  • hdu 1576扩展欧几里得算法
  • WCF入门教程:WCF基础知识问与答(转)
  • 《海量数据库解决方式》读后感
  • Winsock网络编程笔记(1)----入门
  • php中body下出现莫名空白字符
  • 关于ios 运行时 介绍的比较详细的帖子
  • IIS应用程序池监控
  • 理解 backbone.js 中的 bind 和 bindAll 方法,关于如何在方法中指定其中的 this,包含apply方法的说明...
  • 距离变换DT
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 《深入 React 技术栈》
  • 【Amaple教程】5. 插件
  • 【css3】浏览器内核及其兼容性
  • 10个最佳ES6特性 ES7与ES8的特性
  • Angular4 模板式表单用法以及验证
  • express如何解决request entity too large问题
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • js中forEach回调同异步问题
  • node-glob通配符
  • React-生命周期杂记
  • select2 取值 遍历 设置默认值
  • 服务器之间,相同帐号,实现免密钥登录
  • 坑!为什么View.startAnimation不起作用?
  • 聊聊directory traversal attack
  • 通过npm或yarn自动生成vue组件
  • 新书推荐|Windows黑客编程技术详解
  • 一文看透浏览器架构
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (1)虚拟机的安装与使用,linux系统安装
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转)项目管理杂谈-我所期望的新人
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • .describe() python_Python-Win32com-Excel
  • .NET Core 中的路径问题
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .net framework4与其client profile版本的区别
  • .net MySql
  • .Net 路由处理厉害了
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .Net语言中的StringBuilder:入门到精通
  • .NET中两种OCR方式对比
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)