一、 简介
MVC(模型—视图—控制器)结构模式把一个应用程序拆分成三个主要组件:模型、视图和控制器。在创建基于MVC框架的Web应用程序时,你可以把ASP.NET MVC框架作为ASP.NET Web表单模式方案的一种重要候选。较之于基于Web表单的应用程序,ASP.NET MVC框架是一个轻量级的、测试性强的描述框架,它能够与现有ASP.NET特征(例如母版页面和基于成员身份的认证)紧密集成。MVC框架定义于System.Web.Mvc命名空间中。
长时间以来,MVC是一种为众多开发人员所熟悉的标准设计模式。一些类型的Web应用程序受益于MVC框架,而另一些将继续使用基于Web表单与回寄技术的传统型ASP.NET应用程序模式,还有一些类型的Web应用程序则有可能把这两种模式结合到一起使用。总之,MVC框架方案与Web表单方案并非相互排斥的。
总体来看,MVC框架包括下列组件:
(一)模型。模型对象是实现应用程序数据域逻辑的部分。经常情况下,模型对象还负责从数据库中检索和存储模型状态。例如,一个产品对象有可能从一个数据库中检索信息,操作其中的数据,然后把更新信息写会SQL Server数据库中的某一个产品表格内。
【提示】在小型应用程序中,模型经常是一个概念上的分离而不是一个物理概念。例如,如果应用程序仅读取一个数据集并且要把它发送到视图中,那么应用程序就不必专门创建一个物理模型层和相关联的类。在这种情况下,数据就直接承担了一个模型对象的角色。
(二)视图。视图是负责显示应用程序的用户接口(UI)的组件。典型情况下,这个UI是基于模型数据创建的。一个典型的示例就是一个产品表格的编辑视图。在此视图中,可以基于一个产品对象的当前状态显示文本框、下拉列表框和复选框等控件。
(三)控制器。控制器组件的作用是负责处理用户交互,操作模型,并且最终选择一个要显示UI的视图并生成之。在一个MVC应用程序中,视图仅仅负责显示信息,而由控制器负责处理和响应用户输入与交互。例如,由控制器来处理查询字符串值,并且把这些值传递到模型,然后在模型中使用该值进行数据库查询。
MVC模式在帮助你把应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离开来的同时,提供了这些元素之间的松耦合。MVC模式要求每一种不同的逻辑应该存在于应用程序中的特定位置。例如,UI逻辑隶属于视图,而输入逻辑隶属于控制器,业务逻辑则隶属于模型。这种分离有助于你在构建一个应用程序管理复杂性,因为它能够使你在某一时刻仅专注于实现的一个方面。例如,你可以专注于视图而不去关心业务逻辑。
除了管理复杂性外,较于测试一个传统型ASP.NET Web应用程序,基于MVC模式进行开发使得测试应用程序更加容易。例如,在一个传统型ASP.NET Web应用程序中,单个的类既用于显示输出也用于响应用户输入。因此,为传统型ASP.NET应用程序编写自动化测试可能非常复杂,因为为了测试单个页面,你必须实例化页面类,它所有的子控件以及应用程序中的其他依赖类。总之,你需要实例化大量的类才能够运行该页面,所以这种情况下要比针对应用程序的单个部件编写测试困难得多。于是,针对传统型ASP.NET应用程序的测试很可能比实现一个使用MVC框架开发的应用程序的测试要复杂和艰难得多。而且,一个传统型ASP.NET应用程序在测试时还需要使用一个Web服务器。相比之下,MVC框架把组件分离开来并且大量地使用接口,这使得有可能独立于框架的其他部分而较容易地单独测试单个组件。
此外,一个MVC应用程序的三个主要组件之间的松耦合特征还推动了平行开发。例如,一名开发人员可以开发视图,而另一名开发人员则在开发控制器逻辑,第三名程序员则可以专注于模型部分的业务逻辑的开发。
二、 基于MVC框架Web应用程序的优点
归纳来看,ASP.NET MVC框架主要提供了下列优点:
三、 基于Web表单Web应用程序的优点
传统型基于Web表单的框架能够提供下列优点:
四、 ASP.NET MVC框架特征
概括来看,ASP.NET MVC框架大致提供了下列重要特征:
五、 URL映射
典型情况下,在一个ASP.NET网站中,URL会被映射到存储在磁盘上的文件(主要是指.aspx文件)。这些.aspx文件中将包括针对客户端发出的请求要处理的代码或标记。
ASP.NET MVC框架以不同于ASP.NET网站应用程序的方式把URL映射到服务器代码。MVC框架不是把URL映射到ASP.NET页面或HTTP处理器程序,而是直接把URL映射到特定的控制器类。然后,由控制器类负责处理发来的请求,例如用户输入与交互,以及基于用户输入执行适当的应用程序及数据逻辑。典型地,一个控制器类调用一个单独的视图组件来生成相应的HTML输出作为对客户端发出请求的响应。
在ASP.NET MVC框架中,模型、视图和控制器组件被分离开来。典型地,模型组件主要负责维护数据库中持久数据的状态,而视图组件则由控制器进行选择并最终在客户端生成相应的UI。默认情况下,ASP.NET MVC框架使用现有ASP.NET页面(.aspx),母版页面(.master)和用户控件(.ascx)类型作为在浏览器端的输出形式。控制器组件将定位控制器中适当的行为方法,取得用作行为方法的参数值,处理执行行为期间所有可能发生的错误,并生成要求的视图。每一组组件各自存在于一个MVC Web应用程序工程的一个单独的文件夹下。
通过提供了一个URL映射引擎,ASP.NET MVC框架在把映射URL到控制器类方面提供了相当的灵活性。你可以使用这种映射引擎来定义路由规则,然后ASP.NET MVC框架使用这些路由规则来计算发来的URL请求并选择要执行的控制器。你还可以让路由引擎自动地分析URL中定义的变量并且使ASP.NET MVC框架把这些内容以参数方式传递给控制器。
六、 MVC框架与页面回寄
ASP.NET MVC框架并不使用传统的ASP.NET回寄模型来实现与服务器端的交互。代之的是,所有的终端用户交互都被路由到一个控制器类。这有利于保持UI逻辑和业务逻辑的分离,并且有助于测试目的。结果是,ASP.NET视图状态和ASP.NET页面生命周期事件并没有与基于MVC的视图集成到一起。
七、 创建一个简单的ASP.NET MVC应用程序
ASP.NET MVC框架提供了支持Visual Studio的工程模板,从而让你创建支持MVC模式的Web应用程序。
这些MVC工程模板包括:
这些模板可以用于创建一个新的基于ASP.NET MVC框架的Web应用程序。在这些程序中,你可以使用文件夹,模板以及配置文件等手段配置它们。
默认情况下,当你使用“ASP.NET MVC Web Application and Test”模板创建一个新的Web应用程序时,Visual Studio将创建一个添加有两个工程的方案。第一个工程是一个Web工程,你可以在其中实现你的应用程序。第二个工程是一个测试工程,你可以在此为你的MVC组件编写单元测试。
【注意】“ASP.NET MVC Web Application”模板基于“ASP.NET Web Application”模板。所以,在创建基于ASP.NET MVC框架的网站时,你需要从“File”菜单下选择“New Project”,然后选择一个新的ASP.NET MVC工程,而不是选择“New Website”。
最后,你可以使用任何与.NET框架兼容的单元测试框架来测试ASP.NET MVC应用程序。注意,Visual Studio 2008 Professional(以及Team System)已经提供了对于MSTest测试工程的内置的支持。
八、 Web应用程序的MVC工程架构
当你创建一个ASP.NET MVC Web应用程序工程时,诸MVC组件将基于如图1所示的工程文件夹加以分离:
图1—一个ASP.NET MVC Web应用程序的典型架构
除了上面列举的文件夹外,一个MVC Web应用程序还使用下列一些重要的应用程序元素:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
//注意:如果把下列表达改写成Url="{controller}.mvc/{action}/{id}"即可自动支持IIS6
RouteTable.Routes.Add(new Route
{
Url = "{controller}/{action}/{id}",
Defaults = new { action = "Index", id = (string)null },
RouteHandler = new MvcRouteHandler()
});
RouteTable.Routes.Add(new Route
{
Url = "Default.aspx",
Defaults = new { controller = "Home", action = "Index", id = (string)null },
RouteHandler = new MvcRouteHandler()
});
}
}
下列代码展示了一个ASP.NET MVC应用程序的httpModules节的内容:
<httpModules>
<add name="UrlRoutingModule"
type="System.Web.Mvc.UrlRoutingModule,
System.Web.Extensions, Version= 3.6.0 .0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
</httpModules>
当你在Visual Studio 2008 Professional(或Team System)选择一个ASP.NET MVC Web应用程序和测试工程模板时,方案中将自动包括一个测试工程。你可以使用MVC模板来创建测试以及内在接口的mock实现。
九、 理解MVC工程的执行过程
一个发送到ASP.NET MVC的Web应用程序请求首先要传递到UrlRoutingModule对象(这是一个HTTP模块)。然后,UrlRoutingModule对象分析该请求并执行路由选择。值得注意的是,UrlRoutingModule将选择匹配当前请求的第一个路由(Route)对象。
接下来,UrlRoutingModule对象从选择的路由对象中取得IHttpContext对象—由它进一步处理请求。默认情况下,这个IHttpContext就是MvcHandler对象。然后,MvcHandler对象进一步选择相应的控制器,最终由此控制器来处理该请求。
【注意】当一个ASP.NET MVC Web应用程序运行于IIS7环境下时,并不要求为MVC工程指定文件的扩展名。然而,在IIS6中,处理器要求你把.mvc文件扩展名映射到ASP.NET ISAPI中。
模块和处理器成为指向ASP.NET MVC框架的入口,并执行下列动作:
表格1更细致地描述了一个MVC Web工程的各个执行阶段。
表格1—MVC Web工程的各个执行阶段
阶段 |
详细描述 |
初始请求 |
在Global.asax文件中,把路由添加到RouteTable对象。 |
路由 |
UrlRoutingModule模块根据RouteTable实例中匹配的Route对象创建RouteData对象。这些路由数据用于决定所请求的控制器及要调用的行为。 |
映射到控制器 |
MvcRouteHandler处理器负责根据RouteData实例中的数据创建控制器类型名。 |
调用控制器构建程序(controllerbuilder) |
处理器调用ControllerBuilder类的全局静态CreateController方法从而得到一个IController实例。如果没有返回一个IController实例,那么该处理器将返回一个HTTP 500错误指示出现了服务器错误。 |
创建控制器 |
由ControllerBuilder实例直接创建一个新的控制器,或使用一个IControllerFactory对象来创建该控制器。 |
执行控制器 |
MvcHandler实例被添加到ControllerContext对象中并调用该控制器的Execute方法。 |
十、 小结
在本文中,我们对微软最新推出的MVC(模型—视图—控制器)模式进行了理论的剖析,并把它与传统的ASP.NET Web表单模式和页面回寄方案进行了对比。在了解了MVC框架各组件主要功能之后,最后我们对一个典型的MVC Web工程的各个执行阶段作了粗略的归纳。
最后需要注意的是,ASP.NET MVC模式是微软最新推出的一种开发模式,目前最新测试版本为Preview 2(Preview 3也即将问世)。因此,这一模式是否较之于ASP.NET Web表单模式更有利于提高软件的生产效率还有待于开发实践的检验。