ASP.NET开发团队刚发布了ASP.NET MVC第二版的第一个公开的预览版。你可以 在这里下载。
今 天的预览版是在.NET 3.5 SP1和VS 2008下工作的,可与ASP.NET MVC 1.0并行安装在同一个机器上(即,它们不相冲突,如果你安装2.0的话,你现有的ASP.NET MVC 1.0项目不会受影响)。如果你同时安装ASP.NET MVC 1.0 和 ASP.NET MVC 2.0的话,你会在Visual Studio 2008的 “新项目” 对话框中看到2个ASP.NET MVC项目模板:
ASP.NET MVC 2预览版的发布说明详述了如何将现有的ASP.NET MVC 1.0项目升级到使用V2,如果你想将它们移植来利用V2的新特性的话。
新特性
ASP.NET MVC V2将包括一堆新功能和特性(其中一些已经在 ASP.NET MVC产品路线图网页上列出了)。今天的“第一个预览版”包括的一些新特性还是第一次露面,更多的特性将在将来的预览版中出现。第一个预览版的代码还属于早期版本,开发团队今天发布这个版本,意在开始征询大家的反馈,并将它们融入将来的版本。
下面简短地说明一下其中一些新功能:
区域支持
ASP.NET MVC 2将支持一个叫“区域(areas)”的新特性,允许你轻松地将MVC应用的功能进行分割和组合。
“区域”提供了一个将控制器和视图进行分组的方式,允许你把一个大应用的各个子部分相对独立地进行构建。每个区域可以一个单独的ASP.NET MVC项目的形式来实现,并且这些项目可进而为主应用所引用。这在建造大应用时有助于管理其复杂性,并方便多个团队合作开发应用。
下面这个屏幕截图展示一个单一解决方案中有三个项目。其中一个项目叫“CompanySite”(公司网站),包括了核心的网站内容,布局,相关的控制器 和视图。还有2个单独的“区域”项目: “Blogs”(博客) 和 “Forums” (论坛)。这2个项目实现了网站的/Blogs 和 /Forums URL下的功能,封装了所有的路径规则,以及实现这2个部分的控制器和视图:
第一个预览版只包括了区域特性实现的第一个部分,还不包括任何工具支持(目前,你只能手工添加编译任务来创建并配置区域项目)。将来的预览版本将包括工具支持,同时进一步将功能集扩大和完善。
DataAnnotation(数据标记)验证支持
ASP.NET MVC 2现在包含了对最先在.NET 3.5 SP1中发布的DataAnnotation验证的内置支持,这个东西是在ASP.NET动态数据和.NET RIA服务中使用的。DataAnnotation提供了一个简易的方式,可以声明的方式在应用中的Model(模型)和ViewModel(视图模型) 类中添加验证规则,在ASP.NET MVC中有自动的绑定和UI辅助方法验证支持。
要看该特性如何在实际中使用,我们可以象下面这样创建一个新的“Customer” 视图模型类,内含5个属性(是用了 C#特性之一 — 自动属性来实现的)。
然后,我们可以使用System.ComponentModel.DataAnnotations命 名空间下的DataAnnotation特性,在这些属性上饰于适当的验证规则。下面的代码使用了4种不同的内置验证规则: Required], [StringLength], [Range], 和 [RegularExpression]。该命名空间下还包括一个基类,ValidationAttribute, 你可以继承来创建你自己的定制验证特性。
然后,我们可以创建一个CustomersController类,其中有2个 Create action方法。第一个 Create action方法处理对应于“/Customers/Create” URL的HTTP GET请求,基于一个空白的Customer对象显示一个视图模板。第二个 Create action方法则处理同个URL的HTTP POST请求,并接受一个Customer对象作为方法参数。它会检查提交的输入数据是否造成了任何模型绑定错误,如果造成了错误的话,它会使用已经输入 的数据重新显示视图模板,如果没错误的话,它会给用户显示一个提交成功了的视图:
最 后,我们可以在上面任意一个Create action方法中右击,选择 “添加视图”上下文菜单命令,自动地生成(scaffold)一个基于Customer对象的“Create”视图模板的框架。这么做的话,生成的框架视 图模板会包含下面这样一个HTML <form>:
这样,当我们在浏览器中请求“/Customers/Create” URL时,我们会得到象下面这样起始的空白表单:
如果我们输入不合法的数据,提交到服务器时,ASP.NET MVC 2模型绑定器会检测到我们的Customer类上有DataAnnotations特性,会自动地使用它们对提交的表单输入数据进行验证。如果有错误的 话,我们的控制器action方法会重新显示表单,并且给用户显示适当的验证错误消息,象下面这样。注意我们使用DataAnnotation特性指定的 验证属性错误消息字符串是如何通过Html.Validation辅助方法显示给用户的,不用编写额外的代码就可以实现。
The above form will redisplay with error messages each time the user enters invalid input and attempts to perform a form post.
在将来的ASP.NET MVC 2预览版中,我们计划将 jQuery验证插件作 为默认项目模板的一部分来发布,同时添加DataAnnotation验证规则在客户端JavaScript中自动强制执行的支持。这将允许开发人员轻松 地在一个地方,Model或ViewModel对象上,添加验证规则,然后无论对象用在应用中的什么地方,这些规则都会同时在客户端和服务器端强制执行。
如果你不希望直接标记你的模型或视图模型类,你还可以创建一个伴随你的模型类的“伙伴类(buddy class)”,另外封装DataAnnotaton规则。这个功能还在这样一些场景下有用: VS直接生成/更新类的属性代码,你无法简易地在生成的代码上饰以特性(例如,由LINQ to SQL 或 LINQ to Entities设计器生成的类)。
除了提供对DataAnnotations的内置支持外,ASP.NET MVC V2中的DefaultModelBinder类现在还有新的虚拟方法,可以在子类中覆盖,来轻松地集成其他的验证框架( 例如Castle Validator, EntLib Validation等等)。ASP.NET MVC中的验证UI辅助方法是设计来支持任何类型的验证框架的(它们不用知道DataAnnotations)。
强类型UI辅助方法
ASP.NET MVC V2包含了新的HTML UI辅助方法,这些辅助方法允许你在引用视图模板的模型对象时使用强类型的lambda表达式。这可以促成更好的 视图编译时检查(这样缺陷是在编译时发现而不是在运行时发现),还能促成视图模板中更好的代码intellisense支持。
你可以在下面看到一个示范更好intellisense的例子,注意我在使用新的Html.EditorFor()辅助方法时是如何得到Customer模型对象属性的完整列表的:
第 一个预览版提供对新的Html.EditorFor(), Html.LabelFor(), 和 Html.DisplayFor() 辅助方法的内置支持。将在这个星期发布的更新过的MVC Futures程序集还将包含对另外的Html.TextBoxFor(), Html.TextAreaFor(), Html.DropDownListFor(), Html.HiddenFor(), 和 Html.ValidationMessageFor()辅助方法的支持(随着时间的推移,这些方法也会移到核心ASP.NET MVC 2程序集中去)。
在下面,你可以看到Customer创建场景下“Create”视图模板的一个更新了的版本。注意,在UI辅助方法中,我们不是使用字符串表达式来引用 Customer对象,而是使用强类型的lambda表达式。我们在所有这些方法中都可以得到完整的 intellisense 和 编译时检查:
上面的Html.LabelFor()辅助方法生成<label for="Name">Name:</label> HTML 标识。
Html.EditorFor()辅助方法可以用于任何数据类型值。在默认情形下,它很聪明,会根据要编辑的类型输出合适的HTML <input/>元素。譬如,它会为上面的前4个属性(是字符串和整数类型)生成<input type=”text”/>元素,会为最后的那个“IsActive” 属性生成<input type=”checkbox”/>元素,因为这个属性是布尔值类型。
除了支持简单的数据类型外,Html.EditorFor()辅助方法还允许你传递给它拥有多个属性的比较复杂的对象。在默认情形下,它会对对象的所有公 开属性进行循环,输出<label>, <input/> 元素,以及它能找到的每个属性的任何合适的验证消息。例如,我们可以重写上面的视图,对Customer对象只做单个Html.EditorFor()调 用,从概念上来说输出跟上面一样的标识:
强类型的辅助方法允许你在Customer视图类的属性上饰以[DisplayName]特性,来控制为每个属性输出的标签字符串(例如:不是用 “IsActive”作为标签文字,我们可以加一个[DisplayName(“Is Active Customer:”)]特性)。
你也可以加一个[ScaffoldColumn(false)]特性,来表示,在象上面把一个复杂的对象传给Html.EditorFor()那样的场景下,某个特定的属性完全不应该显示出来。
UI 辅助方法模板化支持
Html.EditorFor() 和 Html.DisplayFor() 辅助方法对显示标准的数据类型以及含有多个属性的复杂对象有内置的支持。就象上面说的,它们还支持通过在视图模型上施加象[DisplayName]和 [ScaffoldColumn]特性这样的基本的定制机制。
但经常地,开发人员想要能够进一步定制UI辅助方法的输出,对生成的东西要有完全的控制。Html.EditorFor() 和 Html.DisplayFor()辅助方法通过一个模板化机制支持这个要求,这个机制允许你定义外部的模板,替换原先的,完全控制显示的输出。更棒的 是,你还可以在每个数据类型/类的基础上定制要显示的内容。
在第一个预览版中,你可以在"Views"[控制器名称]目录下(如果你想要定制某个特定的控制器所用视图的显示的话)或在 "Views"Shared目录下(如果你想要定制一个应用中所有视图和控制器的显示的话)加一个“EditorTemplates” 或者 “DisplayTemplates” 子目录。
然后你可以往这些目录中加分模板(partial template)文件,针对个别数据类型或者类来定制显示输出。例如,在下面,我在 "Views"Shared目录下加了一个EditorTemplates子目录,在其中加了三个定制的模板文件:
上面的“Customer.ascx”模板表示我想要定制在调用Html.EditorFor()时其参数为Customer对象时的输出(例如,我可以 定制Customer属性的精确顺序和布局)。上面的“DateTime.ascx” 模板表示我想要定制在调用Html.EditorFor()时其参数为DateTime属性时的输出(例如,我也许想要使用JavaScript的日历控 件,而不是普通的文本框)。我也可以在目录中加一个“Object.ascx” 模板,如果我想要替代所有对象的默认显示的。
除了在每个类的基础上定制输出外,你还可以在目录中加“具名模板(named templates)”。一个常见的场景也许是 “CountryDropDown”模板,它处理字符串数据类型,但不是提供标准的文本框,而是显示一个用户可以选择的列出了国家名称值 的<select>下拉框。下面是这个编辑器模板的一个例子:
然后,我们可以在调用Html.EditorFor()辅助方法时,把上面这个模板的名称作为参数传给它,明确地表示我们想要使用这个模板。例如,在下面,除了指定Country属性的lambda表达式外,我们还指定了在显示时要使用的编辑器模板的名称:
或者,你也可以在你的ViewModel属性和类型上指定“UIHint”特性。这允许你在单一一个地方指定要使用的默认编辑器或者显示器模板,然后在整个应用的所有视图中使用指定的模板(而不必显式地将这个名称作为参数传给Html.EditorFor)。
下面是一个如何使用UIHint特性来表示Customer.Country属性(字符串类型)应该在默认情形下显示时使用CountryDropDown模板的例子:
一旦在我们的视图模型上设置上述特性后,在使用Html.EditorFor()显示那个属性时,我们就不再需要显式指定模板名称了。现在,在/Customers/Create URL上点击刷新时,我们的Country属性就会显示为一个下拉框,而不是一个标准的文本框:
其他酷特性
ASP.NET MVC 2第一个预览版还包含了若干个虽小但是很妙的特性。我最喜爱的几个包括:
新的[HttpPost]特性
在 ASP.NET MVC中,把一个URL的处理分成2个action方法的做法是非常常见的,其中一个处理GET请求,另一个处理POST请求。
在ASP.NET MVC 1中,你使用[AcceptVerbs(HttpVerbs.Post)]特性来表示action方法的“Post”版本:
在ASP.NET MVC 2中这依然工作,但你现在也可以利用更简洁的[HttpPost]特性来做同样的事情:
默认参数值
处理可省参数在web场景中是司空见惯的事。在ASP.NET MVC 1中,处理可省参数一般有2个做法,通过注册定制的路径规则,在其中指定默认的值,或者将某个action方法的参数标记为nullable,然后在 action方法中添加代码处理该参数是否是null(如果是null就提供默认值)。
ASP.NET MVC 2第一个预览版现在支持在action方法的参数上饰以 System.ComponentModel命名空间下的DefaultValueAttribute。 这允许你在某个参数不在请求值中时指定ASP.NET MVC应该传给action方法的参数值。例如,下面是一个我们可以如何处理 /Products/Browse/Beverages 和 /Products/Browse/Beverages?page=2 URLs的例子,如果“page”参数不是查询字符串的一部分时,其值为“1”:
VB今天就允许你直接在语言中指定默认的参数值(而不必象上面那样显式指定DefaultValue特性),VS2010中的C#语言也将支持可省参数的默认值,将允许我们把上面的代码简化成:
这应该会使处理默认/可省场景变得非常地干净利落。
绑定二进制数据
ASP.NET MVC 2的第一个预览版还加了支持绑定base64编码的字符串值到类型为byte[]和System.Data.Linq.Binary的属性。现在还有2个 可以接受这些数据类型的重载的Html.Hidden()版本。在你想要在应用中启用并发性控制,在表单中来回传送数据库行记录的时间戳 (timestamp)值的场景下,这会非常有用。
结语
点击这里下载包含一个ASP.NET MVC 2项目的.zip文件,该项目实现了我在上面示范的样例。
今天的ASP.NET MVC 2版本还只是第一个预览版,将来的预览版中将包括更多的特性,开发团队期待在如何改进和增强功能方面得到许许多多的反馈。
有规律地发布这些预览版的目的是想帮助确保这个反馈过程是开放的,任何想参与的人都可以轻易地参与。请在 www.asp.net的 ASP.NET MVC论坛上发贴提反馈,建议或者贴出你遇到的问题等。 你也可以从 Phil Haack的MVC2贴子 和 Phil和 Scott Hanselman在Channel9录制的关于第一个预览版的录像中了解这个预览版的详情。
希望本文对你有所帮助,
Scott