前言
在上一篇文章中,我們實現了第一個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,
// 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(
"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://localhost/也可以匹配成功,因為預設{controller}為Home,所以,在這條預設值下http://localhost/Home/Index和http://localhost/是等效的。
綜上分析,我們得出一條重要結論:在預設值被設定的情況下,映射規則“配少不配多”,少的部分由預設值代替。
上面的匹配規則中,三個匹配段都帶大括弧的,都是參數匹配,下面我們來說說強字串匹配。例如,我們有一個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);
}
}
}
可以看到,我們在預設規則前增加了一條規則,其中其中控制器名和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下如何處理表單資訊的傳遞。
本文出自張洋部落格T2's Notebook
【編輯精選】
- ASP.NET MVC案例教程(一)
- ASP.NET MVC案例教程(二)
- ASP.NET MVC案例教程(四)
- ASP.NET MVC案例教程(五)
- ASP.NET MVC案例教程(六)
- ASP.NET MVC案例教程(七)