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


    本文转自:http://www.cnblogs.com/artech/archive/2012/02/13/NumericPropertyValidation.html

    对于一个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

    作者:Artech 出处:http://artech.cnblogs.com/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
     
  • 相关阅读:
    目标检测梳理:基于深度学习的目标检测技术演进:R-CNN、Fast R-CNN、Faster R-CNN(转)
    4. 基于深度学习的目标检测算法的综述(转)
    2. 滑动窗口和 Bounding Box 预测(转)
    1. 初步认识目标定位、特征点检测、目标检测(转)
    redux (一)
    react-todoMVC脚手架
    SVN提示图标详解
    react ( 二 )
    react入门(一)
    JavaScript奇技淫巧
  • 原文地址:https://www.cnblogs.com/freeliver54/p/3981574.html
Copyright © 2020-2023  润新知