摘要
????? 本文對ASP.NET MVC的全局運(yùn)行機(jī)理進(jìn)行一個(gè)簡要的介紹,以使得朋友們更好的理解后續(xù)文章。
前言
????? 在上一篇文章中,我們實(shí)現(xiàn)了第一個(gè)ASP.NET MVC頁面。對于沒有接觸過這個(gè)框架的朋友來說,可能對有些地方會(huì)迷惑,所以這篇文章我將通過圖示配合文字的方法,站在全局的角度介紹一些ASP.NET MVC的運(yùn)行機(jī)制,這樣可以幫助朋友們更好的理解后續(xù)文章。^_^
全局
????? 首先我們來看一副圖片,由于這幅圖是我自己畫的,不是摘自微軟官方,所以如果有什么不到位的地方還望海涵!
????? 首先,用戶通過Web瀏覽器向服務(wù)器發(fā)送一條url請求,這里請求的url不再是xxx.aspx格式,而是
http://HostName/ControllerName/ActionName/Parameters
的樣子。這個(gè)請求被ASP.NET MVC的路由映射系統(tǒng)截獲。(路由映射可以在Global.asax中配置,我們一會(huì)再說)路由映射系統(tǒng)按照映射規(guī)則,解析出控制器名 ControllerName,Action名ActionName和各個(gè)參數(shù)Parameters,然后,找尋Controllers目錄下的 ControllerNameController.cs這個(gè)控制器類,默認(rèn)情況下,系統(tǒng)總是找尋Controllers目錄下的“控制器名+Controller”這么一個(gè)類,然后,找尋這個(gè)類下與ActionName同名的方法,找到后,將Parameters作為參數(shù)傳給這個(gè)方法,而后Action方法開始執(zhí)行,完成后返回相應(yīng)視圖,默認(rèn)情況下,會(huì)返回Views目錄下與ControllerName同名的目錄下的與 ActionName同名的aspx文件,并且將ViewData傳遞到視圖。ViewData中一般包含了控制視圖顯示的控制量以及視圖顯示需要的數(shù)據(jù)。
????? 我們按以上思路回顧一下上一篇中主頁的請求過程。我們傳遞的url是
http://localhost/Home/Index
。默認(rèn)路由規(guī)則下,將ControllerName設(shè)為“Home”,ActionName設(shè)為“Index”,沒有參數(shù)。于是系統(tǒng)找尋 Controllers目錄下的HomeController類的Index方法,成功找到,于是執(zhí)行之。這個(gè)方法調(diào)用Mock的Model取出一些數(shù)據(jù),放入ViewData相應(yīng)鍵值項(xiàng)里。然后返回視圖,返回的是Views下Home下的Index.aspx。這個(gè)視圖取出ViewData中的數(shù)據(jù)按照一定格式呈現(xiàn),于是完成了一次典型的ASP.NET MVC調(diào)用。
路由
????? 從上面可以看出,ASP.NET MVC中路由是很重要的。它直接決定了如何解析url,因此決定了系統(tǒng)如何工作。那么,下面我們來揭開路由神秘的面紗。
????? 打開我們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); } } }?
????? 我們揀重點(diǎn)說。注意上面有個(gè)routes.MapRoute方法。這個(gè)方法的作用是向系統(tǒng)增加一條路由規(guī)則。這里唯一的一條規(guī)則是系統(tǒng)默認(rèn)增加的,第一個(gè)參數(shù)是規(guī)則名,是一個(gè)普通字符串。關(guān)鍵是第二個(gè)參數(shù),它也是一個(gè)字符串,但是它描述了如何解析url。可以這樣理解,它描述了url串HostName后面部分如何匹配,其中帶{}的表示參數(shù)匹配,如果不帶則表示字符串匹配。
????? 例如,上面的{controller}/{action}/{id}表示如果HostName后面有三段由“/”分割的字符串,則這個(gè)url被匹配,并且分別被解析成控制器名,Action名和一個(gè)叫“id”的參數(shù)。如果你輸入的是
http://localhost/Home/Index/1
則后面的“1”將被當(dāng)做參數(shù)id的值,但是如果你請求
http://localhost/Home/Index/1/2
,抱歉,你的請求無法成功,因?yàn)檫@條路由規(guī)則沒法匹配你的url,因?yàn)槟愕腍ostName后面有四段,而這個(gè)路由規(guī)則只能匹配三段的。
????? 也許你還注意到一個(gè)問題,
http://localhost/Home/Index
明明HostName后面只有兩段,怎么也被匹配了呢?這就是MapRoute方法的第三個(gè)參數(shù)起作用了。這個(gè)參數(shù)的作用是為上面規(guī)則中各個(gè){}匹配段設(shè)置默認(rèn)值,如上,id的默認(rèn)值為"",即空。所以在
http://localhost/Home/Index
中,雖然沒有顯示指定id,但是它依然可以匹配成功,默認(rèn)作為空值。如果你把其中id=""去掉,你會(huì)發(fā)現(xiàn)
http://localhost/Home/Index
已經(jīng)無法匹配了。依次類推,
http://localhost/Home/
也可以匹配成功,因?yàn)閧action}默認(rèn)是Index,
http://blog.my400800.cn/
也可以匹配成功,因?yàn)槟J(rèn){controller}為Home,所以,在這條默認(rèn)值下
http://blog.my400800.cn/網(wǎng)通4006電話/1
和
http://blog.my400800.cn/
是等效的。
????? 綜上分析,我們得出一條重要結(jié)論:在默認(rèn)值被設(shè)置的情況下,映射規(guī)則“配少不配多”,少的部分由默認(rèn)值代替。
????? 上面的匹配規(guī)則中,三個(gè)匹配段都帶大括號的,都是參數(shù)匹配,下面我們來說說強(qiáng)字符串匹配。例如,我們有一個(gè)url需要這樣
http://localhost/Category/Detail/Name
。如果按照上面的匹配規(guī)則,Name段的值會(huì)被匹配到id中去,可是我們想在CategoryController的Detail方法中使用名叫“name”的參數(shù)而不是使用名叫“id”的參數(shù),怎么辦呢?很簡單,我們增加一下一條匹配規(guī)則:
- 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); } } }?
????? 可以看到,我們在默認(rèn)規(guī)則前增加了一條規(guī)則,其中其中控制器名和Action名不再是參數(shù),而變成了強(qiáng)字符串(沒有{})。這時(shí),當(dāng)我們請求的url是
http://localhost/Cateogry/Detail/para
的形式時(shí),就會(huì)直接匹配新加的規(guī)則,而para的值不會(huì)被賦給成id而是賦給名叫name的變量。
????? 需要注意的是,我們新的路由規(guī)則一定要放在前面,因?yàn)锳SP.NET MVC會(huì)自上向下匹配第一條找到的可匹配路由規(guī)則。
視圖
????? 說完了路由規(guī)則,我們再來說說視圖。
????? 上面說道,Action方法返回類型是ActionResult,其實(shí)這個(gè)返回類型不局限于View方法返回ViewResult,它還有很多實(shí)現(xiàn),這里列舉幾個(gè)。
????? ViewResult:一般呈現(xiàn)某個(gè)aspx文件,由View方法返回。
????? RedirectToResult:使瀏覽器重定向,由Redirect方法返回。
????? RedirectToRouteResult:直接交給下一個(gè)Action,由RedirectToAction方法返回。
????? 還有幾個(gè),先不說了,因?yàn)楹罄m(xù)文章基本用不到其他的,關(guān)于那幾個(gè)以后朋友們可以自己看相關(guān)資料。
小結(jié)
????? 看完這篇文章,就基本把90%的障礙掃清了。下面的文章中,將繼續(xù)我們的實(shí)例。在下一篇中,我們來完成發(fā)布公告的功能,看看ASP.NET MVC下如何處理表單信息的傳遞。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

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