第一章 MVC设计模式与ASP.NET MVC框架
学习目标
- 理解MVC设计模式
- 理解MVC三种组件的功能和关系
- 掌握ASP.NET MVC 框架的安装
- 掌握ASP.NET MVC Web Application的创建
- 理解MVC框架对请求的处理过程
1.1 MVC设计模式
MVC由Trygve Reenskaug提出,首先被应用在SmallTalk-80环境中,是许多交互和界面系统的构成基础。MVC结构是为那些需要为同样的数据提供多个视图的应用程序而设计的,它很好的实现了数据层与表示层的分离。MVC作为一种开发模型,通常用于分布式应用系统的设计和分析中,以及用于确定系统各部分间的组织关系。对于界面设计可变性的需求,MVC(Model-View-Controller)把交互系统的组成分解成模型、视图、控制器三种部件。
视图部件把表示模型数据及逻辑关系和状态的信息以特定形式展示给用户。它从模型获得显示信息,对于相同的信息可以有多个不同的显示形式或视图。
控制器部件是处理用户与软件的交互操作的,其职责是控制提供模型中任何变化的传播,确保用户界面与模型间的对应联系;它接受用户的输入,将输入反馈给模型,进而实现对模型的计算控制,是使模型和视图协调工作的部件。
模型部件保存由视图显示,由控制器控制的数据;它封装了问题的核心数据、逻辑和功能的计算关系,它独立于具体的界面表达和I/O操作。
模型、视图与控制器的分离,使得一个模型可以具有多个显示视图。如果用户通过某个视图的控制器改变了模型的数据,所有其它依赖于这些数据的视图都应反映到这些变化。因此,无论何时发生了何种数据变化,控制器都会将变化通知所有的视图,导致显示的更新。这实际上是一种模型的变化-传播机制。模型、视图、控制器三者之间的关系和各自的主要功能,如下图所示。
图
1.2 ASP.NET MVC框架
ASP.NET MVC Framework是微软在ASP.NET中所添加的一组类库,这组类库可以使用Model-View-Controller的设计模式来开发ASP.NET的应用程序。它与现有的使用Web Forms开发ASP.NET应用程序并没有冲突,所以两者是可以并行的。ASP.NET MVC Framework被包装在System.Web.Mvc.dll中,并利用ASP.NET Routing来支持动作流以及URL Rewriting的能力,让它可以更贴近Web的发展以及Web 2.0的特性。
ASP.NET MVC Framework的第一个版本于2009年3月17日释出RTM版本,新的MVC 2.0目前正在开发,并且也释出了预览版本(CTP)。
ASP.NET MVC Framework虽然是ASP.NET的一部份,不过它的源代码是通过Microsoft Public License (MS-PL)的授权模式公开,因此在MS-PL授权的范围内,任何人是可以去查看与修改它的源代码的。
要安装ASP.NET MVC框架,可访问ASP.NET MVC的官方网站:http://www.asp.net/mvc/,下载其安装文件。安装完成后,可使用Visual Studio 2008创建ASP.NET MVC Web Application。
要获取ASP.NET MVC框架的源代码,可访问CodePlex:http://www.codeplex.com/aspnet。
1.3 创建ASP.NET MVC Web Application
本节将介绍创建ASP.NET MVC Web Application的一般步骤。
1、 确认已经成功安装ASP.NET MVC框架,准备你的工作目录如:“E:\ASP.NET MVC\第一章”。
2、 启动Microsoft Visual Studio 2008。
3、 执行[文件]-[新建]-[项目],进入[新建项目]对话框。如下图:
图
4、 在[新建项目]对话框中,选择[项目类型]为“Visual C#”-“Web”,选择.NET Framework版本为“.NET Framework 3.5”,选择[模板]为“ASP.NET MVC Web Application”,在[位置]文本框中输入你的工作目录如“ E:\ASP.NET MVC\第一章”,在[名称]文本框中输入项目名称如“MvcApplicationExample”。点击[确定]按钮。
5、 进入[Create Unit Test Project]对话框。如下图:
图
在这个对话框中,Visual Studio 2008询问你“是否要为这个应用程序创建一个单元测试项目”,可选择“No”,即暂时不需要单元测试。点击[OK]按钮。
6、 此时可在你的工作目录中看到创建成功的项目。如下图:
图
7、 在[解决方案资源管理器]中可以看到MVC Application 项目的目录结构和包含的文件。如下图:
图
8、 执行[调试]-[开始执行]或按快捷键[CTRL+F5],可运行这个项目。
9、 此时,Visual Studio 2008将启动内置的ASP.NET Development Server承载这个Web应用程序,并通过本机的默认浏览器请求Web应用程序根目录下。
Dvelopment Server控制台如下图:
图
浏览器中呈现的页面如下图:
图
1.4 项目的目录结构与核心组件
新建的ASP.NET MVC Web Application项目由项目模板提供了默认的目录结构。如下图所示:
图
| App_Data | 与一般的基于Web Form的ASP.NET Web应用程序是一样的,用于存放SQL Server Express的数据文件。 |
| Content |
用于存放静态的资源文件的。例如CSS、JS、图片等等。 |
| Scripts | 用于存放JS脚本文件。项目模板默认包含三个JS文件:jquery-1.3.2.js,MicrosoftAjax.js和MicrosoftMvcAjax.js。 |
| Controllers | 用于集中存放Controller类文件。Controller类的命名应以Controller结尾,例如一个名为Home的Controller应命名为HomeController。 |
| Models |
用于存放实现业务模型的类文件,如业务实体类、及实现数据访问和业务逻辑的类等。也可能将Models存放在编译过的类库中,在项目中引用此类库。 |
| Views | 用于集中存在View文件,一般是*.aspx页面。每一个Controller对应一个子目录,而且子目录的名称应与相应的Controller的同名。例如,HomeController的view就应该放到Home子目录中。Views目录下还有一个Shared的子目录,它是用于存放一些共享的view的,例如Error.aspx和Site.Master。Controller在Views\ControllerNmae目录中找不到指定的view文件的时候,会到Shared中去寻找。 |
| Web.config | 项目的配置文件 |
| Global.asax | 应用程序全局文件。用于处理应用程序全局的事件和设置路由策略。 |
| Default.aspx | 应用程序根目录下的默认页。当直接请求应用程序根目录时,将由此文件处理请求。 |
表
MVC项目默认引用的程序集如下图:
图
其中几个重要的程序集解释如下:
System.Web.Routing
用于实现URL路由的程序集。在HttpModule中使用此组件将请求的URL映射到某个Controller及其Action。包含在.NET Framework 3.5 SP1中。
System.Web.Extensions
用于实现ASP.NET AJAX的程序集。
System.Web.Mvc
ASP.NET MVC最主要的程序集。包含在ASP.NET MVC框架的安装包中。
System.Web.Abstractions
提供一组与Web应用程序相关的抽象基类。包含在.NET Framework 3.5 SP1中。
表
实际上,如果你没有安装ASP.NET MVC框架,也可先创建一般的基于Web Form的ASP.NET Web 应用程序,然后在项目中引用上述程序集,再修改配置文件,这样也可得到MVC Web Application。
1.5 请求的处理过程
本节分析请求送到Web服务器后,MVC框架在发还响应之前的处理过程。
从一个实验开始。
之前第一次运行MVC Web Application时,浏览器请求的URL为:http://localhost:2016/。由于URL中的虚拟路径为“/”,所以ASP.NET Web Development Server会将此URL映射到物理路径为当前应用程序根目录:“E:\ASP.NET MVC\第一章\MvcApplicationExample\”,此时Web服务器应执行的是此目录内的默认页面Default.aspx。然而在浏览器中呈现的界面明显不是Default.aspx页面的,因为这个页面根本没有可见的内容。实现上,浏览器中的内容是Views目录中Home子目录中的Index.aspx页面执行的结果。
将浏览器地址栏中的URL改为“http://localhost:2016/Views/Home/Index.aspx”,回车请求此页面。结果如下图:
图
结果为404错误,找不到请求的资源!可以确定请求的URL是没有错误的,如果按照Web Form的工作方式,这个URL应映射到物理路径” E:\ASP.NET MVC\第一章\MvcApplicationExample\Views\Home\Index.aspx ”,这个物理文件也是存在的。
再将浏览器地址栏中的URL改成:http://localhost:2016/Home/Index,回车请求此地址,结果是可正常访问到Views目录中Home子目录中的Index.aspx页面。注意:在Web应用程序的根目录下根本不存在Home目录,它是根目录下Views目录的子目录;而Index也不能视为Index.aspx页面的文件名,因为它没有扩展名。
既然不是直接请求在应用程序目录下存在的物理文件,那么MVC框架如何处理URL请求呢。
1、 寻找入口方法。
之所以请求一个与特定的物理的aspx页面文件没有直接映射关系的URL能够执行并获得这个aspx页面,是因为MVC框架中使用URL重写。在ASP.NET MVC的术语中称为Routing,译为中文可称为路由。实现路由功能的组件是System.Web.Routing.dll程序集。
打开Global.asax.cs类文件,查看其代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcApplicationExample
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", //路由的名称
"{controller}/{action}/{id}", //带参数占位符的URL
new { controller = "Home", action = "Index", id = "" } //参数的默认值
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
}
Application_Start方法是应用程序启动事件的处理程序,它的作用是:在Web应用程序启动时,向MVC框架注册路由规则。
路由规则由System.Web.Routing.RouteCollection集合类中的项表示。IgnoreRoute和MapRoute是System.Web.Mvc.RouteCollectionExtensions静态类为此集合类提供的扩展方法,其中IgnoreRoute用于忽略对URL进行路由映射,在这里是指MVC框架对以axd作为扩展名的文件不进行路由映射;MapRoute则用于对URL进行路由映射。按照MapRoute方法中第二个参数的规则,URL中服务器域名[或IP]和端口之后的部分将以“/”为分隔符被分割成三部分,第一部分表示Controller控制器的名称,第二部分为Action动作方法的名称,第三部分为传递给Action方法的参数值。MapRoute方法的第三个参数则为URL中各个占位符提供默认值。
按照这个路由规则,浏览器请求的URL http://localhost:2016/Home/Index或http://localhost:2016/都将被解析为:Controller为Home,Action为Index,Id为空字符串。
关于路由组件的使用和路由规则的建立,将在后续章节中详细讲解。
2、 寻找Controller控制器。
在Controllers文件夹中可以找到HomeController.cs类文件。按照路由规则,从URL中获取到的Controller控制器名称为Home,则相应的控制器类的类名应为HomeController。这里使用一个约定,即控制器名称+Controller=控制器类名。
控制器类派生自System.Web.Mvc.Controller基类。
3、 寻找Action动作。
打开HomeController.cs类文件,查看其代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcApplicationExample.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
}
}
在HomeController控制器类中,有两个公共方法,返回类型都是ActionResult类,这种方法叫做Action动作方法。由于按照路由规则从URL中提取到的Action为Index,所以MVC框架将调用名为Index的Action动作方法。实际上,控制器所要实现的控制逻辑是在各个Action动作方法中实现的,根据请求的URL中提取的Action名称,MVC框架决定调用哪个Action方法来实现控制逻辑。
控制器的功能是获取模型对象,并选择一个视图由其显示模型的数据,它还负责将模型传递给视图。
Index方法第一行代码是借助于ViewData集合向视图传递模型数据。ViewData是ControllerBase控制器基类提供的属性,它的类型为ViewDataDictionary基于字典的键值对集合。
Index方法第二行代码是选择并返回视图。
4、 寻找View视图。
视图一般为aspx页面。
View方法决定使用哪个视图,可传入字符串参数说明要使用的视图文件名。当它被无参调用时,它将返回Views视图文件夹中与当前控制器同名的子文件夹中与当前动作方法同名的视图结果,即Views/Home/Index.aspx。这里也使用了一个约定:在Views视图文件夹中要按照Controller控制器的名称来创建子文件夹,如名为Home 的控制器在Views中有对应的Home子文件夹,其中存放了此控制器需要的视图文件;视图文件名称又与Action动作名称对应,如Index.aspx对应着名为Index的动作。
5、 视图呈现。
视图负责呈现模型数据。
打开Index.aspx文件,查看其代码。
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
Home Page
</asp:Content>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<h2><%= Html.Encode(ViewData["Message"]) %></h2>
<p>
To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
</p>
</asp:Content>
页面指令中声明了此页面的基类为System.Web.Mvc.ViewPage,ViewPage是所有视图页面的基类。当解析器解析此页面时,将从System.Web.Mvc.ViewPage派生出一个表示此页面的新类。
第二个Content标签中包含一行服务器端脚本。如下:
<% = Html.Encode(ViewData["Message"])%>
这行脚本是为了将模型的数据输出到页面中呈现。其中ViewData是ViewPage基类的属性,这个属性的类型为System.Web.Mvc.ViewDataDictionary,访问此属性可以获取由控制器传递给当前视图的模型数据;Html也是ViewPage基类提供的属性,这个属性的类型为System.Web.Mvc.HtmlHelper,它是个帮助器,主要作用是生成与HTML元素相关的文本。
此视图将被ViewEngine视图引擎[默认是WebForm]解释并编译,然后执行,其中的文本、HTML代码、输出的模型数据等将生成响应流,发送到浏览器端。
最后,我们可总结出MVC框架对URL请求的一般处理过程。
首先,用户通过浏览器向服务器发送url请求,这里请求的url与WebForm不同,不再是直接请求xxx.aspx文件,而是http://HostName/ControllerName/ActionName/Parameters的形式。这个请求被ASP.NET MVC的路由映射系统截获。路由映射可以在Global.asax中配置。路由映射系统按照映射规则,解析出控制器名ControllerName,动作名ActionName和各个参数Parameters,然后,找寻Controllers目录下的ControllerNameController.cs这个控制器类,默认情况下,系统总是找寻Controllers目录下的名称形式为“控制器名+Controller”的类,然后,找寻这个类中与ActionName同名的方法,找到后,将Parameters作为参数传给这个方法,而后Action方法开始执行,完成后返回相应视图,默认情况下,会返回Views目录下与ControllerName同名的子目录下的与ActionName同名的aspx文件,并且将ViewData传递到视图。ViewData中一般包含了控制视图显示的控制量以及视图显示需要的模型数据。
处理过程如下图所示:
图

浙公网安备 33010602011771号