最近几天看了一下Asp.net MVC2的model验证,初始的感觉让我眼前一亮,于是去看了看它的源代码,Validation和Metadata部分应该是从Dynamic Data哪里得到的灵感,一切似乎都那么美好,网上关于如何使用的文章页很多,但是随后的一段经历让我对Validation部分的代码和设计产生了很大的不满,它所夸赞的可以很容易与其它验证框架的集成其实也并不是那么容易,下面我就来说说为什么我会对它不满:

当前的MVC的验证是在Model的属性上加入Attribute,如下:

代码
 1
 2     [DisplayColumn("UserName", "Password", true)]
 3     public class LogOnModel
 4     {
 5         [Required]
 6         [DisplayName("User name")]
 7         public string UserName { get; set; }
 8
 9         [Required]
10         [DataType(DataType.Password)]
11         [DisplayName("Password")]
12         public string Password { get; set; }
13
14         [DisplayName("Remember me?")]
15         public bool RememberMe { get; set; }
16
17         public EmbeddedClass Embedded { get; set; }
18     }
19
20     public class EmbeddedClass
21     {
22         [DisplayName("Try count")]
23         [Range(3, 5)]
24         public int TryCount { get; set; }
25
26         [DisplayName("Non Model")]
27         public string NonModel { get; set; }
28     }

但是随之而来的问题也来了,那就是

1。 过多的属性(Attribute)使得Model过于臃肿,

2。一个Model代表的是一个类,它的实例应该有自己的Attribute, 如果是把Attribute加在了Model上,那么所有的实例只能使用同样的Attribute,在我们的程序中很多的类经常是在很多函数中使用,并且每个函数会有不同的验证要求,

3。 如果是简单类型的参数,就不能做一些验证了,譬如范围验证。

4。 如果类中的属性是非值类型的(非值类型,不包括string),那么验证并不会去验证这个属性实例内部的属性,譬如我上面的Embedded 属性。

这些让我有了一个自己的想法,所以于是想把这些验证放在配置文件中,于是仔细的看了MVC2绑定和验证部分的源代码,想看看如何扩展。我比较懒,DefaultModelBinder 这个类是asp.net mvc2 中用于绑定数据和调用验证的最重要的类,其中Model的验证部分是在 函数OnModelUpdated中被调用的,

1         protected virtual void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
 2             Dictionary<string, bool> startedValid = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
 3
 4             foreach (ModelValidationResult validationResult in ModelValidator.GetModelValidator(bindingContext.ModelMetadata, controllerContext).Validate(null)) {
 5                 string subPropertyName = CreateSubPropertyName(bindingContext.ModelName, validationResult.MemberName);
 6
 7                 if (!startedValid.ContainsKey(subPropertyName)) {
 8                     startedValid[subPropertyName] = bindingContext.ModelState.IsValidField(subPropertyName);
 9                 }
10
11                 if (startedValid[subPropertyName]) {
12                     bindingContext.ModelState.AddModelError(subPropertyName, validationResult.Message);
13                 }
14             }
15         }

在这个函数中,ModelValidator.GetModelValidator(bindingContext.ModelMetadata, controllerContext),有这么一句,也就是获得ModelValidator, 悲剧就在此函数中打开这个函数看看:

代码

1 public static ModelValidator GetModelValidator(ModelMetadata metadata, ControllerContext context) {
 2             return new CompositeModelValidator(metadata, context);
 3         }
 4
 5         public abstract IEnumerable<ModelValidationResult> Validate(object container);
 6
 7         private class CompositeModelValidator : ModelValidator {
 8             public CompositeModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
 9                 : base(metadata, controllerContext) {
10             }
11
12             public override IEnumerable<ModelValidationResult> Validate(object container) {
13                 bool propertiesValid = true;
14
15                 foreach (ModelMetadata propertyMetadata in Metadata.Properties) {
16                     foreach (ModelValidator propertyValidator in propertyMetadata.GetValidators(ControllerContext)) {
17                         foreach (ModelValidationResult propertyResult in propertyValidator.Validate(Metadata.Model)) {
18                             propertiesValid = false;
19                             yield return new ModelValidationResult {
20                                 MemberName = DefaultModelBinder.CreateSubPropertyName(propertyMetadata.PropertyName, propertyResult.MemberName),
21                                 Message = propertyResult.Message
22                             };
23                         }
24                     }
25                 }
26
27                 if (propertiesValid) {
28                     foreach (ModelValidator typeValidator in Metadata.GetValidators(ControllerContext)) {
29                         foreach (ModelValidationResult typeResult in typeValidator.Validate(container)) {
30                             yield return typeResult;
31                         }
32                     }
33                 }
34             }
35         }

它尽然是直接构造了一个CompositeModelValidator,这个CompositeModelValidator还是私有的,没有用工厂模式,CompositeModelValidator不能继承重写,也就是说第一、如果想验证,那就只能是验证属性,不能验证简单类型(当然有其他办法可以解决这个问题),第二、也就是我上面提到的第四点,如果属性是非值类型,对不起不能验证其内部的属性,第三、对于验证一个Model那些部分我控制不了,只能是它的属性。这三点使我我本来想扩展MVC2的验证部分,也就是继承自ModelValidator,看来是不行了,只能自己写新的验证部分了,只觉得MVC2有点失败,比其MVC1的成功,它有点让我失望。

当然,这并不代表了,我上面所说的那些就做不了,我会在下一篇中给出利用Enterprise Library 的验证来实现 扩展。

关注技术文章飞秋:http://www.freeeim.com/,24小时专业转载。

【飞秋】Asp.net MVC2 model验证 看似美好,实则让人失望。相关推荐

  1. 【转】【Asp.Net MVC】asp.net mvc Model验证总结及常用正则表达式

    本文属转载,来源:http://www.byywee.com/page/M0/S868/868615.html关于Model验证官方资料:http://msdn.microsoft.com/zh-cn ...

  2. ASP.NET MVC3 Model验证总结 @Html.ValidationSummary(true)

    http://www.wyjexplorer.cn/Post/2012/8/3/model-validation-in-aspnet-mvc3 ASP.NET MVC3中的Model是自验证的,这是通 ...

  3. [zz]ASP.NET MVC2框架验证学习笔记

    ASP.NET中的框架验证方法1: 1.模型定义 public class User { [Required(ErrorMessage="用户名不能为空!!")]        [ ...

  4. 机关里看似讨巧实则毁人设的8种行为

    每个进入公务员队伍的小伙伴,大概都耳闻目睹过一些"机关厚黑学",机关的水如何深,我们又该如何动用技巧,保护自己.谋求利益,为自己的立足和发展铺平道路. 于是,像下列的这种种看起来很 ...

  5. 这就是飞秋下载早期的学习生涯

    这就是飞秋下载早期的学习生涯,深深地体现出陶瓷的时代特色.这段时间hongjin2的生活是困苦的,心情是苦闷的,但学习热情却是无以伦比的.现在hongjin2一个人拥有两台奔四电脑,随时可上互联网获取 ...

  6. 『飞秋』关于ASP.NET MVC+Repository+Service架构的一些思考

    『飞秋』关于ASP.NET MVC+Repository+Service架构的一些思考 看了一些ASP.NET MVC开源项目后的一些想法,关于ASP.NET MVC+Repository+Servi ...

  7. ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidator

    对于ASP.NET MVC基于标注特性的Model验证,很多人只知道应用在数据类型及其属性上用于定义验证规则和错误消息的ValidationAttribute.通过<ASP.NET MVC以Mo ...

  8. ASP.NET MVC以ModelValidator为核心的Model验证体系: ModelValidator

    旨在为目标Action方法的执行绑定输入参数的Model绑定过程伴随着对Model的验证.借助相应的验证特性,我们可以直接以声明的方式在Model类型上定义验证规则,这些规则将会作为Model元数据的 ...

  9. 【飞秋】ASP.NET 之 常用类、方法的超级总结,并包含动态的EXCEL导入导出功能,奉上类库源码

    最近闲了,花点几天时间将项目中常用的一些类.方法做了一下总结,希望对大家有用. 实用类:UtilityClass 包含如下方法 判断对象是否为空或NULL,如果是空或NULL返回true,否则返回fa ...

最新文章

  1. asp.net访问sqlserver获取数据、IsPostBack属性和VS可视化调试的概念
  2. JS笔记(20): JS中的同步编程和异步编程
  3. 《网络安全原理与实践》一2.1 安全区介绍
  4. 敏捷回顾会议的套路与实践分享
  5. ftp服务器新建虚拟目录,ftp服务器 虚拟目录
  6. 嵌入式基于Linux电机控制,基于嵌入式arm+linux平台的直流电机调速控制系统.pdf
  7. Hyperledger Fabric介绍
  8. php friso,php binding 不兼容php7
  9. Scrum立会报告+燃尽图(Beta阶段第一次)
  10. 数据库配置不当,8.8亿条医疗记录遭泄露
  11. 数据库基础:什么是MySQL?
  12. 酷客多小程序携手Richly network Pte Led正式进军新加坡市场
  13. 设计模式--C++学习(4)
  14. node.js的安装和Vue.js脚手架的安装
  15. 读书笔记:《关于上班这件事--自序·朱德庸》
  16. 条款20:宁以pass-by-reference-to-const替换pass-by-value
  17. 【python实战】---- 30行代码提取个人值班表
  18. Python处理二进制数据文件(大小100M以上),逐步更新
  19. 【】每日360题,2019.11.05日21点财会类考试习题答案
  20. KFS replicator安装(Mysql-KES)

热门文章

  1. Spring 3 MVC深入研究
  2. 极光:2021年移动互联网母婴亲子行业研究报告
  3. 正月初四 | 2月15日 星期一 | 特斯拉否认推出16万元更便宜车型;中国首位百亿票房导演诞生;冷光烟花纳入烟花爆竹管理...
  4. 面向人工智能“新基建”的知识图谱行业白皮书
  5. 利用这些心理学效应,轻松拿到满意offer
  6. 太多产品人死于汇报!
  7. python如何爬取sci论文中所需的数据_sci论文中的科研数据处理方法
  8. python连接mysql_Python 连接mysql与impala
  9. 2015年《大数据》高被引论文Top10文章No.5——对大数据的再认识
  10. 作者:吴琳(1974-),男,博士,国防大学信息作战与指挥训练教研部教授,主要研究方向为复杂系统与网络、战争复杂系统建模。...