网摘1:

在使用Entity Framework 的Database frist或model first时,直接加attribute到modle类上是太现实也不合理的,因为model类是自动生成的,重新生成后会覆盖自己的修改。一个比较合理做法,就是用 partial class的方式来实现。

比如有一个Model类: Movie。那我们就可以添加一个局部类文件,局部类的内容如下:

 1 using System.ComponentModel.DataAnnotations;
namespace Movies.Models
{
[MetadataType(typeof(MovieMetadata))]
public partial class Movie
{
class MovieMetadata
{
[Required(ErrorMessage="Titles are required")]
public string Title { get; set; }
[Required(ErrorMessage="The Price is required.")]
[Range(,,ErrorMessage ="Movies cost between $5 and $100.")]
public decimal Price { get; set; }
}
}
}

通过在这个局部类文件中添加需要的验证属性就可以了。

网摘2:

在MVC的Model中,我们可以定义很多与视图相关的元数据,这些元数据对我们开发视图起着相当重要的作用,特别是在数据验证方面。这些元数据一般情况下我们是不会定义在业务实体(或持久化实体)上面,所以很多情况下,我们会需要开发两种实体:View Model和Business Model。这样就造成,在Action与View的沟通当中,我们需要使用View Model,然后在业务逻辑处理时,我们需要再将View Model映射到Business Model,这将会使我们的开发框架变得繁琐。因为一般情况下,View Model和Business Model在很多情况下,都是很雷同的对象,只是View Model会有很多与视图相关的元数据。在这种情况下,只要我们能把View Model作为Business Model的元数据描述对象(MetadataType)来使用,而不直接参与Action与View的沟通,让这些工作都由Business Model来承担,这样就可以有效的避免很多重复工作。

在System.ComponentModel.DataAnnotations内部,提供了MetadataTypeAttribute这个标签,让我们可以为Business Model指定它对应的视图元数据类型。特别是当我们使用LINQ2SQL、EF等框架来生成实体框架时,我们可以以partial类的形式来提供它对应的视图元数据类型:

这样做在大多数情况下是没有问题的。但是仅仅是这样,还不能解决所有问题。一般情况下Business Model和MetadataType是不在同一个Assembly里面,这时候你就无法以partial类的形式来扩展Business Model。所以我们就需要有一套机制来延迟注册Business Model与MetadataType的映射关系。通过MVC源码的分析,我们可以通过扩展DataAnnotationsModelMetadataProvider的

GetTypeDescriptor方法来解决这个问题。
首先,我们先定义一个Business Model与MetadataType的映射容器:

这个容器非常简单,我们只是定义了一个hashtable来保存它们的映射关系。然后,我们从DataAnnotationsModelMetadataProvider继承一个新的类,重写GetTypeDescriptor方法:

接下来要做的事情就是把CustomDataAnnotationsModelMetadataProvider注册到系统中,用它来代替原来的DataAnnotationsModelMetadataProvider,在Global.asax添加如下代码:

最后需要在映射容器中,添加你希望的映射关系:

通过这样的映射,我们就可以完全解放Business Model对MetadataType的依赖了。

后记: 在调试这个扩展的过程当中,出现了一个相当低级的错误,花了我几个小时的时间。话说提交的数据中有一个名为site的字符串(在Route.Values里面),同时我在Action的参数中,定义的是一个名为site的复杂类型。程序在运行过程中,始终提示异常:类型无法转换。因为我怀疑是我扩展了MetadataType引发的问题,所以拼命的在那边调试,始终没有找到原因。最后还原所有的代码,问题依旧,才让我走到正确的方向上,冤枉死我了。

补充:扩展DataAnnotationsModelMetadataProvider,只能获得DataAnnotations中与UI相关的元数据。要获得与Validation相关的元数据,还需要扩展DataAnnotationsModelValidatorProvider,扩展方式一样,都是重写GetTypeDescriptor方法。

使用分部类给Models添加验证Attributes的更多相关文章

  1. Asp.net mvc + .net ef database first 或 model first 时如何添加验证特性

    今天有个同事问到,在使用Entity Framework 的Database frist或model first时,怎么在model上添加验证的特性? 因为此时的Model是是VS 工具怎么生成的,直 ...

  2. database first表更新一个表会更新所有的model,包括添加验证代码,解决办法

    因为model类是自动生成的,重新生成后会覆盖自己的修改.一个比较合理做法,就是用 partial class的方式来实现. 比如有一个Model类: Movie.那我们就可以添加一个局部类文件,局部 ...

  3. 利用partial关键字声明分部类和分部方法

    一.分部类 1.分部类的定义:简单的说,分部类就是把一个类拆分成多个类,每个类文件只包含其中的一部分,类.结构.接口.方法都可以拆分,在定义的时候加上partial修饰符. 注意:分部类必须属于同一命 ...

  4. 创建ASP.NET Core MVC应用程序(6)-添加验证

    创建ASP.NET Core MVC应用程序(6)-添加验证 DRY原则 DRY("Don't Repeat Yourself")是MVC的设计原则之一.ASP.NET MVC鼓励 ...

  5. [Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则

    目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5 ...

  6. C# 分部类与分部方法

    一.定义 分部方法是指能够使编码人员跨多个代码文件实现类型的语法.简而言之.它可以让我们在一个文件中构建方法原型,而在另一个文件中实现 使用分部方法和分部类需要使用关键词partial,且紧靠在cla ...

  7. ASP.NET MVC 学习7、为Model Class的字段添加验证属性(validation attribuate)

    Adding Validation to the Model ,在Model中添加数据验证 参考:http://www.asp.net/mvc/tutorials/mvc-4/getting-star ...

  8. C# partial修饰符_分部类_分部方法

    今天翻了翻书,发现自己还是遗留下不少基础性的东西,老实说,不管一些基础的东西用到不用到都很应该了解,因为基础毕竟学习量不是很大. 一.分部类 什么是部分类呢?简单来说就是将一个类型或方法拆分到两个或多 ...

  9. ASP.NET MVC 5 学习教程:添加验证

    原文 ASP.NET MVC 5 学习教程:添加验证 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 通过控 ...

随机推荐

  1. mybatis0211 mybatis和spring整合

    1mybatis和spring整合 1.1 mybaits和spring整合的思路 .让spring管理SqlSessionFactory .让spring管理mapper动态代理对象和dao. 使用 ...

  2. online ddl 工具之pt-online-schema-change

      MySQL ddl 的问题现状 在运维mysql数据库时,我们总会对数据表进行ddl 变更,修改添加字段或者索引,对于mysql 而已,ddl 显然是一个令所有MySQL dba 诟病的一个功能, ...

  3. 僵尸进程 图解 分布式 LINUX内核

    http://blog.csdn.net/chdhust/article/details/11872467 服务器进程为何通常fork()两次

  4. Android的属性系统

    http://blog.csdn.net/jerryutscn/article/details/5519423 Android的属性系统 每条属性包含了名字和其对应的值,两者都用字符串来描述.Andr ...

  5. Android进阶笔记11:ListView篇之ListView显示多种类型的条目(item)

    ListView可以显示多种类型的条目布局,这里写显示两种布局的情况,其他类似. 1. 这是MainActivity,MainActivity的布局就是一个ListView,太简单了这里就不写了,直接 ...

  6. iOS 成员变量,实例变量,属性变量的区别,联系

    在ios第一版中: 我们为输出口同时声明了属性和底层实例变量,那时,属性是oc语言的一个新的机制,并且要求你必须声明与之对应的实例变量,例如: 注意:(这个是以前的用法) @interface MyV ...

  7. html中input type=file 改变样式

    <style> #uploadImg{ font-size:12px; overflow:hidden; position:absolute} #file{ position:absolu ...

  8. 关于 VS2012 创建 MVC4 Empty 项目的一个小问题

    今天下午发现一个新建的项目工作异常,主要表现为应该返回JSON的Action没有返回JSON字符串,而是返回了JsonResult的对象名,即字符串“System.Web.Mvc.JsonResult ...

  9. 在Flex4中使用RemoteObjectAMF0来连接fluorine网关 转

    转http://vipnews.csdn.net/newscontent.aspx?pointid=2011_04_21_142132661 RemoteObjectAMF0是一个开源组件,可以很方便 ...

  10. extjs的调试方法

    1.使用extjs自带的测试工具 第一步:在ExtJS下载的资源包中,找到debug.js,将JS文件导入实际要运行的HTML或者JSP页面上 第二步:在有关JS文件代码中嵌入Ext.log('自定义 ...