当前位置 博文首页 > 文章内容

    numeric,针对Numeric属性或字段默认验证消息

    作者:Tan09wlll 栏目:Tan的日记 时间:2021-02-28 17:59:12

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



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

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

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

         针对数字类型字段进行验证的是一个名称为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: }

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