ASP.NET MVC 2 的新增功能

本文档介绍 ASP.NET MVC 2 中引入的新功能和改进。

简介
将 ASP.NET MVC 1.0 项目升级到 ASP.NET MVC 2
新功能
模板化帮助程序
Areas
对异步控制器的支持
支持Action-Method参数中的 DefaultValueAttribute
支持使用模型绑定器绑定二进制数据
ModelMetadata 和 ModelMetadataProvider 类
支持 DataAnnotations 属性
模型验证程序提供程序
客户端验证
Visual Studio 2010 的新代码片段
新建 RequireHttpsAttribute 操作筛选器
重写 HTTP 方法谓词
模板化帮助程序的新 HiddenInputAttribute 类
Html.ValidationSummary 帮助程序方法可以显示Model-Level错误
Visual Studio 中的 T4 模板生成特定于 .NET FrameworkAPI 改进的目标版本的代码
中断性变更
免责声明

简介

ASP.NET MVC 2 基于 ASP.NET MVC 1.0 构建,并引入了一系列侧重于提高工作效率的增强功能和功能。 此版本与 ASP.NET MVC 1.0 兼容,因此,ASP.NET MVC 1.0 的所有知识、技能、代码和扩展将继续适用。

有关 ASP.NET MVC 的详细信息,请访问以下资源:

将 ASP.NET MVC 1.0 项目升级到 ASP.NET MVC 2

ASP.NET MVC 2 可与 ASP.NET MVC 1.0 并行安装在同一服务器上,这使应用程序开发人员能够灵活地选择何时将 ASP.NET MVC 1.0 应用程序升级到 ASP.NET MVC 2。 有关如何升级的信息,请参阅文档 将 ASP.NET MVC 1.0 应用程序升级到 ASP.NET MVC 2

新功能

本部分介绍 MVC 2 版本中引入的功能。

模板化帮助程序

通过模板化帮助程序,可以自动将 HTML 元素与数据类型相关联,以便进行编辑和显示。 例如,在视图中显示 System.DateTime 类型的数据时,可以自动呈现日期选取器 UI 元素。 这类似于字段模板在 ASP.NET 动态数据中的工作方式。 有关详细信息,请参阅 使用模板化帮助程序在 MSDN 网站上显示数据。

Areas

使用区域可将大型项目组织到多个较小的部分,以便管理大型 Web 应用程序的复杂性。 (“area”) 的每个节通常表示大型网站的单独部分,用于对相关的控制器和视图集进行分组。 有关详细信息,请参阅 MSDN 网站上的演练:按区域组织 ASP.NET MVC 应用程序

若要创建新区域,请在“解决方案资源管理器”中右键单击项目,单击“添加”,然后单击“区域”。 此时会显示一个对话框,提示输入区域名称。 输入区域名称后,Visual Studio 会向项目添加一个新区域。

下图显示了具有两个区域(管理员和博客)的项目的示例布局。

显示解决方案资源管理器下拉框中项目的示例布局的屏幕截图,其中包含两个区域、管理员和博客。

创建区域时,Visual Studio 会将派生自 AreaRegistration 的类添加到每个区域。 注册区域及其路由需要此类,如以下示例所示:

namespace MyApplication.Areas.Blog {
    public class BlogAreaRegistration : AreaRegistration {
        public override string AreaName {
            get { return "blog"; }
        }

        public override void RegisterArea(AreaRegistrationContext context) {
            context.MapRoute(
                "blog_default",
                "blog/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );

            context.MapRoute(
                "blog_whatsnew",
                "whats-new",
                new { action = "WhatsNew", id = UrlParameter.Optional  }
            );
        }
    }
}

ASP.NET MVC 2 的默认项目模板在 Global.asax 文件的代码中包含对 RegisterAllAreas 方法的调用。 此方法通过查找派生自 AreaRegistration 类的所有类型、实例化类型的实例,然后在实例上调用 RegisterArea 方法,来注册项目中的每个区域。 以下示例演示如何执行此操作。

public class MyMvcApplication : HttpApplication {

    void App_Start() {
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes);
    }

    public static void RegisterRoutes(RouteCollection routes) {
        routes.MapRoute("default", "{controller}/{action}/{id}", ...);
    }
}

如果不通过调用上下文在 RegisterArea 方法中指定命名空间。Namespaces.Add 方法,默认情况下使用注册类的命名空间。

对异步控制器的支持

ASP.NET MVC 2 现在允许控制器异步处理请求。 这可以通过允许频繁调用阻止操作的服务器 ((如网络请求) )改为调用非阻止操作,从而提高性能。 有关详细信息,请参阅 MSDN 上的 在 ASP.NET MVC 中使用异步控制器 主题。

支持Action-Method参数中的 DefaultValueAttribute

System.ComponentModel.DefaultValueAttribute 类允许为操作方法的参数提供默认值。 例如,假设定义了以下默认路由:

{controller}/{action}/{id}

还假定定义了以下控制器和操作方法:

public class ArticleController {
    public ActionResult View(int id, [DefaultValue(1)]int page) {
    }
}

以下任何请求 URL 都将调用在前面的示例中定义的 View 操作方法。

  • /Article/View/123
  • /Article/View/123?page=1 (实际上与上一个请求相同)
  • /Article/View/123?page=2

如果没有 DefaultValueAttribute 属性,则上述列表中的第一个 URL 将不起作用,因为 page 参数是一个不可为 null 的值类型,其值尚未提供。

如果代码是使用 Visual Basic 2010 或 Visual C# 2010 编写的,则可以使用可选参数而不是 DefaultValueAttribute 属性,如以下示例所示:

Function View(ByVal id As Integer, Optional ByVal page As Integer = 1) _
        As ActionResult
    ' ...
End Function

public ActionResult MyAction(int id, int page = 1) {
    // ...
}

支持使用模型绑定器绑定二进制数据

Html.Hidden 帮助程序有两个新的重载,用于将二进制值编码为 base-64 编码的字符串:

public static string Hidden(this HtmlHelper htmlHelper, string name, Binary value);

public static string Hidden(this HtmlHelper htmlHelper, string name, byte[] value);

一个典型用途是在视图中嵌入对象的时间戳。 例如,应用程序可能包括以下 Product 对象:

public class Product {
    //... other properties ...	
    public byte[] TimeStamp {
        get;
        set;
    }
}

编辑窗体可以在窗体中呈现 TimeStamp 属性,如以下示例所示:

<%@ Page Inherits="ViewPage<Product>" %>
<%= Html.Hidden("TimeStamp", Model.TimeStamp) %>

此标记将带有时间戳值的隐藏输入元素呈现为 base-64 编码的字符串,类似于以下示例:

<input type="hidden" name="TimeStamp" value="QVNQLk5FVCBNVkMgaXMgZnVuIQ==" />

此窗体可能会发布到具有 Product 类型的参数的操作方法,如以下示例所示:

public ActionResult Edit(Product p) {
    // p.TimeStamp is populated from the form
}

在操作方法中,TimeStamp 属性已正确填充,因为发布的 base-64 编码字符串已转换为字节数组。

ModelMetadata 和 ModelMetadataProvider 类

ModelMetadataProvider 类提供一个抽象,用于获取视图中模型的元数据。 MVC 2 包含一个默认提供程序,该提供程序提供由 System.ComponentModel.DataAnnotations 命名空间中的属性公开的元数据。 可以创建提供来自其他数据存储(如数据库或 XML 文件)元数据的元数据提供程序。

ViewDataDictionary 类公开 ModelMetadata 对象,该对象包含由 ModelMetadataProvider 类从模型中提取的元数据。 这使模板化帮助程序能够使用此元数据并相应地调整其输出。

有关详细信息,请参阅 ModelMetadataModelMetadataProvider 类的文档。

支持 DataAnnotations 属性

ASP.NET MVC 2 支持在绑定到模型以提供输入验证时, (System.ComponentModel.DataAnnotations 命名空间) 中定义的 RangeAttribute、RequiredAttribute、StringLengthAttribute 和 RegexAttribute 验证属性。

有关详细信息,请参阅 MSDN 网站上的 如何:使用 DataAnnotations 属性验证模型数据 。 可在 下载 https://go.microsoft.com/fwlink/?LinkId=157753演示这些属性用法的示例项目。

Model-Validator提供程序

模型验证提供程序类表示为模型提供验证逻辑的抽象。 ASP.NET MVC 包含基于 System.ComponentModel.DataAnnotations 命名空间中包含的验证属性的默认提供程序。 还可以创建自己的验证提供程序,用于定义自定义验证规则以及验证规则到模型的自定义映射。 有关详细信息,请参阅 ModelValidatorProvider 类的文档。

Client-Side验证

模型验证程序提供程序类以可由客户端验证库使用的 JSON 序列化数据的形式向浏览器公开验证元数据。 ASP.NET MVC 2 包括一个客户端验证库和适配器,该库和适配器支持前面提到的 DataAnnotations 命名空间验证属性。 提供程序类还允许通过编写处理 JSON 数据并调用备用库的适配器来使用其他客户端验证库。

Visual Studio 2010 的新代码片段

ASP.NET MVC 2 的一组 HTML 代码片段随 Visual Studio 2010 一起安装。 若要查看这些代码段的列表,请在“工具”菜单中选择“代码段管理器”。 对于语言,请选择“HTML”,对于“位置”,请选择“ASP.NET MVC 2”。 有关如何使用代码片段的详细信息,请参阅 Visual Studio 文档。

新建 RequireHttpsAttribute 操作筛选器

ASP.NET MVC 2 包含一个新的 RequireHttpsAttribute 类,该类可应用于操作方法和控制器。 默认情况下,筛选器会将非 SSL (HTTP) 请求重定向到启用了 SSL 的 (HTTPS) 等效项。

重写 HTTP 方法谓词

使用 REST 体系结构样式生成网站时,HTTP 谓词用于确定要对资源执行的操作。 REST 要求应用程序支持各种常见的 HTTP 谓词,包括 GET、PUT、POST 和 DELETE。

ASP.NET MVC 2 包括可应用于操作方法和功能压缩语法的新属性。 这些属性使 ASP.NET MVC 能够基于 HTTP 谓词选择操作方法。 在以下示例中,POST 请求将调用第一个操作方法,PUT 请求将调用第二个操作方法。

[HttpPost]
public ActionResult Edit(int id)

[HttpPut]
public ActionResult Edit(int id, Tag tag)

在早期版本的 ASP.NET MVC 中,这些操作方法需要更详细的语法,如以下示例所示:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(int id) 

[AcceptVerbs(HttpVerbs.Put)] 
public ActionResult Edit(int id, Tag tag)

由于浏览器仅支持 GET 和 POST HTTP 谓词,因此无法发布到需要不同谓词的操作。 因此,不可能以本机方式支持所有 RESTful 请求。

但是,为了在 POST 操作期间支持 RESTful 请求,ASP.NET MVC 2 引入了新的 HttpMethodOverride HTML 帮助程序方法。 此方法呈现一个隐藏的输入元素,该元素使表单能够有效地模拟任何 HTTP 方法。 例如,通过使用 HttpMethodOverride HTML 帮助程序方法,可以将表单提交显示为 PUT 或 DELETE 请求。 HttpMethodOverride 的行为会影响以下属性:

  • HttpPostAttribute
  • HttpPutAttribute
  • HttpGetAttribute
  • HttpDeleteAttribute
  • AcceptVerbsAttribute

隐藏的输入元素的名称为 X-HTTP-Method-Override,其值设置为要模拟的 HTTP 谓词。 还可以在 HTTP 标头或查询字符串值中将替代值指定为名称/值对。

仅当实际请求为 POST 请求时,才能使用替代。 对于使用任何其他 HTTP 谓词的请求,将忽略重写值。

模板化帮助程序的新 HiddenInputAttribute 类

可以将新的 HiddenInputAttribute 属性应用于模型属性,以指示在编辑器模板中显示模型时是否应呈现隐藏的输入元素。 (属性设置 HiddenInput) 的隐式 UIHint 值。 属性的 DisplayValue 属性允许您指定是否在编辑器和显示模式下显示该值。 当 DisplayValue 设置为 false 时,不会显示任何内容,甚至不会显示通常环绕字段的 HTML 标记。 DisplayValue 的默认值为 true。

在以下情况下,可以使用 HiddenInputAttribute 属性:

  • 当视图允许用户编辑对象的 ID 时,必须显示值,并提供包含旧 ID 的隐藏输入元素,以便将其传递回控制器。
  • 当视图允许用户编辑不应显示的二进制属性时,例如 timestamp 属性。 在这种情况下,不会显示值和周围的 HTML 标记 (,例如标签和值) 。

以下示例演示如何使用 HiddenInputAttribute 类。

public class ProductViewModel {
    [HiddenInput] // equivalent to [HiddenInput(DisplayValue=true)]
    public int Id { get; set; }

    public string Name { get; set; }

    [HiddenInput(DisplayValue=false)]
    public byte[] TimeStamp { get; set; }
}

当 属性设置为 true (或未) 指定参数时,将发生以下情况:

  • 在显示模板中,将呈现标签并向用户显示值。
  • 在编辑器模板中,标签呈现,值呈现在隐藏的输入元素中。

当 属性设置为 false 时,将发生以下情况:

  • 在显示模板中,不会为该字段呈现任何内容。
  • 在编辑器模板中,不呈现标签,值在隐藏的输入元素中呈现。

Html.ValidationSummary 帮助程序方法可以显示Model-Level错误

Html.ValidationSummary 帮助程序方法具有仅显示模型级错误的新选项,而不是始终显示所有验证错误。 这样就可以在验证摘要中显示模型级错误,并在每个字段旁边显示特定于字段的错误。

Visual Studio 中的 T4 模板生成特定于目标版本的.NET Framework

ASP.NET MVC T4 主机的 T4 文件可以使用一个新属性,该主机指定应用程序使用的.NET Framework的版本。 这使 T4 模板能够生成特定于.NET Framework版本的代码和标记。 在 Visual Studio 2008 中,该值始终为 .NET 3.5。 在 Visual Studio 2010 中,该值为 .NET 3.5 或 .NET 4。

API 改进

本部分介绍对现有 ASP.NET MVC 类型和成员的更改。

  • 在 Controller 类中添加了受保护的虚拟 CreateActionInvoker 方法。 此方法由 Controller 的 ActionInvoker 属性调用,如果尚未设置调用程序,则允许延迟实例化调用程序。
  • 在 AuthorizeAttribute 类中添加了受保护的 virtual HandleUnauthorizedRequest 方法。 这使派生自 AuthorizeAttribute 的筛选器能够在授权失败时控制行为。
  • 在 ValueProviderDictionary 类中添加了 Add (字符串键、对象值) 方法。 这使你可以使用 ValueProviderDictionary 的字典初始值设定项语法,如以下示例所示:
Controller c = new MyController();
c.ValueProvider = new ValueProviderDictionary(null) {
    { "example1", "example1Value" },
    { "example2", "example2Value" },
    { "example3", new int[] { 1, 2, 3 } }
};
  • 在 Sys.Mvc.AjaxContext 类中添加了get_object方法。 这是类似于 get_data 方法的 JavaScript 方法,但如果响应的内容类型为 application/json,get_object返回 JSON 对象。
  • 在 AuthorizationContext 类中添加了 ActionDescriptor 属性。
  • 添加了 UrlParameter.Optional 令牌,当表单帖子中缺少该属性时,该令牌可用于解决绑定到包含 ID 属性的模型时出现的问题。 有关详细信息,请参阅 Phil Haack 博客 上的 MVC 2 可选 URL 参数 ASP.NET 条目。

重大更改

以下更改可能会导致现有 ASP.NET MVC 1.0 应用程序中出现错误。

实现 IDataErrorInfo 的类的属性验证行为更改

对于使用 IDataErrorInfo 执行验证的模型对象,无论是否设置了新值,都会验证每个属性。 在 ASP.NET MVC 1.0 中,仅验证设置了新值的属性。 在 ASP.NET MVC 2 中,仅当所有属性验证程序都成功时,才会调用 IDataErrorInfo 的 Error 属性。

安装程序中不再提供 IIS 脚本映射脚本

IIS 脚本映射脚本是一个命令行脚本,用于在经典模式下为 IIS 6 和 IIS 7 配置脚本映射。 如果使用 Visual Studio 开发服务器或在集成模式下使用 IIS 7,则不需要脚本映射脚本。 这些脚本在 ASP.NET WebStack 上作为单独的不受支持的下载提供。

MVC Futures 中的 Html.Substitute 帮助程序方法不再可用

由于 MVC 视图引擎的呈现行为发生了更改,Html.Substitute 帮助程序方法不起作用,并且已被删除。

IValueProvider 接口替换了 IDictionary 的所有用法

在 MVC 1.0 中接受 IDictionary 的每个属性或方法参数现在都接受 IValueProvider。 此更改仅影响包含自定义值提供程序或自定义模型绑定器的应用程序。 受此更改影响的属性和方法的示例包括:

  • ControllerBase 和 ModelBindingContext 类的 ValueProvider 属性。
  • Controller 类的 TryUpdateModel 方法。

Site.css 文件中添加了新的 CSS 类

ASP.NET MVC 项目模板中的 Site.css 文件已更新为包含验证功能和模板化帮助程序使用的新样式。

帮助程序现在返回 MvcHtmlString 对象

为了利用 ASP.NET 4 中新的 HTML 编码表达式语法,HTML 帮助器的返回类型现在是 MvcHtmlString 而不是字符串。 如果使用 ASP.NET MVC 2 和 ASP.NET 3.5 上的新帮助程序,将无法利用 HTML 编码语法;仅当在 ASP.NET 4 上运行 ASP.NET MVC 2 时,新语法才可用。

JsonResult 现在仅响应 HTTP POST 请求

为了缓解可能会泄露信息的 JSON 劫持攻击,默认情况下,JsonResult 类现在仅响应 HTTP POST 请求。 对返回 JsonResult 对象的操作方法的 Ajax GET 调用应更改为改用 POST。 如有必要,可以通过设置 JsonResult 的新 JsonRequestBehavior 属性来替代此行为。 有关潜在攻击的详细信息,请参阅 Phil Haack 博客上的 博客文章 JSON 劫持

ModelBindingContext 上的 Model 和 ModelType 属性资源库已过时

已将新的可设置 ModelMetadata 属性添加到 ModelBindingContext 类。 新属性封装 Model 和 ModelType 属性。 尽管 Model 和 ModelType 属性已过时,但为了向后兼容,属性 getter 仍然有效;它们委托给 ModelMetadata 属性以检索值。

对 DefaultControllerFactory 类的更改会中断派生自它的自定义控制器工厂

通过删除 RequestContext 属性修复了 DefaultControllerFactory 类。 请求上下文实例将代替此属性传递到受保护的虚拟 GetControllerInstance 和 GetControllerType 方法。 此更改会影响派生自 DefaultControllerFactory 的自定义控制器工厂。

自定义控制器工厂通常用于为 ASP.NET MVC 应用程序提供依赖项注入。 若要更新自定义控制器工厂以支持 ASP.NET MVC 2,请更改方法签名或签名以匹配新签名,并使用请求上下文参数而不是 属性。

“区域”现在是保留的路由值键

路由值中的字符串“区域”现在在 ASP.NET MVC 中具有特殊含义,其含义与“控制器”和“操作”相同。 一个含义是,如果 HTML 帮助程序提供包含“area”的路由值字典,则帮助程序将不再在查询字符串中追加“area”。

如果使用的是“区域”功能,请确保不要将 {area} 用作路由 URL 的一部分。

免责声明

这是一份初稿,并可能在本文所述软件最终商业发布之前进行大幅更改。

本文档中包含的信息代表 Microsoft Corporation 在发布之日对所讨论问题的当前观点。 由于 Microsoft 必须响应不断变化的市场条件,因此不应将其解释为 Microsoft 作出的承诺,并且 Microsoft 无法保证在发布日期之后提供的任何信息的准确性。

本白皮书仅用于提供信息。 MICROSOFT 对本文档中的信息不做任何明示、暗示或法定的担保。

用户有责任遵守所有适用的版权法/著作权法。 在不限制版权所辖权利的前提下,未经 Microsoft Corporation 的明确书面许可,本文档的任何部分不得被复制、存储或引进检索系统,或者以任何形式、任何方式(电子、机械、影印、录音等)或为任何目的进行传播。

Microsoft 可能拥有本文档所涵盖主题的专利、专利申请、商标、版权或其他知识产权。 除非 Microsoft 提供了明确的书面许可协议,否则提供本文档并不意味着赋予您这些专利、商标、版权或其他知识产权的任何许可。

除非另有说明,否则此处描述的示例公司、组织、产品、域名、电子邮件地址、徽标、人员、地点和事件都是虚构的,并且无意或应推断任何真实的公司、组织、产品、域名、电子邮件地址、徽标、人员、地点或事件。

© 2010 年 Microsoft Corporation。 保留所有权利。

Microsoft 和 Windows 是 Microsoft Corporation 在美国和/或其他国家/地区的注册商标或商标。

此处提到的真实公司和产品的名称可能是其各自所有者的商标。