請註明轉載地址:http://www.cnblogs.com/arhat瀏覽器
因爲今天是星期六,因此多寫幾篇,感受前幾天的忙碌沒有及時發佈文章,趁着週末老魏盡力的多寫幾篇文章。由於本系列基本上快結束了,因此老魏也要加把勁了,這個系列完成後,老魏會開始NHibernate,Spring.NET,EF等相關文章的書寫。但願你們可以支持一下!服務器
本章老魏主要給你們講述一下在ASP.NET MVc3中的路由技術,固然本章屬於那種不會也會開發ASP.NET MVC的章節,可是老魏仍是建議你們要學習一下這個路由技術,這樣你們會理解ASP.NET
MVC的生命週期,同時可以避免你們走不少彎路。app
當咱們建立一個ASP.NET MVC3項目的時候,咱們會發如今項目中有一個Global.asax文件,這個文件它包含了ASP.NET應用程序生命週期事件處理,當應用程序啓動的時候會先運行這個文件中的Application_Start方法。
咱們來看看Global.asax文件的代碼:學習
public class MvcApplication : System.Web.HttpApplication { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); } public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // 路由名稱 "{controller}/{action}/{id}", // 帶有參數的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數默認值 ); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); } }
當一個ASP.NET MVC應用程序第一次運行時, Application_Start()方法被調用。這個方法,又調用RegisterRoutes()方法,RegisterRoutes()方法建立了路由表。測試
記得當時老魏在學習路由的時候很是的迷惑,不理解什麼是路由,但慢慢的理解什麼路由。所謂的路由就是至關於一個路由器,用來分配和匹配用的。好比咱們的計算機(A)由路由器分配一個地址「192.168.1.23」,那麼若是這個計算機須要訪問「192.168.1.128」的計算機(B),那麼A計算機須要把他請求的地址發送給路由器,而路由器接收到這地址以後,從路由表中開始查找計算機B的地址,若是B的地址在路由器中的路由表中註冊過,則路由器把A的請求發送給B,若是路由器沒有找到B在路由表中註冊的地址,那麼發送不成功!this
那麼,在ASP.NET MVC中的路由也是這個意思,只不過不是訪問的計算機,而是訪問的是控制下Action。那麼咱們能夠仿照上面的描述來描述一下ASP.NET MVC的路由過程。好比如今有一個控制器A(/Home/Index)須要訪問控制器B(/About/Index)那麼,在頁面中,咱們點擊超連接:url
<a href=」/About/Index」>About</a>,那麼這個超連接將會向服務器發送一個請求,這個請求被Global.asax接收,由於Global.asax中已經註冊過了路由,那麼則接收到這個請求的時候,路由表中就會查找這個地址」/About/Index」,若是找到了,在開始訪問,沒有找到則會404。spa
因此,從上面的描述中,咱們知道,在Global.asax的RegisterRoutes方法是用來註冊訪問路由的。在路由表中註冊的路由就是訪問的地址規則,若是訪問的地址知足了地址規則纔會訪問,不然錯誤!code
咱們能夠經過一張圖來看一下這個過秤。blog
從這個圖中,咱們看到MVC下的請求過程,其實你們也看到了,在這個請求過程當中,Global.asax的路由系統起到一個很是重要的做用,那麼下面咱們來看看它是如何來匹配瀏覽器發送過來的請求,執行這個請求。
在Global.asax的RegisterRoutes方法中註冊了路由規則,這個規則用來匹配瀏覽器發送過來的請求,默認狀況下,這個方法裏面已經註冊了一個默認的路由。
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // 路由名稱 "{controller}/{action}/{id}", // 帶有參數的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數默認值 ); }
這個方法中傳入一個參數RouteCollection集合,這個集合中就是路由表用來保存路由規則的。經過方法MapRoute方法來增長一條路由規則。這個方法重載了6次,那麼根據不一樣的需求調用不一樣的方法。那麼本章咱們將講解經常使用的方法,後面的方法咱們在後續的章節中講解。
public static Route MapRoute(this RouteCollection routes, string name, string url); public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults); public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces); public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints); public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces); public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);
其中,默認路由用的是第二個方法。咱們來分析一個這個方法。
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
參數:
name:路由的名字
url:路由規則
Defaults:路由的默認值
那麼,咱們看看默認的路由。
routes.MapRoute( "Default", // 路由名稱 "{controller}/{action}/{id}", // 帶有參數的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數默認值 );
首先,路由的名稱是Default,路由的規則是"{controller}/{action}/{id}",路由的默認值 new { controller = "Home", action = "Index", id = UrlParameter.Optional }。
咱們來分析一下路由的規則,默認的路由規則是"{controller}/{action}/{id}",那麼也就是說,瀏覽器發送過來的請求必須是contrroller開頭/action中間/id參數,這樣的形式。那麼咱們寫幾個來匹配一下。
訪問地址:/Home/Index/1 —— /controlller/action/id——匹配
訪問地址:/Home/Index——/Controlller/action/id——匹配
訪問地址:/Home/Index/apple——/Controlller/action/id——匹配
訪問地址:/Home/Index/1/2 —— /controlller/action/id——不匹配
咱們用上面的例子來匹配默認的路由,那麼經過上面的例子,咱們會發現一個問題,爲何第二個和第三個可以匹配成功呢?路由規則中配置了有一個id的參數,怎麼沒有傳遞就成功呢?緣由是,在默認之中,設置了Id的默認值,因此若是沒有傳遞參數也是能夠的。但是爲何傳遞的apple也能成功呢?由於在http協議中傳遞的參數類型都是string類型的。
那麼,若是如今項目中,沒有AboutController控制器,那麼咱們在瀏覽器中輸入下面的地址:
訪問地址:/About/Index —— /controlller/action/id——匹配
首先,訪問的地址匹配了路由規則,因爲在項目中沒有這個控制器,則路由表就找不到對應的控制器去執行,因此回報錯。
如今咱們來分析一下第三個參數,也就是路由規則的默認值。
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
這個默認值的做用是,若是在瀏覽器中輸入http://localhost,那麼將會調用默認的路由規則,同時把默認值做爲請求的內容。也就說說,咱們訪問http://localhost就是訪問http://localhost/Home/Index。這個就是默認值的做用。
其實在訪問的過程當中,最重要的就是默認的規則,只要你訪問的地址可以匹配路由規則,則按照路由規則和請求的內容來訪問,不然則按照默認值來訪問。好比咱們訪問/About/Index這個地址時候,知足了匹配的規則,那麼請求的內容就是AboutController和Index方法,則默認值將不會起做用了。
經過上面的分析,咱們明白了路由的做用,那麼咱們能不能本身添加一個路由規則呢?答案是確定的,咱們能夠自定義路由,可是須要注意的是自定義路由必須位於默認路由的前面,由於ASP.NET MVC默認狀況下尋找路由的時候是從上到下進行匹配的。
好,咱們添加一個路由。
routes.MapRoute( "MyRoute", // 路由名稱 "{action}", // 帶有參數的 URL new { controller = "About", action = "Index"} // 參數默認值 );
咱們添加的這個路由很是的簡單,理由名稱是MyRoute,路由規則就一個{action},而後下面是默認值,咱們的默認值是控制器About,Action爲Index沒有參數。
那麼咱們試着猜測一下,若是咱們在瀏覽器中輸入http://localhost/Index的時候,是否是訪問的是AboutController/Index方法呢?答案是確定的,由於咱們符合了這個規則。
這裏咱們須要注意的是,默認值中,咱們必須設置controller和action的默認值。那麼咱們在定義一個路由。
routes.MapRoute( "Display", // 路由名稱 "Dispaly/{controller}/{action}", // 帶有參數的 URL new { controller = "About", action = "Index" } // 參數默認值 );
這個路由的匹配規則是Display/{controller}/{action}那麼咱們在瀏覽器中輸入下面的地址http://localhost:4878/Display/about/index就是匹配規則的。那麼咱們在輸入一個地址http://localhost:4878/Display/home/index這個地址也是匹配的,不過是這個地址沒有用默認值而已。
講到這裏,不知道你們有沒有明白路由和自定義路由呢?但願你們可以看得明白,並可以靈活應用起來。
同時,你們能夠經過在View中生成ActionLink來作一下測試。可是這裏得提醒你們一下,若是沒有特別的說明,請不要自定義路由!