ASP.NET MVC 2 模型验证

【原文地址】ASP.NET MVC 2: Model Validation 
【原文发表日期】 Friday, January 15, 2010 4:14 AMweb

除了写博客外,我如今还使用Twitter发短贴和共享连接。请经过twitter.com/scottgu跟随我。正则表达式

这是我针对即将发布的ASP.NET MVC 2所撰写的贴子系列的第二篇,这个博客贴子将讨论 ASP.NET MVC 2中一些验证方面的改进。数据库

ASP.NET MVC 2 验证

对用户输入的验证以及强制业务规则/逻辑是大多数web应用的核心需求。ASP.NET MVC 2包含了一堆新的特性,显著地简化了对用户输入的验证以及在模型/视图模型中对验证逻辑的强行实施。这些特性是这样设计的,验证逻辑老是在服务器上执行的,也能够选择在客户端经过JavaScript来执行。ASP.NET MVC 2中的验证设施和特性这般设计,以便:安全

1) 开发人员能够轻易地利用内置于.NET框架中的DataAnnotation验证支持。DataAnnotation提供了一个很是简便的方式,使用最少的代码在对象和属性上用声明的方式添加验证规则。服务器

2) 开发人员能够集成他们本身的验证引擎,或者利用现有的验证框架,象Castle验证器或EntLib验证库。ASP.NET MVC 2的验证特性是设计来在利用新的 ASP.NET MVC 2的验证设施(包括客户端验证,模型绑定验证等等)的同时,简化任何类型的验证架构的插入的。架构

这意味着,在常见的应用场景中启用验证是极其容易的,同时对更高级的场景则还能保持极好的灵活性。mvc

使用ASP.NET MVC 2 和 DataAnnotation来启用验证

让咱们在ASP.NET MVC 2中来全程示范一个简单的CRUD场景,利用新的内置DataAnnotation验证支持。具体来讲,让咱们来实现一个“Create”表单来容许用户输入朋友的数据:app

image

咱们想要确保在保存到数据库以前,输入的信息是合法的,若是不合法,就显示合适的错误消息:框架

image

我 们想要使得这个验证同时在服务器端和客户端(经过 JavaScript)发生。咱们还想要确保咱们的代码遵照DRY原则(Don't Repeat Yourself,不重复本身),意味着咱们应该只在一处实施验证规则,而后使得咱们的控制器,action方法和视图来兑现这个承诺。asp.net

在下面,我将使用VS 2010,用ASP.NET MVC 2来实现上面的场景。你也可使用VS 2008及ASP.NET MVC 2来实现彻底同样的场景。

第一步: 实现FriendsController (一开始没有验证)

咱们首先在一个新的ASP.NET MVC 2项目中加一个简单的“Person”类,象下面这样:

image

它有四个属性(是用C#的自动属性支持实现的, 在VS 2010中VB也支持自动属性了,哎!)。

而后在项目中加一个 “FriendsController” 控制器类,呈示2个 “Create” action方法。第一个action方法是在对/Friends/Create URL的HTTP-GET请求进来时调用的,它会显示一个空白的表单,用来输入我的数据。第二个action方法是在对/Friends/Create URL的HTTP-POST请求进来时调用的。它会将提交的表单输入映射到一个Person对象,核实没有绑定错误发生,若是是合法的,最终会将数据保存 到数据库中去(在本教程的后面咱们会实现相关的数据库工做)。若是提交的表单输入是不合法的,该action方法会从新显示带有错误的表单:

image

在实现了控制器以后,能够在Visual Studio中在其中一个action方法中右击,选择 “添加视图”命令, 这会调出 “添加视图” 对话框。选择自动生成传入对象为Person的“Create”视图:

image

而后Visual Studio会在咱们项目的\Views\Friends\目录中,生成一个含有框架代码(scaffolded)的Create.aspx视图文件。注意下面,它利用了ASP.NET MVC 2中新的强类型HTML辅助方法(促成了更好的intellisense和编译时检查支持):

image

如今,当咱们运行该应用,访问 /Friends/Create URL时,咱们将获得一张能够输入数据的空白表单:

image

但,由于咱们尚未在应用中实现任何验证,谁也没法阻止咱们在表单中键入假的输入,将其提交到服务器去。

第二步: 使用DataAnnotation来启用验证

如今,让咱们来更新应用,执行一些基本的输入验证规则。咱们将在咱们的Person模型对象上实现这些规则,而不是在控制器或视图中实现。在Person对象上实现这些规则的好处是,这将确保这些验证在应用中任何使用Person对象的场景中都会被执行(例如,若是后来添加了编辑场景的话)。这将帮助确保咱们将代码保持DRY,避免在多处重复这些规则。

ASP.NET MVC 2 容许开发人员轻松地在模型或视图模型类上添加声明式验证特性,而后ASP.NET MVC在应用中实施模型绑定操做时,这些验证规则就会被自动执行。为看其例子,让咱们更新Person类,在其中加几个验证特性。这么作,在文件的顶部加 一个对“System.ComponentModel.DataAnnotations”命名空间的 “using” 语句,而后在Person的属性上饰于[Required], [StringLength], [Range], 和 [RegularExpression] 验证特性(这几个特性都是在那个命名空间中实现的):

image

注: 在上面咱们明式指定了错误信息字符串,你也能够在资源文件中定义它们,或者按进来的用户的语言/文化作本地化,你能够在这里了解如何本地化验证错误消息。

既然咱们加了验证特性到Person类上,让咱们来从新运行咱们的应用,看在键入假的数值,将其提交回服务器时会发生什么:

image

注意上面咱们的应用如今有一个蛮好的出错体验了。带不合法输入的文本元素以红色高亮显示,咱们指定的验证错误消息也显示给了用户。表单还保留用户原先输入的数据,这样他们不用从新填写什么。但,你也许会问,怎么会是这样?

要理解这个行为,让咱们看一下处理咱们表单的POST场景的Create action方法:

image

在 咱们的HTML表单被提交回服务器时,上面的方法就会被调用。由于该action方法接受一个“Person” 对象为参数,ASP.NET MVC会建立一个Person对象,自动地将进来的表单输入数值映射到该对象上。做为该过程的一部分,ASP.NET MVC还会检查该Person对象上的DataAnnotation验证特性是否合法。若是一切都合法,那么咱们代码中的 ModelState.IsValid检查就会返回真值,在这种情形下,咱们(最终)将把该Person对象保存到数据库中,而后从新定向回到主页上去。

但若是Person对象上有任何验证错误的话,咱们的action方法就会以该不合法Person对象的数据从新显示表单,这是经过上面代码片断中最后一行代码实现的。

然 后,错误消息就会显示在咱们的视图中,由于咱们的Create表单在每个<%= Html.TextBoxFor() %>辅助方法的调用旁边都有一个<%= Html.ValidationMessageFor() %>辅助方法调用。Html.ValidationMessageFor() 辅助方法会针对传入视图的任何不合法的模型属性输出合适的错误消息:

image

这个模式/方式有一个好处,就是很是容易配置,它还容许咱们轻松地添加或改变咱们Person类上的验证规则,而没必要改变控制器或视图中的任何代码。这个在一个地方指定验证规则,而后在全部的地方都会被承诺和遵照的能力,容许咱们以最少的努力快速地发展咱们的应用和规则,而且将代码保持在很是DRY的程度。

第三步: 启用客户端验证

目前咱们的应用只能作服务器端的验证,这意味着咱们的终端用户须要将表单提交到服务器才能看到任何验证错误消息。

ASP.NET MVC 2的验证架构中同样很是酷的东西是,它同时支持服务器端  客户端验证。为启用这个功能,咱们要作的就是在视图中添加2个 JavaScript引用,编写一行代码:

image

在咱们添加了这三行后,ASP.NET MVC 2 就会使用咱们加到Person类上的验证元数据,为咱们链接好客户端JavaScript验证逻辑。这意味着,当用户使用tab键跳出一个不合法的输入元素时,就会获得瞬时的验证错误。

要在咱们的朋友应用中看客户端JavaScript支持的实战例子的话,让咱们从新运行应用,在前三个文本框中填入合法的数值,而后尝试点击“Create(建立)”。注意,咱们没必要访问服务器就会获得遗漏值的瞬时错误消息:

image

若是咱们输入一些不是合法的email的字符话,错误消息就会瞬时从“Email Required (Email是个必需值)” 变为 “Not a valid email (email不合法)”(这是咱们将规则加到Person类上时指定的错误消息):

image

在输入一个合法的email时,错误消息就是瞬时消失,文本框背景色也会恢复到正常的状态:

image

好事是,咱们没必要编写本身的任何定制JavaScript就能启用上面的验证逻辑。咱们的验证代码仍是那么DRY,咱们能够在一个地方指定规则,而后在整个应用中获得执行,同时在客户端和服务器端。

注意,为安全的缘由,服务器端验证规则老是执行的,即时你启用了客户端支持。这避免黑客尝试绕过客户端规则,哄骗攻击(spoof)你的服务器。

ASP.NET MVC 2中的客户端JavaScript验证支持可与你在ASP.NET MVC应用中使用的任何验证框架/引擎协做,它并不要求你使用 DataAnnotation 验证方式,全部的基础设施是独立于 DataAnnotation的,能够与Castle验证器, EntLib验证应用块,或你选择使用的任何定制验证方案协做使用。

若是你不想使用咱们的客户端JavaScript文件,你也能够将其替换成jQuery验证插件,而使用那个库。 ASP.NET MVC Futures下载还包括针对ASP.NET MVC 2服务器端验证框架启用jQuery验证的支持。

第四步: 建立自定义的[Email]验证特性

.NET 框架中的System.ComponentModel.DataAnnotations命名空间包括了众多可为你所用的内置验证特性。咱们在上面的例子中 使用了其中的四个:[Required], [StringLength], [Range], 和 [RegularExpression]。

你 也能够定义本身的定制验证特性,而后应用它们。你能够经过继承自System.ComponentModel.DataAnnotations命名空间中 的ValidationAttribute基类,定义彻底定制的特性。或者,你也能够选择继承自任何现有的验证特性,若是你只想要扩展它们的基本功能的 话。

例如,为帮助清理咱们Person类中的代码,咱们也许想要建立一个新的[Email]验证特性,将检查合法email的正则表达 式封装起来。要这么作的话,咱们只要象这样继承自RegularExpressionAttribute基类,而后用合适的email正则表达式调用 RegularExpressionAttribute基类的构造器:

image

而后将Person类更新成使用咱们新的[Email]验证属性,换掉咱们先前使用的正则表达式,这使得咱们的代码更干净,封装也更好:

image

在建立定制的验证特性时,你还能够指定在服务器端以及在客户端经过JavaScript执行的验证逻辑。

除 了建立可施用于对象上个别属性的验证特性外,你还能够将验证特性施用于类的层次,这容许你对一个对象中的多个属性实施验证逻辑。要看实战例子的话,你能够 参阅包含在默认ASP.NET MVC 2应用项目模板中AccountModels.cs/vb文件中的“PropertiesMustMatchAttribute” 定制特性(在VS 2010中作 文件->新ASP.NET MVC 2 Web项目,而后查询该类)。

第五步: 持久化到数据库中

如今让咱们来实现将朋友数据保存到数据库所需的逻辑。

image 

至 此,咱们只用了平白的(plain-old)C#类(有时称为“POCO” 类, 即 “plain old CLR (or C#) object”)。咱们可使用的一个方案是,编写一些单独的持久代码,将这咱们已经编写好的现有类映射到数据库去。目前象NHibernate这样的对 象关系映射(Object relational mapping - ORM)方案很是地好支持这样的POCO/PI风格的映射。随.NET 4发布的ADO.NET实体框架(Entity Framework - EF)也支持POCO / PI映射,并且就象NHibernate,EF也能启用以“只用代码(code only)”的方式(没有映射文件,也不须要设计器)定义持久性映射的能力。

若是咱们的Person对象以这种方式映射到数据库的话,咱们不用对Person类作任何改动,也不用改动任何验证规则,它还会继续无缺地工做。

但假如咱们要使用图形工具来作ORM映射的话,怎么办?

今天使用Visual Studio的许多开发人员并不编写他们本身的ORM映射/持久逻辑,而是使用Visual Studio中内置的设计器来帮助管理这样的映射逻辑。

使 用DataAnnotation(或者任何其余形式的基于特性的验证)时一个常常问起的问题是,“若是你手头的模型对象是由GUI设计器建立/维护的话, 你该如何施用这些特性?”。例如,假如与相似咱们至此为止一直在使用的POCO风格的Person类不一样,咱们而是在Visual Studio中经过象LINQ to SQL 或 ADO.NET EF设计器这样的GUI映射工具定义/维护咱们的Person类的话,该怎么办呢:

image

上 面是一张屏幕截图,展现了在VS 2010中使用ADO.NET EF设计器定义的一个Person类。上方的窗口定义了Person类,下方的窗口展现了该类的属性是如何映射到数据库中的“People”表的映射编辑 器。当你在设计器上点击保存时,它会自动为你在项目中生成一个Person类。这很棒,但每次你作了改动,点击保存时,它就会从新生成 Person 类,这会致使你在对象上面声明的任何验证特性的丢失。

将 额外的基于特性的元数据(象验证特性)施加到由VS设计器自动生成/维护的类的一个方法是,采用一个咱们称之为“伙伴类(buddy classes)”的技术。基本上来讲,你建立另一个类,包含你的验证特性和元数据,而后经过将 “MetadataType”特性施加到一个与工具生成的类一块儿编译的partial类上,将其与由设计器生成的类链接起来。例如,若是咱们想要将咱们前 面用到的验证规则施加到由LINQ to SQL 或 ADO.NET EF设计器维护的Person类上,咱们能够更新咱们的验证代码,使其存在于一个单独的“Person_Validation”类上,使用象下面这样的代 码将其链接到由VS建立的“Person”类上:

image

上面的作法没有纯粹的POCO方法那么优雅,但其好处是,能够用于Visual Studio中任何工具或设计器生成的代码。

最后一步 – 将Friend保存到数据库中

最后一步,不论是否采用了POCO或工具生成的Person类,是将合法的朋友数据保存到数据库中去。

这只要求咱们用三行代码将FriendsControlle类中的 “Todo”占位语句替换掉,这三行代码将新朋友保存到数据库。下面是整个FriendsController类的完整代码(使用了ADO.NET EF作数据库持久化):

image

如今,当咱们访问 /Friends/Create URL时,咱们能够轻松地添加新人到咱们的朋友数据库中去:

image

对全部数据的验证都是同时在客户端和服务器端执行的。咱们能够轻易地在一个地方添加/修改/删除验证规则,而由整个应用中的全部的控制器和视图来执行这些规则。

结语

ASP.NET MVC 2极大地简化了web应用的验证集成。它倡议一种基于模型的验证方式,容许你将你的应用保持DRY,帮助确保验证规则在整个应用中保持一致。 ASP.NET MVC 2中内置的DataAnnotation支持,本来就使得对常见的验证场景的支持很是容易。并且,ASP.NET MVC 2验证设施中的扩展性支持容许你支持更大范围的更高级的验证场景,能够插入任何现有的或者定制的验证框架/引擎。

但愿本文对你有所帮助。

相关文章
相关标签/搜索