請求一個ASP.NET mvc的網站和之前的web form是有區別的,ASP.NET MVC框架內部給咱們提供了路由機制,當IIS接受到一個請求時,會先看是否請求了一個靜態資源(.html,css,js,圖片等),這一步是web form和mvc都是同樣的,若是不是則說明是請求的是一個動態頁面,就會走asp.net的管道,mvc的程序請求都會走路由系統,會映射到一個Controller對應的Action方法,而web form請求動態頁面是會查找本地實際存在一個aspx文件。下面經過一個ASP.NET MVC5項目來詳細介紹一下APS.NET MVC5路由系統的機制。javascript
1 public class MvcApplication : System.Web.HttpApplication 2 { 3 protected void Application_Start() 4 { 5 //註冊 ASP.NET MVC 應用程序中的全部區域 6 AreaRegistration.RegisterAllAreas(); 7 //註冊 全局的Filters 8 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 9 //註冊 路由規則 10 RouteConfig.RegisterRoutes(RouteTable.Routes); 11 //註冊 打包綁定(js,css等) 12 BundleConfig.RegisterBundles(BundleTable.Bundles); 13 } 14 }
這個Application_Start方法會在網站啓動的自動調用,其中咱們看到:RouteConfig.RegisterRoutes(RouteTable.Routes);這個就是向ASP.NET MVC 框架註冊咱們自定義的路由規則,讓以後的URL可以對應到具體的Action。接下來咱們再來看看RegisterRoutes方法作了些什麼?css
1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteCollection routes) 4 { 5 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 6 routes.MapRoute( 7 name: "Default", 8 url: "{controller}/{action}/{id}", 9 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 10 ); 11 } 12 }
1 routes.MapRoute( 2 name: "Default", 3 url: "{controller}/{action}/{id}", 4 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 5 );
URL
|
URL段 |
http://mysite.com/Admin/Index
|
controller = Admin
action = Index
|
http://mysite.com/Index/Admin
|
controller = Index
action = Admin
|
http://mysite.com/Apples/Oranges
|
controller = Apples
action = Oranges
|
http://mysite.com/Admin
|
無匹配-段的數量不夠
|
http://mysite.com/Admin/Index/Soccer
|
無匹配-段的數量超了 |
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("MyRoute", "{controller}/{action}"); 4 }
用到了RouteCollection的MapRoute方法。其實咱們還能夠調用 Add方法,傳一個Route的實例給它同樣的達到相同的效果。html
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler()); 4 routes.Add("MyRoute", myRoute); 5 }
1 public static void RegisterRoutes(RouteCollection routes) { 2 routes.MapRoute("MyRoute", "{controller}/{action}", new { action = "Index" }); 3 }
要設置Controller和Action的默認值。java
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("MyRoute", "{controller}/{action}", 4 new { controller = "Home", action = "Index" }); 5 }
Url段的數量
|
實例
|
Route映射
|
0
|
mydomain.com
|
controller = Home
action = Index
|
1
|
mydomain.com/Customer
|
controller = Customer
action = Index
|
2
|
mydomain.com/Customer/List
|
controller = Customer
action = List
|
3
|
mydomain.com/Customer/List/All
|
無匹配—Url段過多
|
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("MyRoute", "{controller}/{action}", 4 new { controller = "Home", action = "Index" }); 5 6 routes.MapRoute("", "Public/{controller}/{action}", 7 new { controller = "Home", action = "Index" }); 8 }
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("", "X{controller}/{action}"); 4 5 routes.MapRoute("MyRoute", "{controller}/{action}", 6 new { controller = "Home", action = "Index" }); 7 8 routes.MapRoute("", "Public/{controller}/{action}", 9 new { controller = "Home", action = "Index" }); 10 11 }
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("MyRoute", "{controller}/{action}/{id}", 4 new { controller = "Home", action = "Index", id = "1" }); 5 }
1 public ViewResult CustomVariable() { 2 3 ViewBag.CustomVariable = RouteData.Values["id"]; 4 return View(); 5 }
1 public ViewResult CustomVariable(int id) { 2 3 ViewBag.CustomVariable = id; 4 return View(); 5 }
MVC框架使用內置的Model綁定系統將從URL獲取到變量的值轉換成Action參數相應類型的值。這種轉換除了能夠轉換成基本int,string等等以外還能夠處理複雜類型,自定義的Model,List集合等。web
Url段的數量
|
實例
|
Route映射
|
0
|
mydomain.com
|
controller = Home
action = Index
|
1
|
mydomain.com/Customer
|
controller = Customer
action = Index
|
2
|
mydomain.com/Customer/List
|
controller = Customer
action = List
|
3
|
mydomain.com/Customer/List/All
|
controller = Customer
action = List
id = All
|
4
|
mydomain.com/Customer/List/All/Delete
|
controller = Customer
action = List
id = All
catchall = Delete
|
5
|
mydomain.com/Customer/List/All/Delete/Perm
|
controller = Customer
action = List
id = All
catchall = Delete /Perm
|
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("Default", 4 "{controller}/{action}/{id}", 5 new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 6 new string[] { "WebApplication1.Controllers" } 7 ); 8 }
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", 4 new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 5 new { controller = "^H.*"}, 6 new[] { "URLsAndRoutes.Controllers"}); 7 }
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", 4 new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 5 new { controller = "^H.*", action = "^Index$|^About$"}, 6 new[] { "URLsAndRoutes.Controllers"}); 7 }
上例在controller和action上都定義了約束,約束是同時起做用是,也就是要同時知足。上面表示只匹配contorller名字以H開頭的URL,且action變量的值爲Index或者爲About的URL。正則表達式
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", 4 new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 5 new { controller = "^H.*", action = "Index|About", 6 httpMethod = new HttpMethodConstraint("GET") }, 7 new[] { "URLsAndRoutes.Controllers" }); 8 }
上面表示只匹配爲GET方式的請求。c#
1 using System.Web; 2 using System.Web.Routing; 3 4 namespace URLsAndRoutes.Infrastructure { 5 6 public class UserAgentConstraint : IRouteConstraint { 7 private string requiredUserAgent; 8 9 public UserAgentConstraint(string agentParam) { 10 requiredUserAgent = agentParam; 11 } 12 13 public bool Match(HttpContextBase httpContext, Route route, string parameterName, 14 RouteValueDictionary values, RouteDirection routeDirection) { 15 16 return httpContext.Request.UserAgent != null && 17 httpContext.Request.UserAgent.Contains(requiredUserAgent); 18 } 19 } 20 }
asp.net mvc自定義路由約束的使用:瀏覽器
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", 4 new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 5 new { 6 controller = "^H.*", action = "Index|About", 7 httpMethod = new HttpMethodConstraint("GET", "POST"), 8 customConstraint = new UserAgentConstraint("IE") 9 }, 10 new[] { "URLsAndRoutes.Controllers" }); 11 }
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.RouteExistingFiles = true; 4 5 routes.MapRoute("DiskFile", "Content/StaticContent.html", 6 new { 7 controller = "Account", action = "LogOn", 8 }, 9 new { 10 customConstraint = new UserAgentConstraint("IE") 11 }); 12 13 routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", 14 new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 15 new { 16 controller = "^H.*", action = "Index|About", 17 httpMethod = new HttpMethodConstraint("GET", "POST"), 18 customConstraint = new UserAgentConstraint("IE") 19 }, 20 new[] { "URLsAndRoutes.Controllers" }); 21 }
咱們把RouteExistingFiles屬性設置爲true,表示存在的文件也走路由,上面咱們把Content/StaticContent.html這個文件映射到controller 爲Account,action 爲LogOn中了,而並非指磁盤中存在的文件。基於asp.net mvc的這個特性咱們就能夠實現mvc以.html結尾的僞靜態服務器
1 public static void RegisterRoutes(RouteCollection routes) { 2 3 routes.RouteExistingFiles = true; 4 5 routes.MapRoute("DiskFile", "Content1/StaticContent.html", 6 new { 7 controller = "Account", action = "LogOn", 8 }, 9 new { 10 customConstraint = new UserAgentConstraint("IE") 11 }); 12 13 routes.IgnoreRoute("Content/*{filename}"); 14 routes.MapRoute("", "{controller}/{action}"); 15 16 }