asp.net mvc 之旅—— 第三站 路由模板中強(qiáng)大的自定義IRouteConstraint約束
我們?cè)趯憁vc的時(shí)候,經(jīng)常會(huì)配置各種url模板,比如controller,action,id 組合模式,其實(shí)呢,我們還可以對(duì)這三個(gè)參數(shù)進(jìn)行單獨(dú)的配置,采用的方式自然
就是MapRoute中的constraints屬性。
一:簡(jiǎn)單的正則匹配
正則匹配算是最最簡(jiǎn)單的一個(gè)方法,比如針對(duì)上面路由中id的值,我可以用正則進(jìn)行限定,也就是說id只能是整數(shù),這個(gè)可以做到嗎???對(duì)這么擴(kuò)展性極強(qiáng)的mvc,
當(dāng)然可以做到,比如我下面寫的這樣:
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index" }, constraints: new { id = @"\d+" } );
然后,我輸入一個(gè)正確的url,效果是這樣的。

當(dāng)我把id改成abc的話,效果居然是這樣滴。。。。

牛逼吧,頁(yè)面已經(jīng)無法打開,是不是很開心,接著就有吊毛找你,這個(gè)id限制能不能再?gòu)?qiáng)大點(diǎn),根據(jù)數(shù)據(jù)庫(kù)的配置,或者第三方邏輯來顯示到底要不要顯示,
這時(shí)候是不是有點(diǎn)悲劇,目前的id貌似只有正則匹配,貌似并不能強(qiáng)大到自定義邏輯控制id值,不過不要灰心,剛才我也說了,mvc是一個(gè)擴(kuò)展性極強(qiáng)的框架,
這點(diǎn)事情自己有辦法處理。
二:IRouteConstraint 強(qiáng)大的自定義邏輯驗(yàn)證
可以看到IRouteConstraint 是一個(gè)接口,接口定義如下:
1 // 2 // 摘要: 3 // 定義類必須實(shí)現(xiàn)才能檢查某 URL 參數(shù)值是否對(duì)約束有效的協(xié)定。 4 [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] 5 public interface IRouteConstraint 6 { 7 // 8 // 摘要: 9 // 確定 URL 參數(shù)是否包含此約束的有效值。 10 // 11 // 參數(shù): 12 // httpContext: 13 // 一個(gè)對(duì)象,封裝有關(guān) HTTP 請(qǐng)求的信息。 14 // 15 // route: 16 // 此約束所屬的對(duì)象。 17 // 18 // parameterName: 19 // 正在檢查的參數(shù)的名稱。 20 // 21 // values: 22 // 一個(gè)包含 URL 的參數(shù)的對(duì)象。 23 // 24 // routeDirection: 25 // 一個(gè)對(duì)象,指示在處理傳入請(qǐng)求或生成 URL 時(shí),是否正在執(zhí)行約束檢查。 26 // 27 // 返回結(jié)果: 28 // 如果 URL 參數(shù)包含有效值,則為 true;否則為 false。 29 bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection); 30 }
在這個(gè)接口中提供了一個(gè)Match方法,而我要做的就是實(shí)現(xiàn)一個(gè)繼承它的類就可以了,當(dāng)返回true代表通過,返回false代表匹配失敗。。。。就像我現(xiàn)在
這樣的爛代碼:
1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteCollection routes) 4 { 5 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 6 7 routes.MapRoute( 8 name: "Default", 9 url: "{controller}/{action}/{id}", 10 defaults: new { controller = "Home", action = "Index" }, 11 constraints: new { id = new MyRouteConstraint() } 12 ); 13 } 14 } 15 16 public class MyRouteConstraint : IRouteConstraint 17 { 18 public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 19 { 20 //獲取id的值 21 var id = values[parameterName]; 22 23 //logic。。。 24 25 return true; 26 } 27 }
要看清楚哦。。。在我實(shí)現(xiàn)的MyRouteConstraint類中的Match方法,我通過values[parameterName]可以成功獲取id的值,不行我可以調(diào)試給親看。。。

拿到這個(gè)值之后,你就可以肆意的去玩耍了。。。
三:源碼分析
到現(xiàn)在為止,你是不是很好奇這吊毛玩意是怎么實(shí)現(xiàn)的。。。。其實(shí)很簡(jiǎn)單的哦,還記得各種mvc入門書籍中說,路由路由的概念。。。其實(shí)呢,也就是一個(gè)
Route類而已嘛。。。就像下面這樣。

而Route類中,最最重要的莫過于GetRouteData方法,它就是用來決定是否可以看心情把你這個(gè)http請(qǐng)求送到Controller中去。。。然后我們?cè)賮砜纯?/p>
這個(gè)方法的源代碼。。。


最終,功夫不負(fù)有心人,兩串最核心的代碼展現(xiàn)在你的面前。
1. constraint as IRouteConstraint 如果當(dāng)前是IRouteConstraint類型,走我實(shí)現(xiàn)的Match方法。
2. constraint as string 走我的正則匹配,如:Regex.IsMatch。。。。
好了,本篇就講到這里,希望對(duì)你有幫助。

浙公網(wǎng)安備 33010602011771號(hào)