本章概要
- 理解ASP.NET MVC
- ASP.NET MVC3 预览
- 如何创建MVC3应用程序
- MVC应用程序结构
本章首先简要介绍ASP.NET MVC, 解释它怎样适应ASP.NET MVC的历史版本,总结ASP.NET MVC3的主要更新,并展示如何配置ASP.NET MVC3应用程序的开发环境。
鉴于本书是介绍某web框架的高级系列教程之一,因此将介绍的言简意赅。我们不打算花费过多的时间来说服您来学习ASP.NET MVC,而是假设您已经为此而购买了本书。要想证明一个软件框架和模式成功,最好的方式莫过于展示它在现实世界中的应用。
ASP.NET MVC简介
ASP.NET MVC是将Model-View-Controller模式应用到ASP.NET 框架,而形成的搭建web应用的架构。我们首先看一下ASP.NET MVC和ASP.NET 框架的关系,然后再逐个难点进行突破。
ASP.NET MVC怎样适应ASP.NET
自从2002年发布ASP.NET 1.0以来,人们很容易把ASP.NET 和Web Forms看做一回事。ASP.NET 通常支持两个抽象层:
- System.Web.UI: Web窗体层。包括服务端控件,View State等;
- System.Web:管道。提供基本的web堆栈,包括models, handlers,以及HTTP堆等。
ASP.NET的主要开发方法是有一系列的web表单堆叠而成的-通过拖拽控件,魔术式的状态管理,以及后台编译时神奇的服务端控件处理(但经常混淆页面生命周期,不够优化的HTML,等等)。
但是,有些可能性还是存在的——直接响应HTTP请求,按照web框架真正的工作方式来进行构建,以及通过Handlers,Modules或其他手写代码来编写优雅的HTML代码。你可以实现,但是十分复杂,因为没有任何内建的模式来支持这些。但是,在更广范围的计算机科学界是不乏设计模式的。自从2007年发布ASP.NET MVC以来,ASP.NET MVC正在逐渐成为最流行的web开发框架之一。
MVC模式
Model-View-Controller(MVC)多年来一直是重要的设计模式之一。1979年时最初被称作Tbing-Model-View-Editor,后来简称Model-View-Controller。它是用来分离应用程序关注点的强有力的方法(例如,将数据访问层和展示逻辑分离开来),并能极好地适用于web应用程序。很明显,分离关注点将会为应用程序的设计添加些许额外的复杂度,但肯定是利大于弊。自从发布以来已经应用于许多框架中,可以看到,无论在Java还是C++, Mac还是Windows,它已经渐渐融入了诸多框架。
MVC将应用程序的用户界面划分为三个方面:
- Model:一些描述将要处理的数据的类,并且定义一些数据修改和操作的逻辑规则。
- View:定义如何展示应用程序的用户界面(UI)。
- Controller: 处理用户交互、应用程序流以及具体的应用逻辑的类。
MVC用作用户界面模式
请注意我们引入MVC作为一种用户界面模型。MVC模式展示了一种处理用户交互的解决方案,但是并没有提到应该怎样处理数据访问、服务交互等其他应用程序的关注点。在通往MVC时要记住一点:它是有用的模式,但很可能只是开发应用过程中用到的诸多模式之一。
MVC用作web框架
MVC模式经常被用在web编程中,关于ASP.NET MVC可以大致这样理解:
- Models:这是一些呈现所关注的领域模型的类。这些领域模型通常封装存储在数据库中的数据,以及操作数据和增强领域业务逻辑的代码。对于ASP.NET MVC而言,通过使用Entity Framework和NHibernate工具,结合针对领域模型的业务逻辑的自定义代码,它在某种程度上类似于数据访问层。
- View:一个动态生成HTML的模板。在第3章会更加深入了解view。
- Controller:管理View和Model质检关系的具体类。它响应用户输入,告知Model,并决定要展示的view。在ASP.NET MVC中,该类以Controller为后缀。
通往MVC3之路
短短两年之内,已经发布了三个主要的ASP.NET MVC版本以及几个其他过渡版本。为了更好地理解ASP.NET MVC3,了解它的发展历程也是很重要的。本节主要介绍三个ASP.NET MVC版本的内容及背景。
ASP.NET MVC 1概述
2007年2月,微软的Scott Guthrie (“ScottGu”)在飞往美国东海岸参加会议的途中构思出了ASP.NET MVC的要点。这是一个简单的应用,只包含几百行的代码,但为一些web开发者听众带来的希望和潜力却是巨大的。
接下来,2007年10月,在华盛顿雷德蒙德举行的奥斯汀ALT.NET会议上,ScottGu想众多开发者展示了“在飞机上编写的超酷的东西”,并问他们是否看到了这个需要以及大家的看法。这是比较令人震惊的。事实上,很多人关心这个叫做Scalene的原型。Eilon Lipton 2007年9月将第一个原型发送给了团队,然后他和ScottGu 一起将原型、代码以及想法来回修改了多次。
即便到了官方版本发布之时,很明显ASP.NET MVC仍然不是我们标准的微软产品。它的开发周期包含了很强的交互性:官方版本发布之前发布了九个测试版本,进行单元测试,源代码也是采用公开的序列号。这一切都强调了一个哲理:在开发过程中要注重沟通交流。最终的成果是官方版MVC 1.0发布了,包含代码及单元测试,而且已经被由使用它的开发者们进行了预览和使用。ASP.NET MVC 1.0于2009年3月13日正式发布。
ASP.NET MVC 2概述
仅仅时隔一年之后,2010年三月ASP.NET MVC2发布了。MVC2的主要特点包括:
- 支持自定义模板的UI helpers.
- 客户端和服务端基于属性的Model验证
- 强类型HTML helper
- 改进Visual Studio 工具 :基于使用ASP.NET MVC1开发应用的开发者们的反馈,添加了许多API强化和高级特性,例如:
- 支持将较大的应用进行分割
- 异步Controllers支持
- 支持通过使用Html.RenderAction展示一个页面/站点的子段落
- 许多新的helper方法,实体,以及API强化
MVC2的发布开设了一个先例,即没有太多突破性的改变。我想这是ASP.NET MVC设计模式需要遵循的一个约定,在不改变核心的前提下进行一系列扩展。
ASP.NET MVC3概述
迫于Web Matrix的发布日期,ASP.NET MVC3(以后本书简称MVC3)在MVC2后10个月就发布了。假如MVC 3是装在箱子里的,那么它的前面可能会写着:
- 包含Razor引擎的View表现层!
- .NET 4的数据注释支持!
- 改进Model验证后的流线型验证!
- 包含了依赖方案和整体Action过滤的强大地钩子!
- 丰富的javascript支持,包括不唐突的javascript, jQuery验证以及JSON绑定!
- 开始NuGet!!!
对于曾经用过之前版本MVC的读者来说,我们将快速浏览一下这几个主要特性来开始我们的MVC之旅。
Razor引擎
Razor是自十年前ASP.NET 1.0发布以来对于HTML展示的一个最主要的更新。在MVC1和2中默认使用的view引擎是Web Forms View引擎,因为它和Web Forms使用相同的ASPX/ASCX/MASTER文件和语法。它可以正常运作,但它的设计是支持在图形编辑器中进行控件编辑的,然后进行显示。下面是一个Web Forms页面语法的例子:
<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master”
Inherits=”System.Web.Mvc.ViewPage<MvcMusicStore.ViewModels.StoreBrowseViewModel>”
%>
<asp:Content ID=”Content1” ContentPlaceHolderID=”TitleContent” runat=”server”>
Browse Albums
</asp:Content>
<asp:Content ID=”Content2” ContentPlaceHolderID=”MainContent” runat=”server”>
<div class=”genre”>
<h3><em><%: Model.Genre.Name %></em> Albums</h3>
<ul id=”album-list”>
<% foreach (var album in Model.Albums) { %>
<li>
<a href=”<%: Url.Action(“Details”, new { id = album.AlbumId }) %>”>
<img alt=”<%: album.Title %>” src=”<%: album.AlbumArtUrl %>” />
<span><%: album.Title %></span>
</a>
</li>
<% } %>
</div>
</asp:Content>
Razor是专门设计用来作为view引擎语法的。它有一个主旨: code-focused templating for HTML generation.下面是如何使用Razor生成相同的标签:
@model MvcMusicStore.Models.Genre
@{ViewBag.Title = “Browse Albums”;}
<div class=”genre”>
<h3><em>@Model.Name</em> Albums</h3>
<ul id=”album-list”>
@foreach (var album in Model.Albums)
{
<li>
<a href=”@Url.Action(”Details”, new { id = album.AlbumId })”>
<img alt=”@album.Title” src=”@album.AlbumArtUrl” />
<span>@album.Title</span>
</a>
</li>
}
</ul>
</div>
Razor语法容易输入和阅读,它不像Web Forms引擎中包含XML类似的重量级语法。
我们已经谈了用Razor语法进行开发的不同。为了将它推广到更多的地方,我们一起看一下开创Razor语法的团队的设计目标:
- 简洁,丰富,流畅: Razor对于生成HTML的模板的及其关注,最终造就了极其简约的语法。这不仅减少了键盘输入,当然这是不言而喻的,另外它还能很容易的表达你的意图。一个关键的例子是对于标签和代码之间传递数据时的简化。当你用循环来写一些model属性时会看到实际效果:
@foreach (var album in Model.Albums)
{
<li>
<a href=”@Url.Action(“Details”, new { id = album.AlbumId })”>
<img alt=”@album.Title” src=”@album.AlbumArtUrl” />
<span>@album.Title</span>
</a>
</li>
}
基于母版页的概念进行改进,Razor使用Layouts简化了标签,它具有更高的灵活性和更少的代码。
- 并非一种新生语言:Razor是一种让你能够凭直觉在模板中使用.NET编码技术的语法。
- 易于学习:正因为Razor不是一种新的语言,所以它是很容易学习的。了解了HTML,了解了.NET;那么就开始键入HTML,然后在需要编写.NET代码的时候输入@符号就可以了。
- 使用任何文本编辑器:由于Razor是专注于HTML的轻量级语法,你可以选择任意一种编辑器。Visual Studio的语法高亮和智能感知特性是非常友好的,不过实际上Razor简单到你可以在任何文本编辑器中进行编辑。
- 强大的智能感知:尽管Razor设计之初并未要求智能感知,不过当查看model对象支持的属性时,智能感知将会提供极大的便利。在这些情况下,Razor确实在Visual Studio中提供了完善的智能感知,如图1-1.
- 单元测试:Razor引擎的核心编译引擎并不依赖于System.web或ASP.NET等,它可以在单元测试甚至命令行中执行。尽管目前还没有直接支持这些的工具,但可以使用类似于David Ebbo 的Visual Studio单文件生成器(http://visualstudiogal-lery.msdn.microsoft.com/1f6ec6ff-e89b-4c47-8e79-d2d68df894ec/)的系统来将view编译成类,然后像其他项目一样进行加载和测试。
这仅仅是Razor使编写view代码简洁有趣的亮点之一,我们将在第3张中进一步深入讨论。
输入验证改进
输入验证是构建Web应用过程中非常重要的一环,但是并不有趣。我通常在确信它正常工作的前提下,花费尽可能少的时间来编写验证代码。
MVC2的属性驱动验证系统通过用声明性代码取代反复的强制性编码,从而减少了该过程中的许多麻烦。有许多情况下最好忘掉这种“主逻辑”,并且不得不编写更多大量的代码。MVC3扩展了这种验证支持,来应对将可能遇到的大多数情景。要想了解ASP.NET MVC更多关于验证的信息,请查看第6章。
.NET 4数据注释支持
MVC2是基于.NET3.5进行编译的,所以并没有提供对于.NET 4数据注释功能的支持。由于.NET 4的支持,目前MVC3已经添加了一些新的并且非常有用的验证特性。这些例子包括:
- MVC 2中的DisplayName特性是不能本地化的,但.NET 4支持的System.ComponentModel.DataAnnootations Display特性是可以的。
- ValidateAttribute在.NET 4中得到了增强,可以更好地在验证整个model的上下文时起作用,大大简化了否则可能要引用两个model属性的验证。
改善model验证而进行流线型验证
MVC3对于.NET 4 IValidatableObject借口的支持得到了广大的认同。通过在model类中实现该借口并实现Validate方法,你可以通过任何你能想到的方式扩展model类。代码如下所示:
public class VerifiedMessage : IValidatableObject {
public string Message { get; set; }
public string AgentKey { get; set; }
public string Hash { get; set; }
public IEnumerable<ValidationResult> Validate(
ValidationContext validationContext) {
if (SecurityService.ComputeHash(Message, AgentKey) != Hash)
yield return new ValidationResult(“Agent compromised”);
}
}
丰富的javascript支持
JavaScript在当代任何web应用中都是十分重要的部分。ASP.NET MVC3添加了一些客户端开发的重要支持,并集成了高质量JavaScript的当前标准。要想了解ASP.NET MVC3中新的Javascript相关特性,请看第8章。
高级特性
Dependency Resolution
ASP.NET MVC3引入了名为dependency resolver的新概念,它极大的简化了应用程序中的依赖注入的使用。它更容易去除应用程序组建的耦合性,并且提高了可配置性和可测试性。
以下情况下已经添加了相应支持:
- Controllers(注册并注入controller工厂,注入controller)
- Views(注册并注入view引擎,将依赖注入到view页面)
- Action 过滤器(定位并注入过滤器)
- Model绑定(注册并注入)
- Model验证提供(注册并注入)
- Model元数据提供(注册并注入)
- 值提供(注册并注入)
这是一个足够大的话题,所以我们用一整章(第11章)来讨论。
Global Action Filters
MVC2 action filters提供一个钩子,在执行某个action之前或者之后执行一些代码。它是通过将自定义特性应用于controller action或者全局controller来实现的。MVC2中包含了一些过滤器,就像 Authorize特性等。
MVC 3使用全局action过滤器进行了扩展,他可以应用于真个应用程序中的所有action方法。这对于应用程序的基础关注点是非常有用的,例如如handling和日志等。
MVC3特性总结:各种易用性
这是一些伟大的特性,但是如果让我来设计这个箱子,我会在上面写着:
- 如果你已经推迟了学习ASP.NET MVC,那么它是如此简单,没有任何理由再延迟了。
- 如果你已经学习ASP.NET MVC一段时间了,那么MVC3能让你的许多复杂的代码变得不在必要。
注:参考书籍《Professional ASP.NET MVC3》,仅供学习和交流,请勿用于商业用途。