asp.net mvc 之旅—— 第三站 路由模板中強大的自定義IRouteConstraint約束


      我們在寫mvc的時候,經常會配置各種url模板,比如controller,action,id 組合模式,其實呢,我們還可以對這三個參數進行單獨的配置,采用的方式自然

就是MapRoute中的constraints屬性。

 

一:簡單的正則匹配

    正則匹配算是最最簡單的一個方法,比如針對上面路由中id的值,我可以用正則進行限定,也就是說id只能是整數,這個可以做到嗎???對這么擴展性極強的mvc,

當然可以做到,比如我下面寫的這樣:

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index" },
                constraints: new { id = @"\d+" }
            );

 

然后,我輸入一個正確的url,效果是這樣的。

 

當我把id改成abc的話,效果居然是這樣滴。。。。

 

牛逼吧,頁面已經無法打開,是不是很開心,接着就有吊毛找你,這個id限制能不能再強大點,根據數據庫的配置,或者第三方邏輯來顯示到底要不要顯示,

這時候是不是有點悲劇,目前的id貌似只有正則匹配,貌似並不能強大到自定義邏輯控制id值,不過不要灰心,剛才我也說了,mvc是一個擴展性極強的框架,

這點事情自己有辦法處理。

 

二:IRouteConstraint 強大的自定義邏輯驗證

     

      可以看到IRouteConstraint 是一個接口,接口定義如下:

 1     //
 2     // 摘要:
 3     //     定義類必須實現才能檢查某 URL 參數值是否對約束有效的協定。
 4     [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
 5     public interface IRouteConstraint
 6     {
 7         //
 8         // 摘要:
 9         //     確定 URL 參數是否包含此約束的有效值。
10         //
11         // 參數:
12         //   httpContext:
13         //     一個對象,封裝有關 HTTP 請求的信息。
14         //
15         //   route:
16         //     此約束所屬的對象。
17         //
18         //   parameterName:
19         //     正在檢查的參數的名稱。
20         //
21         //   values:
22         //     一個包含 URL 的參數的對象。
23         //
24         //   routeDirection:
25         //     一個對象,指示在處理傳入請求或生成 URL 時,是否正在執行約束檢查。
26         //
27         // 返回結果:
28         //     如果 URL 參數包含有效值,則為 true;否則為 false。
29         bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection);
30     }

 

在這個接口中提供了一個Match方法,而我要做的就是實現一個繼承它的類就可以了,當返回true代表通過,返回false代表匹配失敗。。。。就像我現在

這樣的爛代碼:

 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     }

 

要看清楚哦。。。在我實現的MyRouteConstraint類中的Match方法,我通過values[parameterName]可以成功獲取id的值,不行我可以調試給親看。。。

拿到這個值之后,你就可以肆意的去玩耍了。。。

 

三:源碼分析

到現在為止,你是不是很好奇這吊毛玩意是怎么實現的。。。。其實很簡單的哦,還記得各種mvc入門書籍中說,路由路由的概念。。。其實呢,也就是一個

Route類而已嘛。。。就像下面這樣。

 

而Route類中,最最重要的莫過於GetRouteData方法,它就是用來決定是否可以看心情把你這個http請求送到Controller中去。。。然后我們再來看看

這個方法的源代碼。。。

 

最終,功夫不負有心人,兩串最核心的代碼展現在你的面前。

1. constraint as IRouteConstraint   如果當前是IRouteConstraint類型,走我實現的Match方法。

2. constraint as string                  走我的正則匹配,如:Regex.IsMatch。。。。

 

好了,本篇就講到這里,希望對你有幫助。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM