ASP.NET MVC 1.0 RC 版发布了

【原文地址】ASP.NET MVC 1.0 Release Candidate Now Available
【原文发表日期】 Tuesday, January 27, 2009 12:13 PM

今天,我们发布了ASP.NET MVC 1.0 最终版的候选版本(简称RC)。 点击这里下载(注:该链接才上线,所以如果链接不工作的话,请等几分钟,让你访问的服务器有机会更新)。该版本可以在Visual Studio 2008和免费的Visual Web Developer 2008下工作。

今天的ASP.NET MVC RC版本是我们在发布最终的1.0版本前的最后一个公开版本。我们预计在下个月(【译注】,指2月份)发布ASP.NET MVC 1.0 的最终版。

除了缺陷修补外,今天的版本还包含了若干个新的功能。它还包含了基于客户反馈对现有功能的几个改善。请阅读随ASP.NET MVC下载一起发布的发布说明,以了解所有改动的完整细节。该发布说明也包含了如何把用ASP.NET MVC Beta版本建造的现有应用升级到RC版的详细指令。

Visual Studio工具方面的改进

RC版本包含了Visual Studio工具方面的几个新功能(是在beta版本提供的新功能之外的,在这里我就不讨论beta中的这些功能了),这些功能包括:

添加控制器的命令

你现在可以在ASP.NET MVC项目中间键入Ctrl-M, Ctrl-C,或者右击 /Controller 文件夹,然后选择“Add->Controller(添加控制器)”上下文菜单项来创建新的控制器类:

这会调出“添加控制器”对话框,允许你给要创建的控制器取名,以及表示你是否想自动地生成(scaffold)常见的CRUD方法:

点击“添加”按钮会生成一个控制器类,并将它加到项目中去:

添加视图的命令

你现在可以在一个控制器的action方法中键入Ctrl-M, Ctrl-V,或者在一个action方法中右击,选择“添加视图”上下文菜单项来生成新的视图模板:

这会调出“添加视图”对话框,允许你给要创建的新视图取名(其中预先填充了基于约定的选项)。它允许你创建“Empty(空白)”的视图模板,或者根据控制器的action方法传给视图的对象类型自动地生成或scaffold视图模板。脚手架(scaffolding)基础设施在生成视图模板时会使用反射,这样它可以基于传给它的任何POCO (plain old CLR object,普通的CLR对象)生成新的模板。它对任何特别的ORM或数据实现都没有依赖性。

例如,在下面,我们表示想要基于从上面的action方法中传入的Product对象序列生成一个“列表”视图模板:

点击“添加”按钮会在 \Views\Products\ 文件夹中生成一个视图模板,内含默认的“脚手架”实现:

然后,我们运行应用,并在浏览器中请求 /products URL,就会看到取出的产品列表:

RC版本发布了好几个内置的脚手架模板:“Empty(空白)”, “List(列表)”,“Details(细节)”,“Edit(编辑)”和“Create(创建)”(你也可以添加自己的脚手架模板,稍后会提供更多细节)。

例如,要支持产品编辑,我们可以象下面这样在Products控制器上实现“Edit” action方法的HTTP-GET版本,然后调用“添加视图”命令:

在“添加视图”对话框中,我们可以表示我们将把一个Product对象传给我们的视图,然后选择“Edit”模板选项来生成脚手架实现:

点击“添加”按钮会在 \Views\Products\ 文件夹中生成一个编辑视图模板,内含默认的脚手架实现:

然后,我们可以运行应用,在浏览器中请求/products/edit/1 URL,来编辑Product细节:

要保存编辑后的改动,我们可以在Products控制器中实现“Edit” action方法的HTTP-POST版本:

注意在上面的代码中,在出错的情形下(例如,有人给一个数字型的值输入了一个非法的字符串),我们是如何重新显示视图的。“Edit(编辑)”和“Create(创建)”脚手架模板包含了在这种情形发生时,为保留用户输入和用红字标志不合法的输入元素所需的HTML验证辅助方法:

你最终大概不会原封不动地使用脚手架生成的模板,经常会完全换掉这些模板。但能够得到一个初始的实现并能很快地运行起来,针对你的场景有一个你可以轻松细调的起始视图模板是非常有用的。

因为脚手架基础设施支持针对任何普通的CLR对象生成脚手架视图,你既可以将其用于领域模型对象(包括用LINQ to SQL, LINQ to Entities, nHibernate, LLBLGen Pro, SubSonic, 和其他流行的ORM实现映射的对象),也可以用于自定义的Presentation Model/ViewModel类。

 

添加和定制脚手架模板

ASP.NET MVC的脚手架基础设施是用Visual Studio内置的T4模板架构(Scott Hanselman 在这里有一篇关于T4的好博客)来实现的。

你可以定制/改动任何内置的ASP.NET MVC脚手架模板实现。你还可以创建另外的脚手架模板(例如,ScottGu Crazy Look脚手架选项),让它们在“添加视图”对话框中作为选项显示出来。

要在整个机器层次定制/添加脚手架模板,打开 “C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC\CodeTemplates” 文件夹:

AddController 子文件夹包含了“添加控制器”对话框中的脚手架模板,而“AddView”子文件夹则包含了“添加视图”对话框中的脚手架模板:

填充在“添加视图”对话框中的脚手架模板只是带“.tt”文件扩展名的文本文件而已,这些“.tt” 文本文件包含了在模板被选中时会运行的行内C# 或 VB代码:

你可以打开和编辑任何现有的文件来定制默认的脚手架行为,你还可以添加新的“.tt”模板文件 -- 就象我在上面加的“Scott Crazy Look.tt”文件一样。在添加新的模板文件之后,“添加视图”对话框会更新,自动将其包括在可使用的脚手架选项列表之中:

除了在机器层次定制/添加模板文件外,你还可以在个别项目层次添加/改动这些模板文件,这还允许你将这些模板签入源码控制系统,在整个团队间轻松地使用它们。

你可以通过在项目下面加一个CodeTemplates文件夹,来在项目层次定制脚手架模板,然后你可以在其中建立“AddController”和“AddView”子文件夹:

你只要在项目中加一个同名的“.tt”文件,就可以覆盖任何一个默认的机器层次的模板文件。例如,在上面,我们覆盖了用在“添加控制器”场景中的默认“Controller.tt” 脚手架模板。

你可以将新的视图脚手架模板文件置于“AddView”文件夹中即可加入到列表中。例如,在上面,我们在项目中加了一个“Yet Another Crazy Look.tt” 视图模板。在使用“添加视图”对话框时,我们现在就会看到定义在机器和项目层次的所有模板的集合:

注: 当你将 “.tt”模板加到 \CodeTemplates 文件夹中时,确认在属性表格中将每个“.tt”模板文件的“Custom Tool(定制工具)”属性设成了空白字符串(否则的话,在运行时你会得到错误),你也许还需要关闭和重新打开项目以清除错误列表中会出现的一个伪错误。不久,我们将发表更多讨论创建/定制脚手架模板的博客贴子。

转到控制器/转到视图命令

RC版现在支持在项目中的控制器和视图间的快速导航。

当你的鼠标在控制器的action方法中时,你可以键入Ctrl-M, Ctrl-G,来快速地导航到对应的视图模板。你也可以通过在当前的action方法中右击,选择“Go To View(转到视图)”菜单选项才实现同样的导航跳跃:

在上面的例子中,我们在ProductsController类的“Edit” action方法中用了“Go To View”命令,这会在VS中打开\Views\Products\Edit.aspx视图模板,并使其拥有默认的焦点:

在视图模板中,你现在还可以键入 Ctrl-M, Ctrl-G 来快速地导航到视图对应的控制器类中。你也可以在视图模板中右击,选择“Go To Controller(转到控制器)”菜单选项来实现同样的导航操作:

编译视图的MSBuild任务

在默认情形下,当你编译一个ASP.NET MVC项目时,它会编译项目中除了视图模板文件中代码以外的所有代码。在ASP.NET MVC Beta版本中,如果你想要编译视图模板中的代码的话,你需要编写自己的MSBuild任务。ASP.NET MVC RC 版本则包含了一个内置的MSBuild 任务,你可以用它来把视图包括成为项目编译过程的一部分。该任务会核实应用中所有视图,母板页,部分视图的语法和其中的行内代码,如果遇上问题的话,会给你编译错误。

但因为性能的缘故,我们不建议在开发期间运行它来做快速编译,但将它加到特定的编译配置(例如,staging和部署)或者在与 Build 或 CI (连续集成)服务器一起使用时还是非常方便的。 请参阅发布说明中有关启用该任务的详细步骤。

重构视图的支持

在你使用VS 2008的“Rename(重新命名)”重构命令对控制器类或action方法重新命名时,\Views子文件夹中的文件和文件夹名现在会自动更新。VS 2008 会在控制器类被更新时,将标准的基于约定的命名模式施用于现有的视图文件/文件夹。

视图方面的改进

RC版包括了若干个特定于视图的改进,这些改进是基于预览版的反馈融合进来的。

不带后台代码文件的视图

基于反馈,我们把默认的视图模板改成了不再带后台代码文件,这个变动有助于强化视图在MVC应用中的目的(视图意在纯粹的显示,不该包含任何与显示无关的代码),去掉了项目中没被使用的文件(对大多数人来说)。

RC版本现在添加了对从使用泛型的基类继承视图模板的C#和VB句法支持。例如,在下面,我们在Edit.aspx视图模板中使用了这个句法,它的 “inherits”属性是从ViewPage<Product> 类型继承而来的:

不使用后台代码文件的一个好处是,在将视图模板文件加到项目后,你现在能立刻得到intellisense。在以前的版本中,你需要在生成视图后马上编译一次才能在其中得到intellisense。RC版本使得添加和立刻编辑视图文件的流程不再需要编译,过程也更加流畅。

重要主要事项: 如果你在把用以前版本创建的ASP.NET MVC项目升级到RC版,请确认遵循发布说明中的步骤,即,\Views文件夹中的web.config文件中的一些设置需要更新一下,上面的基于泛型的句法才会工作。

Model属性

在以前的ASP.NET MVC版本中,你使用ViewData.Model属性来访问传给视图的强类型模型对象:

上面的句法依然工作,虽然现在你还可以使用ViewPage上一个顶层的"Model"属性:

这个属性的功能跟前面的代码例子完全一样,它主要的好处在于,它允许你编写简明的代码。它还允许在你想要视图模板只与传给它的强类型模型打交道的情形下,避免使用ViewData字典。

设置标题

加到新的ASP.NET MVC项目的默认母板页模板在<head>部分拥有一个<asp:contentplaceholder/>元素,这可方便视图模板来控制要显示的HTML页面中的 <title> 元素,而不需要控制器明确地传递一个“title” 参数来配置它(这个方法是以前ASP.NET MVC版本中的默认方法,从责任的角度来看,我们认为是有问题的)。
(【译注】该功能也引入了一个缺陷,详情请参考Phil Haack的博客 Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1,你需要下载RC的更新版,还请参阅的Phil Haack的博客 ASP.NET MVC RC Refresh

例如,为定制Edit视图的<title>来包括当前产品的名字,我们现在可以加下面的代码到Edit.aspx模板中,直接根据传进视图的模型对象生成标题:

然后,上面的代码就会使得浏览器在运行时使用产品名显示标题:

除了设置<title>元素外,你还可以使用上面的方法在运行时动态地添加其它<head>元素。这会非常有用的另一个常见场景是,为搜索引擎优化(SEO)配置特定于模型/视图的<meta/>元素。

强类型的HTML/AJAX辅助类

有一个不少人都提出的要求是,在使用视图的HTML和AJAX辅助对象时,在指称Model时使用强类型表达式的句法(而不是字符串)的能力。

在ASP.NET MVC Beta版本中,这是不可能的,因为HtmlHelper和AjaxHelper辅助类并没有在它们的签名中呈示模型的类型,所以大家需要建造直接基于ViewPage<TModel>基类的辅助方法才能达成这个目的。

ASP.NET MVC RC 版本引进了新的HtmlHelper<TModel>和 AjaxHelper<TModel> 类型,是在ViewPage<TModel> 基类上呈示的。这些类型现在允许任何人建造使用了表达式句法的强类型HTML和AJAX辅助扩展来指称View的模型。 例如:

核心ASP.NET MVC V1程序集中的HTML表单辅助扩展方法还将使用不是基于表达式的字符串句法,今天发布的MVC Futures程序集(可在RC版下工作)有几个基于表达式句法的表单辅助方法的初始实现,我们计划对这些方法多迭代几次,然后考虑在下一个版本中把它们加到ASP.NET MVC核心程序集中。

当然,你还是可以添加自己的辅助方法(使用基于字符串或强类型的表达式方法)。内置的HTML/AJAX 辅助方法都是可以去掉的(因为它们是扩展方法),如果你要用自己的版本来替换或覆盖它们的话。

表单提交方面的改进

RC版本包括了若干个特定于表单提交方面的改进:

在常见场景下不再要求[Bind(Prefix=””)]

RC版本不再要求你明确地使用[Bind]特性(或将其前缀值设置为"")才能将进来的没有前缀的表单提交参数映射到复杂的action方法参数上了。

要理解其意义,让我们来实现ProductsController的 “Create” 场景。我们先来实现“Create” action方法的HTTP-GET 版本,我们用下面的代码来返回一个基于空白的Product对象的视图:

然后我们在action方法中右击,选择“添加视图”命令,生成基于一个Product对象的“Create” 视图模板的框架:

注意上面我们的Html.TextBox()辅助方法是如何引用产品对象上的“ProductName”和“SupplierID”属性的。这会生成象下面这样的HTML标识,其中的input “name” 属性是 “ProductName” 和 “SupplierID”:

然后,我们可以实现“Create” action方法的HTTP-POST 版本,该方法接受一个Product对象作为参数:

在 ASP.NET MVC Beta版本中,我们需要在上面的Product参数前加一个[Bind(Prefix=””)]特性,否则的话,ASP.NET MVC绑定基础设施只会寻找带“productToCreate.”前缀的表单提交值(例如,productToCreate.ProductName 和 productToCreate.SupplierID),而不会找到我们表单的提交值(因为这些值没有对应的前缀)。

在RC版本中,默认的action方法绑定器开始还会尝试将productToCreate.ProductName表单值映射到Product对象上。但如果它们找不到这样的值的话,它们现在会尝试将“ProductName” 映射到Product对象上。这使得你需要传递复杂对象到action方法的场景的句法更加干净和简明。你可以在映射领域对象(象上面的Product对象)以及Presentation Model/ViewModel类(象ProductViewModel 类)时利用这个功能。

我们的Create action方法的一个完整的实现(包括基本的输入类型错误处理)会象这样:

现在,我们的Create action方法会保存Product对象,如果所有的值都输入正确的话。在用户尝试使用不合法的产品属性值创建Product时,例如,用“Bogus” 字符串来替换一个合法的Decimal值,表单就会重新显示,用红字标记非法的输入元素:

ModelBinder API方面的改进

ASP.NET MVC RC版中的模型绑定基础设施已经重构过了,加了额外的扩展点,允许自定义的绑定和验证定义。你可以阅读ASP.NET MVC RC的发布说明以了解这些细节。

除了注册为类外,现在的模型绑定器还能注册为接口。

IDataErrorInfo支持

ASP.NET MVC 中默认的模型绑定器现在支持实现了IDataErrorInfo接口的类。这允许以一种共同的方式来抛出验证错误信息,该方式可在Windows Forms, WPF ,以及现在的 ASP.NET MVC应用中公用。

单元测试方面的改进

ASP.NET MVC RC版本包括了单元测试方面一些显著的改进:

ControllerContext不再从RequestContext继承而来

RC版本包括了对 ControllerContext类的重构,该重构极大地简化了常见的单元测试场景。ControllerContext不再从RequestContext继承而来,而是在其中封装了RequestContext,将其呈现为一个属性。ControllerContext的属性和继承类现在都是virtual的,而不是sealed的了,这极大地方便了mock对象的创建。

要理解其有助之处,让我们来考虑一个象下面这样的action方法,其中使用了内置的“Request” 和 “User” 对象:

在以前的ASP.NET MVC版本中测试上面的action方法要求模拟RequestContext和 ControllerContext(还在RouteData对象中引进了一些不是显而易见的构造器)。

在RC版中,我们现在可以象下面这样单元测试(使用了Moq框架来模拟我们Controller的ControllerContext,允许我们模拟Request.IsAuthenticated 和 User.Identity.Name属性):

这样的重构改进不光有助于测试控制器的action方法,还有助于测试过滤器,路径,自定义的actionresult类型,已经其它各种场景。

AccountsController的单元测试

包括在RC版中的ASP.NET MVC项目模板现在添加了25个预制的单元测试,这些测试是用来核实AccountsController类的行为的(该类是在默认情形下加到项目中,用来处理登录和帐号管理场景的)。这方便了重构和更改AccountsController。AccountsController的实现也被修改过了,以利于基于非成员提供器的权限系统的集成。

防范跨站请求伪造攻击(Cross Site Request Forgery-简称CSRF)

跨站请求伪造攻击(也称为XSRF攻击)会导致使用了信任的浏览器代理的用户在一个网站上采取非计划中的行动。这些攻击依赖于用户也许还登录了另外一个网站这样一个事实,一个恶意的网站可以通过创建一个发向起始网站的请求(例如,用黑客网站上的<img src=””/>来链向起始网站的URL)来做攻击。该请求是用用户的浏览器做的,用了用户的认证凭据。攻击者希望用户的认证或会话cookie还是有效的,如果是这样的话,攻击者有时可以采取破坏性的行动。你可以在这里了解该黑客技术的细节。

ASP.NET MVC RC现在包括了一些内置的防范CSRF攻击的辅助方法,可以有助于减轻CSRF攻击。例如,你现在可以使用Html.AntiForgeryToken()辅助方法,在表单中生成一个隐藏的input记号:

这个辅助方法会发出一个HTTP cookie,在我们的表单中生成一个隐藏的输入元素。恶意的网站不能同时获取这2个值。

然后我们可以在我们想要保护的任何action方法上施加一个新的 [ValidateAntiForgeryToken]特性:

这会检查合适的记号的存在,如果不匹配的话,会阻止我们的HTTP-POST action方法的运行(减小了成功的CSRF攻击的机会)。

File处理方面的改进

ASP.NET MVC RC版包含了若干个文件处理方面的改进:

FileResult 和 File() 辅助方法

RC版添加了一个新的FileResult类,可被用来表示一个文件将作为一个控制器action方法的ActionResult而返回。 Controller基类现在还包含了一套File()方法,可以方便创建和返回FileResult。

例如,让我们假设我们想要建造一个相片管理网站,我们可以象下面这样定义一个简单的Photo类,在其中封装了要保存的相片的细节:

然后,我们可以象下面这样使用新的File()辅助方法,在PhotoManager控制器中实现一个DisplayPhoto action方法,用来显示数据库中的相片。在下面的代码中,我们把要显示的字节,以及文件的 mime类型传给了File()辅助方法,如果我们将 <img src=””/> 元素指向我们的action方法的话,浏览器就会在页面中显示对应的相片:

假如我们想要终端用户能够下载相片,并保存在本地的话,我们可以象下面这样实现一个DownloadPhoto action方法。在下面的代码中,我们传入了第三个参数,该参数将导致ASP.NET MVC设置一个头信息,使得浏览器显示一个“保存为。。”的对话框,在其中预先填充我们提供的文件名:

当用户点击指向/PhotoManager/DowloadPhoto/1232 URL的链接时,会提示保存是否要相片:

文件上传的支持

 

RC版中还包括了对上传文件以及多部分mime内容的内置的模型绑定器支持。

例如,我们可以有这样一个<form>,其enctype属性被设置为“multipart/form-data”,会向/PhotoManager/UploadPhoto URL提交表单。如果表单中有一个<input type=”file” name=”fileToUpload”/>元素,可由终端用户选择一个文件,这个文件会作为HttpPostedFileBase对象传给我们的action方法:

然后我们可以使用HttpPostedFileBase对象来访问上传文件的原始字节,它的mime类型,以及将其保存到数据库中或硬盘上。

AJAX方面的改进

The ASP.NET MVC RC 版包括了若干个AJAX方面的改进:

jQuery Intellisense 文件包括在ASP.NET MVC项目模板中了

新创建的 ASP.NET MVC 项目现在包括了标准的jQuery库文件(同时包括完整的和压缩的版本),以及vsdoc intellisense文档文件,该文件会被Visual Studio用来提供更丰富的intellisense支持(你可以在这里了解有关详情):

这可以在客户端代码块和JavaScript文件中促成丰富的jQuery JavaScript intellisense:

今天的RC版本发布的是jQuery 1.2.6,我们计划在 ASP.NET MVC 1.0 最终版中发布即将发行的jQuery 1.3.1,同时会包括一个相应的JavaScript intellisense文件的更新版。

Request.IsAjaxRequest Property属性

Request.IsAjaxRequest属性可以用来检测某个请求是否来自客户端的AJAX调用 (这在AJAX功能没有启用,你需要优雅地降级的场景下会非常有用)。在RC版本中,这个方法中的逻辑已被更改为可以识别“X-Requested-With” 这个HTTP头信息(除了由ASP.NET AJAX发送的表单域值外)。这是个众所周知的头信息,为诸多JavaScript库(象Prototype, jQuery, 和 Dojo)所发送,这促成了一种统一的方式来在ASP.NET MVC请求中检测是否是AJAX调用。

JavaScriptResult ActionResult 和 JavaScript() 辅助方法

Controller这个基类现在含有一个JavaScript()辅助方法,它返回一个新的ActionResult,其类型为JavaScriptResult。这支持了这样的功能: 从服务器端返回原始的JavaScript脚本,之后为内置的ASP.NET MVC辅助方法在客户端运行。这在你想要根据服务器端的逻辑在客户端执行条件性的JavaScript的情形下会非常有用。

结语

我们非常兴奋,我们处在了ASP.NET MVC V1版本的最后冲刺阶段。请尽快地报告你在RC版中发现的任何问题,这样我们就可以在最终版中解决这些问题。开发团队计划在下几个星期内仔细地监听任何反馈,假定没有任何大的问题的话,将在下个月发布正式的V1版本。

希望本文对你有所帮助,

Scott

posted on 2009-03-04 22:50  bitstudio  阅读(235)  评论(0编辑  收藏  举报