二、理解Models,Views,Controllers
一、理解Models,Views,Controllers
这篇文章的主要目的就是来解绍ASP.NET MVC中的M,V,C这三个概念。
通过这篇文章我们来学习ASP.NET MVC的各部分如何一起协调工作,以及ASP.NET MVC体系结构与ASP.NET WEB FORMS传统程序结构和ASP的区别。
二、简单的ASP.NET MVC程序
VS的ASP.NET MVC模板会生成一个非常简单而完整的ASP.NET MVC程序框架,在这里我们就使用这个程序框架。
在VS2008中点击“文件”-“新建项目”打开新建项目对话框。在左边选择语言类型,在模板区域选择ASP.NET MVC Web Application,填写项目名称及项目所在位置,点击确定按钮。
![](http://hiphotos.baidu.com/grayworm/pic/item/a772e76edc6e8bc680cb4a0a.jpg)
《图1》
在创建ASP.NET MVC应用程序的时候,系统会提示我们是否要创建试项目。在这里我们不创建测试项目。
![](http://hiphotos.baidu.com/grayworm/pic/item/c07ec710a443e31d203f2e0b.jpg)
《图2》
当ASP.NET MVC 应用程序创建完成后,在解决方案管理器窗口中,我们会看到几个文件夹和文件。其中有三个文件夹非常引人注目:Models,Views,Controllers。通过字面意思大家可以猜到这三个文件夹的作用了,它们是分别存放模型文件、视图文件和控制文件的文件夹。
展开Controllers文件夹,我们会看到一个名子为HomeController.cs的文件。展开Views文件夹,我们会看到有两个子文件夹Home和Shared,展开Home文件夹我们会看到有页面两个文件About.aspx和Home.aspx(如下图所示)。这此文件形成了一个简单的ASP.NET MVC程序框架。
![](http://hiphotos.baidu.com/grayworm/pic/item/eda893f9ae81ba45242df214.jpg)
《图3》
在第一次按F5键或点击调试动行按钮时,会出一个对话框,如下图所示,提示我们是否要启用Web.Config文件中的调试开关。我们点击“确定”继续运行程序
![](http://hiphotos.baidu.com/grayworm/pic/item/0be209a9ab8b15e01f17a216.jpg)
《图4》
当我们运行ASP.NET MVC应用程序的时候,VS在浏览器中启动项目。这个简单的程序框架只包含两个页面:Index页面和About页面。在运行的时候默认显示Index页面,当我们点击About US链接时,会显示About页面
![](http://hiphotos.baidu.com/grayworm/pic/item/6daef9de4d2f0b44cdbf1a16.jpg)
《图5》
在这里需要我们注意浏览器的地址栏。当我们点击Home超链接时,浏览器地址栏会变为/Home,当我们点击About Us超链接时,浏览器地址栏会变成/About
但当我们关闭浏览器,返回VS开发界面后,在程序中我们并没有发现Home和About这两个页面文件。这是为什么呢?
三、一个URL地址并不对应于一个页面!(原创:灰灰虫的家 http://hi.baidu.com/grayworm)
在传统的ASP.NET Web Forms应用程序或ASP程序中,它们的URL地址与页面文件之间是一一对应的关系。如果我要访问SomePage.aspx页面,那在服务器的硬盘上必须得有一个SomePage.aspx文件。否则会产生404-Page Not Found的错误。
相反地,在ASP.NET MVC程序中,浏览器地址栏中的URL路径和应用程序中的文件之间并没有对应关系。实际上,在ASP.NET MVC应用程序中,浏览器地址栏中的URL地址是与控制器(Controller)的动作(Action)相对应。
在传统的ASP.NET 或 ASP程序中,浏览器的请求被映射到文件上;而在ASP.NET MVC 应用程序中,浏览器的请求被映射到控制器的动作上。
传统的ASP.NET 或 ASP程序是以内容为中心,而ASP.NET MVC 应用程序则是以程序逻辑为中心。
四、理解URL Routing
浏览器的请求被映射到控制器的相应动作上,这个映射过程我们称之为URL Routing。URL Routing就是把入站请求路由到相应的控制器动作上。
URL Routing是通过路由表来处理请求的。路由表被写在Global.asax文件中,在程序第一次运行的时候会调用这段程序创建路由表。默认情况下,MVC的Global.asax文件代码如下:
Listing 1 – Global.asax
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcApplication1
{
public class GlobalApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Default","{controller}/{action}/{id}",new {controller ="Home",action="Index",id=""});
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
}
当ASP.NET应用程序第一次启动的时候,会调用Application_Start()方法。这个方法中调用了RegisterRoutes()方法,在RegisterRoutes()方法中创建了一个默认的路由表。
默认情况下,路由表只包含一个路由。这个路由将所有的入站请求URL 地址分解为三个部:
第一部分:映射到控制器名上。
第二部分:映射到控制器的动作名上。
第三步分:映射到动作函数的Id参数上
例如:URL地址/Product/Details/3 被解析为三部分如下:
Controller = ProductController
Action = Details
Id = 3
路由的三个部分在不做设置的情况下都具有默认值。
Controller默认值为HomeController。
Action的默认值为Index。
Id的默认值为空字符串。
好了,记住这些默认值后,我们再来分析下面的URL地址
/Employee
它的URL地板被解析后的三个部分为:
Controller = EmployeeController
Action = Index
Id = “”
最后来看一下,如果我们打开ASP.NET MVC应用程序时不加任何的URL地址的情况:
如:http://localhost/ 被解析为:
Controller = HomeController
Action = Index
Id = “”
大家可以看到,这种情况被默认被路由到HomeController类的的Index()动作上了。
五、理解控制层
在MVC程序中,控制层用来响应用户的请求,当浏览器发出请求时,由控制层接收,并把处理结果发送回浏览器。
控制器是一个类,在ASP.NET MVC程序中,在Controller文件夹中包含一个名子为HomeController.cs的控制器。HomeController.cs的代码如下:
Listing 2 – HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
ViewData["Title"] = "About Page";
return View();
}
}
}
在HomeController中包含两个方法Index()和About()。这两个方法就是两个动作。当客户端发出/Home/Index请求时,会触发HomeController.Index()方法;当客户端发出/Home/About请求时会触发HomeController.About()方法。
控制器的任何public方法都被当作是控制器的动作。也就是控制器的所有public方法都可以在浏览器的URL地址栏中进行调用,因此,我们要对此小心设计。
六、理解视图层
控制层的HomeController类中的Index()和About()都返回一个视图。视图包含要发送到客户端的HTML标记和文档内容。视图相当于ASP.NET MVC应用程序的页面。
在创建视图的进候,我们需要正确设置视图的位置。
HomeController.Index()动作返回视图的路径为:\Views\Home\Index.aspx
HomeController.About()动作返回视图的路径为:\Views\Home\About.aspx
一般地,想让控制器的动作返回视图的话,我们需要在Views文件夹下创建一个子文件夹,该子文件夹应具有与控制器相同的名子。在子文件夹内我们需要创建一个.aspx文件,该.aspx文件应具有与控制器的动作相同的名子。About.aspx视图代码如下:
Listing 3 – About.aspx
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="About.aspx.cs" Inherits="MvcApplication1.Views.Home.About"%>
<asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server">
<h2>About Us</h2>
<p>
TODO: Put <em>about</em> content here.
</p>
</asp:Content>
上面的代码中,除了第一行外,其余的内容是标准的HTML,我们可以在需要的地方修改视图的HTML内容。
一个MVC的视图与ASP或ASP.NET Web Forms比较相似。我们可以在视图的HTML内容中嵌入相应的服务器代码(C#或VB.NET)。使用脚本代码来控制数据显示。
七、理解模型层
上面我们讨论了控制层和模型层。下我们来再来谈一下模型层
MVC模型层包含了控制层和视图层之外的应用程序的所有逻辑。模型层应当包含应用程序所有的商业逻辑和数据库访问逻辑。例如:如果使用Linq to Sql访问数据库的话,应当在Models文件夹中创建建Linq to Sql类(dbml文件)。
视图层应当只包含生成用户界面的逻辑。控制层应当只包含返回视图或动作跳转等极少量的程序逻辑。其余所有剩下的东西都应当包含在模型层中。(原创:灰灰虫的家 http://hi.baidu.com/grayworm)
一般地,我们应当尽量实现“较厚”的模型层和“极薄”的控制层。控制层的方法中应当包含尽量的少的程序代码。如果控制层“太厚”的话,我们应想考虑把控制层部分逻辑转移到模型层中去。
总结:
这篇文章从总体上来看了ASP.NET MVC WEB应用程序的各个部分。
知道如何把URL地址路由到不同的控制器动作上。
知道控制如何与视图相协调返回用户数据。
知道模型层如何包含数据访问逻辑和商业逻辑。