約束路由
上面我們有一個{id}用來捕獲參數的,但是你也發現了它可以捕捉任何字符串等等,但是我們有時需要限制它,比如讓它只能輸入數字,那么我們就可以使用正則表達式去約束它。
如下修改RouteConfig.cs:
1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteCollection routes) 4 { 5 routes.MapRoute( 6 name: "Default", 7 url: "{controller}/{action}/{id}", 8 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 9 constraints: new{id = @"^\d*$"}, 10 namespaces: new[] { "MvcStudy.Controllers" } 11 ); 12 } 13 }
我們可以清楚的看到我們通過constraints參數將id參數約束為只能輸入數字,當然你也可以通過一樣的方式去約束其他的參數。通過httpMethod = new HttpMethodConstraint("GET","POST")可以約束該路由只能通過那種方式訪問。
如果你的約束是上面無法做到的,那么下面的自定義約束一定會符合你的要求。新建一個自定義的約束只需要創建一個實現IRouteConstraint接口的類即可,比如我們限制只能是谷歌瀏覽器才能訪問,新建一個Filters文件,並新建一個MyRouteConstraint類,寫入如下的代碼:
1 public class MyRouteConstraint : IRouteConstraint 2 { 3 4 public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 5 { 6 return httpContext.Request.UserAgent.Contains("Chrome"); 7 } 8 }
接着我們換到不同的瀏覽器去測試,就會發現區別了(如果你通過瀏覽器的開發者工具或者其他工具修改UserAgent的話也可以越過這個約束,如Filddler2工具)
解決與物理路徑的沖突
當發送一個請求至ASP.NET MVC時,其實會檢查網站中存不存在這個請求的物理路徑文件,如果存在的話,就會直接將這個物理文件返回。但是有時候我們需要它執行控制器的某個方法,而不是直接將這個物理文件返回。那么我們就需要這節知識。下面我們先在網站根目錄中新建一個 Test.html ,在其中隨便寫上一些內容,然后訪問。再在RouteConfig.cs中寫入如下代碼:
1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteCollection routes) 4 { 5 routes.RouteExistingFiles = true; 6 7 routes.MapRoute( 8 name: "Default2", 9 url: "Test.html", 10 defaults: new { controller = "Home", action = "List" } 11 ); 12 } 13 }
這個時候我們再重新刷新瀏覽器,那么我們就可以看到控制器返回的結果了,這樣我們就解決了物理路徑和路由之間的沖突問題了。
8.繞過路由系統
如果我們有一些URL路徑不希望通過路由系統,那么我們就可以利用這節知識。
下面是RouteConfig.cs的內容:
1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteCollection routes) 4 { 5 routes.IgnoreRoute("webResources.axd{*pathinfo}"); 6 7 routes.MapRoute( 8 name: "Default2", 9 url: "Test.html", 10 defaults: new { controller = "Home", action = "List" } 11 ); 12 } 13 }
9.自定義路由系統
如果上面的技術還無法解決你的問題,那么我們下面將會介紹如何自定義路由系統。自定義路由系統只需要繼承RouteBase並實現兩個方法,如下:
(1):GetRouteData
(2):GetVirtualPath
下面是我寫的一個簡單示例,用來判斷訪問者是否是移動設備,如果是移動設備則路由到前綴為M的控制器處理請求,否則返回NULL交由默認的路由
處理,下面為我的源碼:
1 public class CustomRouteBase : RouteBase 2 { 3 private List<String> userAgent; 4 5 public CustomRouteBase(params String[] userAgents) 6 { 7 userAgent = userAgents.ToList(); 8 } 9 10 public override RouteData GetRouteData(HttpContextBase httpContext) 11 { 12 RouteData rd = new RouteData(this, new MvcRouteHandler()); 13 Regex r = new Regex(@"/(\w+)", RegexOptions.IgnoreCase); 14 MatchCollection mc = r.Matches(httpContext.Request.Path); 15 String agent = httpContext.Request.UserAgent.ToLower(); 16 foreach (String item in userAgent) 17 { 18 if (agent.Contains(item)) 19 { 20 if (mc.Count >= 2) 21 { 22 rd.Values.Add("controller", "M" + mc[0].Groups[1].Value.ToString()); 23 rd.Values.Add("action", mc[1].Groups[1].Value.ToString()); 24 } 25 else 26 { 27 rd.Values.Add("controller", "MHome"); 28 rd.Values.Add("action", "Index"); 29 } 30 return rd; 31 } 32 } 33 return null; 34 } 35 36 public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 37 { 38 return null; 39 } 40 }
最后我們將該自定義路由添加進來(RouteConfig.cs):
1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteCollection routes) 4 { 5 routes.Add(new CustomRouteBase("iphone", "ipad", "android")); 6 7 routes.MapRoute( 8 name: "Default2", 9 url: "Test.html", 10 defaults: new { controller = "Home", action = "List" } 11 ); 12 } 13 }
現在你新建一個MHome的控制器,然后訪問看看(建議使用Google瀏覽器,並通過開發者工具改變UserAgent即可快速看到效果)。
10.自定義路由處理程序
或許你會覺得ASP.NET MVC的控制器太麻煩,相比而言有些功能你更希望使用一般處理程序。但是訪問的時候必須使用物理路徑又發覺麻煩,那么通過學習這節,你將可以將一般處理程序也加入到路由中,並且可控性很強。
首先我們必須新建一個實現IRouteHandler接口的類:
1 public class DonwloadHandler : IRouteHandler 2 { 3 4 public IHttpHandler GetHttpHandler(RequestContext requestContext) 5 { 6 return new CustomHandler(); 7 } 8 } 9 10 public class CustomHandler : IHttpHandler 11 { 12 13 public bool IsReusable 14 { 15 get { return false; } 16 } 17 18 public void ProcessRequest(HttpContext context) 19 { 20 context.Response.Write("download model"); 21 } 22 }
你們可以看到上面的源碼,我是直接在下面新建了一個實現IHttpHandler的類,並且在GetHttpHandler中將該類的實例返回,當然你還可以在這個方法中進行判斷以便根據實際情況交由不同的一般處理程序去處理請求。
下面就是將這個路由處理程序添加到路由中,這里我們映射到MyTest這個路徑:
1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteCollection routes) 4 { 5 routes.Add(new Route("MyTest",new DonwloadHandler())); 6 7 routes.MapRoute( 8 name: "Default2", 9 url: "Test.html", 10 defaults: new { controller = "Home", action = "List" } 11 ); 12 } 13 }
接着我們訪問http://localhost:2392/MyTest就可以看到結果了。
裝載:http://www.cnblogs.com/yaozhenfa/