摘要
????? 本文對ASP.NET MVC的全局運行機理進行一個簡要的介紹,以使得朋友們更好的理解后續文章。
前言
????? 在上一篇文章中,我們實現了第一個ASP.NET MVC頁面。對于沒有接觸過這個框架的朋友來說,可能對有些地方會迷惑,所以這篇文章我將通過圖示配合文字的方法,站在全局的角度介紹一些ASP.NET MVC的運行機制,這樣可以幫助朋友們更好的理解后續文章。^_^
全局
????? 首先我們來看一副圖片,由于這幅圖是我自己畫的,不是摘自微軟官方,所以如果有什么不到位的地方還望海涵!
????? 首先,用戶通過Web瀏覽器向服務器發送一條url請求,這里請求的url不再是xxx.aspx格式,而是
http://HostName/ControllerName/ActionName/Parameters
的樣子。這個請求被ASP.NET MVC的路由映射系統截獲。(路由映射可以在Global.asax中配置,我們一會再說)路由映射系統按照映射規則,解析出控制器名 ControllerName,Action名ActionName和各個參數Parameters,然后,找尋Controllers目錄下的 ControllerNameController.cs這個控制器類,默認情況下,系統總是找尋Controllers目錄下的“控制器名+Controller”這么一個類,然后,找尋這個類下與ActionName同名的方法,找到后,將Parameters作為參數傳給這個方法,而后Action方法開始執行,完成后返回相應視圖,默認情況下,會返回Views目錄下與ControllerName同名的目錄下的與 ActionName同名的aspx文件,并且將ViewData傳遞到視圖。ViewData中一般包含了控制視圖顯示的控制量以及視圖顯示需要的數據。
????? 我們按以上思路回顧一下上一篇中主頁的請求過程。我們傳遞的url是
http://localhost/Home/Index
。默認路由規則下,將ControllerName設為“Home”,ActionName設為“Index”,沒有參數。于是系統找尋 Controllers目錄下的HomeController類的Index方法,成功找到,于是執行之。這個方法調用Mock的Model取出一些數據,放入ViewData相應鍵值項里。然后返回視圖,返回的是Views下Home下的Index.aspx。這個視圖取出ViewData中的數據按照一定格式呈現,于是完成了一次典型的ASP.NET MVC調用。
路由
????? 從上面可以看出,ASP.NET MVC中路由是很重要的。它直接決定了如何解析url,因此決定了系統如何工作。那么,下面我們來揭開路由神秘的面紗。
????? 打開我們Demo下的Global.asax.cs文件,可以看到如下代碼:
Global.asax.cs:
- using ?System; ??
- using ?System.Collections.Generic; ??
- using ?System.Linq; ??
- using ?System.Web; ??
- using ?System.Web.Mvc; ??
- using ?System.Web.Routing; ??
- ??
- namespace ?MVCDemo ??
- { ??
- ???? //?Note:?For?instructions?on?enabling?IIS6?or?IIS7?classic?mode,? ??
- ???? //?http://www.my400800.cn ??
- ??
- ???? public ? class ?MvcApplication?:?System.Web.HttpApplication ??
- ????{ ??
- ???????? public ? static ? void ?RegisterRoutes(RouteCollection?routes) ??
- ????????{ ??
- ????????????routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" ); ??
- ??
- ????????????routes.MapRoute( ??
- ???????????????? "Default" ,?????????????????????????????????????????????? //?Route?name ??
- ???????????????? "{controller}/{action}/{id}" ,??????????????????????????? //?URL?with?parameters ??
- ???????????????? new ?{?controller?=? "Home" ,?action?=? "Index" ,?id?=? "" ?}?? //?Parameter?defaults ??
- ????????????); ??
- ??
- ????????} ??
- ??
- ???????? protected ? void ?Application_Start() ??
- ????????{ ??
- ????????????RegisterRoutes(RouteTable.Routes); ??
- ????????} ??
- ????} ??
- }??
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MVCDemo { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // http://www.my400800.cn public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } } }?
????? 我們揀重點說。注意上面有個routes.MapRoute方法。這個方法的作用是向系統增加一條路由規則。這里唯一的一條規則是系統默認增加的,第一個參數是規則名,是一個普通字符串。關鍵是第二個參數,它也是一個字符串,但是它描述了如何解析url。可以這樣理解,它描述了url串HostName后面部分如何匹配,其中帶{}的表示參數匹配,如果不帶則表示字符串匹配。
????? 例如,上面的{controller}/{action}/{id}表示如果HostName后面有三段由“/”分割的字符串,則這個url被匹配,并且分別被解析成控制器名,Action名和一個叫“id”的參數。如果你輸入的是
http://localhost/Home/Index/1
則后面的“1”將被當做參數id的值,但是如果你請求
http://localhost/Home/Index/1/2
,抱歉,你的請求無法成功,因為這條路由規則沒法匹配你的url,因為你的HostName后面有四段,而這個路由規則只能匹配三段的。
????? 也許你還注意到一個問題,
http://localhost/Home/Index
明明HostName后面只有兩段,怎么也被匹配了呢?這就是MapRoute方法的第三個參數起作用了。這個參數的作用是為上面規則中各個{}匹配段設置默認值,如上,id的默認值為"",即空。所以在
http://localhost/Home/Index
中,雖然沒有顯示指定id,但是它依然可以匹配成功,默認作為空值。如果你把其中id=""去掉,你會發現
http://localhost/Home/Index
已經無法匹配了。依次類推,
http://localhost/Home/
也可以匹配成功,因為{action}默認是Index,
http://blog.my400800.cn/
也可以匹配成功,因為默認{controller}為Home,所以,在這條默認值下
http://blog.my400800.cn/網通4006電話/1
和
http://blog.my400800.cn/
是等效的。
????? 綜上分析,我們得出一條重要結論:在默認值被設置的情況下,映射規則“配少不配多”,少的部分由默認值代替。
????? 上面的匹配規則中,三個匹配段都帶大括號的,都是參數匹配,下面我們來說說強字符串匹配。例如,我們有一個url需要這樣
http://localhost/Category/Detail/Name
。如果按照上面的匹配規則,Name段的值會被匹配到id中去,可是我們想在CategoryController的Detail方法中使用名叫“name”的參數而不是使用名叫“id”的參數,怎么辦呢?很簡單,我們增加一下一條匹配規則:
- using ?System; ??
- using ?System.Collections.Generic; ??
- using ?System.Linq; ??
- using ?System.Web; ??
- using ?System.Web.Mvc; ??
- using ?System.Web.Routing; ??
- ??
- namespace ?MVCDemo ??
- { ??
- ???? //?Note:?For?instructions?on?enabling?IIS6?or?IIS7?classic?mode,? ??
- ???? //?visit?http://go.microsoft.com/?LinkId=9394801 ??
- ??
- ???? public ? class ?MvcApplication?:?System.Web.HttpApplication ??
- ????{ ??
- ???????? public ? static ? void ?RegisterRoutes(RouteCollection?routes) ??
- ????????{ ??
- ????????????routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" ); ??
- ??
- ????????????routes.MapRoute( ??
- ???????????????? "Category" ,?????????????????????????????????????????????? //?Route?name ??
- ???????????????? "Category/Detail/{name}" ,??????????????????????????? //?URL?with?parameters ??
- ???????????????? new ?{?controller?=? "Category" ,?action?=? "Detail" ,?name?=? "" ?}?? //?Parameter?defaults ??
- ????????????); ??
- ??
- ??
- ????????????routes.MapRoute( ??
- ???????????????? "Default" ,?????????????????????????????????????????????? //?Route?name ??
- ???????????????? "{controller}/{action}/{id}" ,??????????????????????????? //?URL?with?parameters ??
- ???????????????? new ?{?controller?=? "Home" ,?action?=? "Index" ,?id?=? "" ?}?? //?Parameter?defaults ??
- ????????????); ??
- ??
- ????????} ??
- ??
- ???????? protected ? void ?Application_Start() ??
- ????????{ ??
- ????????????RegisterRoutes(RouteTable.Routes); ??
- ????????} ??
- ????} ??
- }??
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MVCDemo { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Category", // Route name "Category/Detail/{name}", // URL with parameters new { controller = "Category", action = "Detail", name = "" } // Parameter defaults ); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } } }?
????? 可以看到,我們在默認規則前增加了一條規則,其中其中控制器名和Action名不再是參數,而變成了強字符串(沒有{})。這時,當我們請求的url是
http://localhost/Cateogry/Detail/para
的形式時,就會直接匹配新加的規則,而para的值不會被賦給成id而是賦給名叫name的變量。
????? 需要注意的是,我們新的路由規則一定要放在前面,因為ASP.NET MVC會自上向下匹配第一條找到的可匹配路由規則。
視圖
????? 說完了路由規則,我們再來說說視圖。
????? 上面說道,Action方法返回類型是ActionResult,其實這個返回類型不局限于View方法返回ViewResult,它還有很多實現,這里列舉幾個。
????? ViewResult:一般呈現某個aspx文件,由View方法返回。
????? RedirectToResult:使瀏覽器重定向,由Redirect方法返回。
????? RedirectToRouteResult:直接交給下一個Action,由RedirectToAction方法返回。
????? 還有幾個,先不說了,因為后續文章基本用不到其他的,關于那幾個以后朋友們可以自己看相關資料。
小結
????? 看完這篇文章,就基本把90%的障礙掃清了。下面的文章中,將繼續我們的實例。在下一篇中,我們來完成發布公告的功能,看看ASP.NET MVC下如何處理表單信息的傳遞。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
