真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

.NET/ASP.NETRouting路由(深入解析路由系統(tǒng)架構(gòu)原理)

閱讀目錄:

讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:申請域名、雅安服務器托管、營銷軟件、網(wǎng)站建設、唐河網(wǎng)站維護、網(wǎng)站推廣。

  • 1.開篇介紹

  • 2.ASP.NET Routing 路由對象模型的位置

  • 3.ASP.NET Routing 路由對象模型的入口

  • 4.ASP.NET Routing 路由對象模型的內(nèi)部結(jié)構(gòu)

    • 4.1】UrlRoutingModule 對象內(nèi)部結(jié)構(gòu)

    • 4.2】RouteBase、Route、RouteCollection、RouteTable 路由核心對象模型

    • 4.3】RouteValueDictionary、RouteData、RequestContext 路由數(shù)據(jù)對象模型

    • 4.4】IRouteHandler 、IHttpHandler兩個接口之間的關系

  • 5.】UrlRoutingHandler 對象內(nèi)部結(jié)構(gòu)及擴展應用

1】開篇介紹

這篇文章讓我們愉快的學習一下ASP.NET中核心的對象模型Routing模塊,為什么說愉快呢,因為Routing正是建立在大家都比較熟悉的ASP.NET管道模型基礎之上的,所以相比其他一些陌生的概念會輕松很多,不過不要緊一回生二回熟;

ASP.NET Routing 系統(tǒng)是一切通過ASP.NET進行Uri訪問應用程序的基礎(并非物理文件的直接映射);隨著Routing的出現(xiàn),我們的WEB設計已經(jīng)和以前大不一樣;越來越輕量級、簡單化,都通過簡便的Uri資源的方式進行處理,將精力放在業(yè)務的設計上;現(xiàn)在主流的Rest ful api 也都是建立在這樣的一種機制下的,然而我們的ASP.NETMVC也是一種通過獨立的Uri進行程序訪問處理的框架,所以也是建立在ASP.NET Routing;再者就是現(xiàn)在也比較熱門的ASP.NET技術(ASP.NETWEBAPI);都是建立在Routing框架之上,可見它還是蠻重要的;

所以這篇文章讓我們來分析一下Routing的工作原理,它為什么能在不影響現(xiàn)有框架的基礎上提供這么好的擴展性,真的讓人很想去一探究竟;目前非常可觀是我們都了解ASP.NET現(xiàn)有的框架知識,我們大概了解它肯定是在ASP.NET管道模型的哪個位置進行了相應的攔截;

下面我們帶著這個重要的線索來一點一點弄清楚它是如何為其他框架做支撐的,我最疑惑的是它是如何將WebPage和MVC進行很好的區(qū)分的 ,最關鍵的是它如何做到只提供一個接口讓后續(xù)的相關框架都能基于這個公共的Routing接口進行擴展的,它的對象模型肯定很巧妙;我們需要去搞懂它,才能有信心去繼續(xù)我們的ASP.NET相關框架的后續(xù)學習;

注意:全文使用Routing一詞替代ASP.NETRouting一詞,特此說明,以免概念混淆;

2】ASP.NETRouting路由對象模型的位置

問到ASP.NET最重要的擴展點在哪里?我想我們都會異口同聲的說:在管道模型上,這也符合我們對此問題求解的一個基本思路;ASP.NET管道模型大家都懂的,在管道模型的相關事件中只要我們定義相關的事件就可以在管道的處理中插入自己的邏輯在里面;管道的最后執(zhí)行接口是IHttpHander類型,只有阻止原本默認的IHttpHander接口創(chuàng)建才有可能改變整個的處理流程;

圖2.1:

.NET/ASP.NET Routing路由(深入解析路由系統(tǒng)架構(gòu)原理)

那么Routing只有在阻止IHttpHander接口的創(chuàng)建前先執(zhí)行,才能扭轉(zhuǎn)整個處理路線的機會,上圖中顯示的Application Event(2)(IHttpHander執(zhí)行)意思是說只有在IHttpHander執(zhí)行前的某個Application Event中進行Routing的執(zhí)行才能在原本執(zhí)行IHttpHander的地方執(zhí)行其他定制的IHttpHander;而IHttpHander是ASP.NET框架的最終執(zhí)行的接口,所以如果要想改變原本執(zhí)行Page的Hander,需要提供自定義的IHttpHander接口對象;

換句話說,一切的執(zhí)行入口其實在IHttpHander.Proce***equest()方法中,但是現(xiàn)在矛盾的是ASP.NET Routing卡在中間,它讓原本直接的處理流程變的有點撲簌迷離,它隔開了“ASP.NET基礎框架 ""基于ASP.NET的應用框架 "(如:ASP.NETMVC\ASP.NETWEBAPI\自定義框架);

注意:“ASP.NET基礎框架”指ASP.NET本身的框架可以理解為傳統(tǒng)的WEBFROM;而“基于ASP.NET的應用框架”是指基于ASP.NET基礎框架而設計的如:MVC\WEBPAGE\WEBAPI之類的上層輕量級應用框架;

圖2.2:

.NET/ASP.NET Routing路由(深入解析路由系統(tǒng)架構(gòu)原理)

其實這幅圖很明了的表達式了ASP.NETRouting的位置,它是用來為ASP.NETASP.NETMVC、ASP.NETWEBAPI承上啟下的關鍵紐帶;根據(jù)上面我們的分析思路,Routing是ASP.NET框架直接交互的對象模型,所以站在ASP.NET的角度它是不知道背后究竟發(fā)生了什么事情,其實ASP.NETRouting已經(jīng)在ASP.NETApplication某個生命事件中將原本的創(chuàng)建邏輯移花接木了;

3.】ASP.NETRouting路由對象模型的入口

Routing起到中間人的作用,將ASP.NET的相關邏輯透明包裝,我們雖然能在Routing的上層同樣可以使用相關的ASP.NET對象,但是概念已經(jīng)發(fā)生了根本上的變化;我們可以隨意的引入自定義的IHttpHander實現(xiàn)類,根據(jù)前端傳過來的Uri進行策略執(zhí)行,也就是說你完全可以定義一套自己內(nèi)部使用的Uri規(guī)則和處理框架,建立在Routing基礎之上會很容易;

根據(jù)IHttpModule、IHttpHander的相關的知識,我們很容易就能知道從哪里可以找到Routing的入口線索,如果我們都沒有猜錯的話在系統(tǒng)的Web.config文件中肯定有一個專門處理Routing的IHttpModule,利用來它將ASP.NETRouting對象植入到ASP.NET框架之中;

我們找到.NET Framework環(huán)境配置的地方:C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config 在該文件中我們可以找到系統(tǒng)級別的配置信息;

其實這里面配置的都是系統(tǒng)級別的選項,而我們程序里面使用的Web.config文件只是用來配置跟應用程序相關的選項,這樣的好處是我們可以在應用程序級別很方便的改變系統(tǒng)的默認配置;

我們找到httpModules配置節(jié),在倒數(shù)第二行發(fā)現(xiàn)一個nameUrlRoutingModule-4.0IHttpModule配置,應該就是它了,最關鍵的是它的type信息是System.Web.Routing.UrlRoutingModule 毋庸置疑了;

現(xiàn)在就好辦多了,我們只要順藤摸瓜就能找到UrlRoutingModule是如何工作的了,不過先不能急,還有些思路并不清晰,我們繼續(xù)慢慢分析;按照這樣的一個思路,基本上我們可以斷定UrlRoutingModule就是協(xié)調(diào)ASP.NETRouting框架的紐帶;

圖3.1:

.NET/ASP.NET Routing路由(深入解析路由系統(tǒng)架構(gòu)原理)

此圖總結(jié)了我們到目前為止的一個基本思路,底層ASP.NET框架處理HTTP的對象化,然后通過ASP.NETRouting Module創(chuàng)建IHttpHandler接口對象,再然后就是執(zhí)行IHttpHander接口,共三個步驟;

作為應用框架也就是最上層的代碼,如何才能決定ASP.NETRouting框架在處理ASP.NET的調(diào)用的時候能使用自己的IHttpHander接口對象,這個問題就需要我們深入的看一下ASP.NETRouting路由對象的內(nèi)部對象模型了;

4.】ASP.NETRouting路由對象模型的內(nèi)部結(jié)構(gòu)

這里我將使用ASP.NETMVC作為應用框架來講解本例(目前我并不了解ASP.NETWEBAPI);那么ASP.NETMVC作為應用層框架,是如何讓ASP.NETRouting幫助轉(zhuǎn)換IHttpHander接口的呢,這就不得不去分析Routing一些列的對象之間的組成關系及互相作用了;

根據(jù)3.】小節(jié),我們已經(jīng)了解ASP.NETRouting是使用UrlRoutingModuel對象來作為ASP.NET管道的監(jiān)聽者,然后根據(jù)一系列的內(nèi)部處理得出最終的IHttpHander接口對象;那么要想搞清楚UrlRoutingModule是如何具體的協(xié)調(diào)這一切的,必須得深入的去分析源代碼才行,盡管我們只需要了解一個80%那也少不了這個環(huán)節(jié);

注意:需要源代碼的朋友可以直接去一下站點獲取,微軟官方開源網(wǎng)站:http://www.codeplex.com/,開源中國:http://www.oschina.net/都可以找到源代碼;

4.1】UrlRoutingModule對象內(nèi)部結(jié)構(gòu)

首當其沖需要搞清楚的就是UrlRoutingModule對象,根據(jù)源碼指示我們基本上能確定幾個基本的原理,首先UrlRoutingModule繼承自IHttpModule接口,訂閱了Application.PostResolveRequstCache事件,在該事件中主要是通過全局路由對象表RouteTable對象獲取提供給上層使用的依賴注入接口IRouteHander接口;

【依賴注入接口】

這里需要解釋一下什么叫依賴注入接口,可以簡單的將依賴注入接口理解成提供給外界一個具體實現(xiàn)的機會;其實就是設計原則中的“依賴倒置原則”,在RouteData的內(nèi)部不是直接依賴具體的對象;接口就是契約,提供一個接口就是約定雙方之間的契約;這里是約定了Routing框架將使用IRouteHander接口來獲取最后的處理IHttpHander接口;

下面我們將對UrlRoutingModule對象進行分析,由于我們分析源代碼是想搞清楚對象模型之間的操作流程及關系,所以不可能分析所有的代碼,我們的重點是搞清楚他們的執(zhí)行順序及原理;由于UrlRoutingModule對象是導火線,它的出現(xiàn)將接二連三的牽連其他的對象出現(xiàn),我們將分小節(jié)進行分析,交界處將一帶而過;

根據(jù)我們前面的分析思路,我們首先要找到UrlRoutingModule綁定Application事件的地方;

protected virtual void Init (HttpApplication application)
        {
            application.PostResolveRequestCache += PostResolveRequestCache;
        }

在PostResolverRequestCache方法中,我們將看到該方法調(diào)用了本地內(nèi)部的一個同名方法:

void PostResolveRequestCache (object o, EventArgs e)
        {
            var app = (HttpApplication) o;
            PostResolveRequestCache (new HttpContextWrapper (app.Context));
        }

然后實例化了一個HttpContextWrapper包裝對象,傳入該同名方法;

public virtual void PostResolveRequestCache (HttpContextBase context)
        {
            var rd = RouteCollection.GetRouteData (context);
           //(1)匹配RouteData對象,后面分析;
            var rc = new RequestContext (context, rd);
            //(2)封裝計算出來的RouteData對象和當前HttpRequest對象;
            IHttpHandler http = rd.RouteHandler.GetHttpHandler (rc);
            //(3)使用(1)步驟計算出來的當前RouteData對象中的RouteHander屬性獲取路由處理程序IHttpHander接口;
            context.Request.RequestContext = rc;
            context.RemapHandler (http);
       }

當然我已經(jīng)省略了部分不太相關的代碼,畢竟要想說清楚所有的代碼一篇文章顯然是不夠的;上述代碼中我用紅色標記出重要的部分;

首先是第一個重要點(1),匹配RouteData對象;其實就是我們在程序里面配置的Url模板數(shù)據(jù),當請求來的時候我們需要去根據(jù)當前請求的Url到路由表去匹配是否有符合當前Url的路由對象;

routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

其實就是對應著本段代碼的配置,這段代碼處理后將是一個Route對象實例,而上面的RouteCollection就很好理解了,它是Route的強類型集合;

到目前為止,已經(jīng)出現(xiàn)了好幾個跟Route相關的對象,沒關系,當我們將整條線分析到頭時將很清楚他們的作用;

第二個重要點(2),封裝RequestContext對象,其實我們從類型的名稱上就能確定它的用途,它是請求上下文,也是有界上下文;這里面封裝了在下面獲取IHttpHander接口時將需要當作參數(shù);

第三個重點(3),利用前面的匹配得到的RouteData對象,其實RouteData是路由數(shù)據(jù)的意思,那么什么叫路由數(shù)據(jù):就是路由匹配成功后所生成的和路由相關的數(shù)據(jù);還記得我們在3】節(jié)分析的原理嗎,UrlRoutingModule對上層提供基本的路由功能,但是具體的處理是在應用層面上;

那么就是這里通過RouteData.RouteHandler.GetHttpHandler(RequestContext requestContext) 方法獲取到的最終頂層應用處理器;

圖4.1:

.NET/ASP.NET Routing路由(深入解析路由系統(tǒng)架構(gòu)原理)

上面的解釋可以使用這幅圖來簡單的表達;

UrlRoutingModule對象通過RouteData路由數(shù)據(jù)對象獲取IRouteHander接口,然后通過IRouteHander接口獲取最終的IHttpHander接口;

小結(jié):其實可以將UrlRoutingModule對象理解成是ASP.NETRouting模塊的基礎部分,而擴展的地方則在我們應用程序配置的地方,也就是我們通常在Global.asax.cs文件中配置的路由數(shù)據(jù);當我們在配置Route對象的時候其實已經(jīng)指定了IRouteHander接口,然后這個接口會被放入RouteData同名屬性中,而不是作為零散的對象被UrlRoutingModule直接獲??;

4.2】RouteBase、Route、RouteCollection、RouteTable路由核心對象模型

在4.1 】節(jié)中,UrlRoutingModule是路由框架的基礎設施部分,內(nèi)置于. NETFramework系統(tǒng)及ASP.NET配置之中web.config;在ASP.NET進行版本升級的時候該部分工作已經(jīng)由系統(tǒng)自動幫我們升級,我們在使用的時候只需要創(chuàng)建ASP.NET3.5 SP1以上的版本都會自動擁有路由系統(tǒng)功能,因為根據(jù)微軟官方MSDN介紹,路由系統(tǒng)是在ASP.NET3.5 SP1中引入的;其實我們大部分使用的ASP.NET版本已經(jīng)是4.5的,就算以前是2.0、3.0的版本也會陸續(xù)升級到最新的版本;因為新版本的框架提供了無數(shù)個讓你無法拒絕的優(yōu)勢;

那么當基礎部分有了之后我們能做到就是應用編程接口的編程,其實這部分才是我們接觸的地方;而這一小節(jié)我們將重點分析路由系統(tǒng)提供給我們應用層面的編程接口,也就是上面標題列出的幾個核心對象;

先基本介紹一下這幾個對象的意思和彼此之間的關系:

RouteBase:很明顯是Route的基類,提供了作為自定義路由對象的頂層抽象,所有的路由框架的內(nèi)部均使用抽象的RouteBase為依賴;

Route:路由系統(tǒng)默認實現(xiàn)的路由對象繼承自RouteBase抽象基類,用來作為我們默認的路由配置對象,當然你可以可是實現(xiàn)自己的Route對象;

RouteCollection:Route作為單個Url的配置,那么系統(tǒng)中肯定會有多個Url規(guī)則的配置,所以RouteCollection對象是表示Route的強類型集合,該類繼承自 Collection類型;所以RouteCollection是用來作為Route的集合管理用的;注意這里的泛型Collection中的RouteBase,再一次提醒我們要“依賴倒置”;

RouteTable:用來存放RouteCollection對象,路由表中有一系列的路由對象,而這一系列的對象就是RouteCollection管理的;在RouteTable中用Routes靜態(tài)屬性表示當前系統(tǒng)全局的路由映射表;

這里很明顯能看出來對路由的一層一層抽象,從簡單的Route表示一個路由映射,再到表示Route的集合RouteCollection,再到最后的RouteTable的,抽象的很OO;

為了讓大家對上面這些對象的解釋有一個直觀的認識,我們用一張圖來解釋他們?nèi)绾侮P聯(lián)和執(zhí)行流程;

圖4.2:

.NET/ASP.NET Routing路由(深入解析路由系統(tǒng)架構(gòu)原理)

下面我們將深入到各個對象的內(nèi)部去摸索一下他們之間的交互,我們根據(jù)這種引用關系來分析,首先是Route對象;

【Route、RouteBase】

Route對象繼承自RouteBase代表一個Url模板的配置,包括Url的模板的字符串,如:api/order/102304,還有一些輔助性的內(nèi)容,這不是本節(jié)的重點,我們只要知道它是用來做Url的配置即可; Route對象不是直接被我們實例化的,而是通過應用層的擴展方法進行實例化,為什么要這么做,其實這里就是路由為什么能轉(zhuǎn)到上層的關鍵點;

根據(jù)ASP.NETMVC中的路由集合擴展類,也就是System.Web.Mvc.RouteCollectionExtensions靜態(tài)類中的擴展方法,這些擴展方法就是用來包裝我們在應用ASP.NET的時候配置Route使用的;是否還記得我們第4】節(jié)的一開始介紹了一個依賴注入接口的原理,這里將通過依賴注入接口達到外掛自定義實現(xiàn)的目的;

在Route源碼中,我們將看到它有一個IRouteHander接口類型的屬性RouteHander;

public class Route : RouteBase
{
  public IRouteHandler RouteHandler { get; set; }
}

這個IRouteHandler接口類型的屬性就是我們ASP.NETMVC將要實現(xiàn)的一個IRouteHandler接口;而這個接口的定義:

public interface IRouteHandler
{
    IHttpHandler GetHttpHandler (RequestContext requestContext);
}

很簡單,就是為了創(chuàng)建出ASP.NET管道引擎最后執(zhí)行的IHttpHandler接口; Route類有一個重寫了RouteBase的核心方法:

public override RouteData GetRouteData (HttpContextBase httpContext)

該方法是用來獲取當前路由的一些匹配數(shù)據(jù)的,關于RouteData在4.1】節(jié)介紹過,詳細我們將看下面關于對它的詳細分析,這里將不做介紹了;

小結(jié):其實Route對象還算簡單,關鍵的兩點就是GetRouteData方法和IRouteHander接口,前者是用來獲取當前路由匹配成功后的路由信息,而后者是用來返回最終要執(zhí)行的IHttpHandler接口;

【RouteCollection、RouteTable】

RouteCollecton和RouteTable對象比較簡單;我們先來看RouteCollection對象,首先你可能會有疑問,為什么不用一個簡單的Collection類型的對象來存放Route實例,非要實現(xiàn)了一個RouteCollection;不看源碼還真不知道它內(nèi)部做了很多工作,首先最重要的就是線程并發(fā)情況下的Look機制;由于我們的RouteCollection對象是全局靜態(tài)對象,會同時存在著多個線程并發(fā)的讀取這個對象,所以必須在對集合訪問的時候進行互斥控制;比如說這段代碼:

public void Add (string name, RouteBase item)
{
    lock (GetWriteLock ()) {
        base.Add (item);
        if (!String.IsNullOrEmpty (name))
            d.Add (name, item);
    }
}

在添加路由的時候首先鎖住寫入對象,然后才能安全的進行操作;我們接著RouteTable對象,這個對象最簡單,就是一個靜態(tài)屬性Routes用來存放全局路由表;

public class RouteTable
{
    static RouteTable ()
    {
        Routes = new RouteCollection ();
    }
    public static RouteCollection Routes { get; private set; }
}

當首次獲取Routes屬性時,會在靜態(tài)構(gòu)造函數(shù)中實例化RouteCollection對象;

4.3】RouteValueDictionary、RouteData、RequestContext 路由數(shù)據(jù)對象模型

在第4.2】小節(jié)中,我們分析了路由系統(tǒng)的幾個核心對象,但是核心對象要想運行起來中間必須有一些數(shù)據(jù)封裝的對象為他們消除數(shù)據(jù)傳遞的問題;而這小節(jié)的三個核心對象真是路由系統(tǒng)能成功工作的必不可少的數(shù)據(jù)存放、數(shù)據(jù)傳輸容器的核心對象;

先基本介紹一下這幾個對象的意思和彼此之間的關系:

RouteValueDictionary:路由對象內(nèi)部存放中間值使用的對象,比如Url模板的默認值,命名空間,地址欄傳過來的參數(shù)等等;當然也可以用來存放任何Key-Value形式的任何值;

RouteData:路由數(shù)據(jù),用來包裝根據(jù)路由Url匹配成功后的路由數(shù)據(jù)封裝,最重要的是將IRouteHander接口傳遞到UrlRoutingModule中去;

RequestContext:請求上下文,將HttpRequest、RouteData包裝起來傳入IRouteHander接口獲取IHttpHander接口;因為IRouteHandler接口方法GetHttpHandler需要知道當前請求的一些信息和根據(jù)當前Url處理后的路由數(shù)據(jù)才能計算出當前的IHttpHandler接口;

為了讓大家對上面這些對象的解釋有一個直觀的認識,我們用一張圖來解釋他們?nèi)绾侮P聯(lián)和執(zhí)行流程;

圖4.3:

.NET/ASP.NET Routing路由(深入解析路由系統(tǒng)架構(gòu)原理)

下面詳細的分析每個對象的內(nèi)部原理;

【RouteValueDictionary】

RouteValueDirctionary對象是在路由對象內(nèi)部存放數(shù)據(jù)用的,比如:我們在配置路由的時候,可以指定一些默認值、命名空間等等;

看RouteValueDictionary源碼定義:

public class RouteValueDictionary : IDictionary

該類型繼承自字典接口IDictionary,繼承自字典接口而不是繼承自字典基類目的只是想使用字典的行為而不是它的默認實現(xiàn);在RouteValueDictionary內(nèi)部使用了一個Dictionary類型作為最終容器;

Dictionary d = new Dictionary (CaseInsensitiveStringComparer.Instance);

在構(gòu)造函數(shù)中使用了一個內(nèi)部類CaseInsensitiveStringComparer進行Key的相等比較:

internal class CaseInsensitiveStringComparer : IEqualityComparer
        {
            public static readonly CaseInsensitiveStringComparer Instance = new CaseInsensitiveStringComparer ();
            public int GetHashCode (string obj)
            {
                return obj.ToLower (CultureInfo.InvariantCulture).GetHashCode ();
            }
            public bool Equals (string obj1, string obj2)
            {
                return String.Equals (obj1, obj2, StringComparison.OrdinalIgnoreCase);
            }
        }

IEqualityComparer接口還是很不錯的,不過現(xiàn)在基本上不這么用了,而是直接提供了一個Lambda做為比較函數(shù);

【RouteData】

路由數(shù)據(jù)對象,它的大概意思我想大家應該知道了,上面提到過很多次,這里就不介紹了;我們直接看一下RouteData內(nèi)部核心代碼段:

public RouteData (RouteBase route, IRouteHandler routeHandler)
{
    // arguments can be null.
    Route = route;
    RouteHandler = routeHandler;
    DataTokens = new RouteValueDictionary ();
    Values = new RouteValueDictionary ();
}
public RouteValueDictionary DataTokens { get; private set; }
public RouteBase Route { get; set; }
public IRouteHandler RouteHandler { get; set; }
public RouteValueDictionary Values { get; private set; }

通過構(gòu)造函數(shù)我們能了解到,保存了對Route對象的引用和IRouteHander接口的引用,為什么將IRouteHandler作為構(gòu)造函數(shù)參數(shù),那是因為RouteBase根本沒有對IRouteHander接口的屬性定義;IRouteHandler接口在不在RouteBase或Route中不重要,因為Route可以是自定義的,這里的強制性是在RouteData中,它的構(gòu)造函數(shù)必須接受IRouteHandler類型接口;

我們接著看,在構(gòu)造函數(shù)的下面兩行代碼中分別是實例化了DataTokens、Values兩個屬性,而類型是RouteValueDictionary,這也剛好和我們上面分析的對上了;RouteValueDictionary是內(nèi)部用來保存這些零散鍵值對數(shù)據(jù)容器,在Route、RouteData還有其他地方均需要用到;就是因為RouteValueDictionary的Value是Object類型,所以可以用來存放任何類型的值,比較通用;

【RequestContext 】

RequestContext在上面也已經(jīng)接觸很多次了,表示請求上下文,也就是跟當請求相關的所有數(shù)據(jù)都封裝在里面;在后面的文章中,我們將接觸很多類似Context的對象,如:ControlContext,ViewContext之類的,都是用來控制上下文的邊界,而不是直接傳遞零散的參數(shù);

4.4】IRouteHandler 、IHttpHander兩個接口之間的關系

IRouteHandler接口是路由框架起作用的核心,只有提供了IRouteHandler實現(xiàn)才能順利的得到背后的IHttpHandler接口;ASP.NETMVC提供了MvcRouteHandler對象來實現(xiàn)IRouteHandler接口,MvcRouteHandler在內(nèi)部實例化實現(xiàn)了IHttpHandler接口的MvcHandler對象;MvcHandler然后通過RequestContext對象獲取RouteData對象,接著得到相應的Control信息,進行后續(xù)的執(zhí)行處理;

5.】UrlRoutingHandler 對象內(nèi)部結(jié)構(gòu)及擴展應用

在ASP.NETRouting路由框架中有一個很重要的IHttpHandler接口對象UrlRoutingHanlder,我想你肯定很疑惑,為什么需要這樣一個對象;其實它的存在是為了提供給我們繞過UrlRoutingModule模塊的機會;根據(jù)上面的詳細的分析,我們知道路由的入口在UrlRoutingModule,所有的路由相關的映射工作都在該類中完成,但是有時候我們很想繞過UrlRoutingModule進行簡單的處理或者性能方面的優(yōu)化考慮,這就派上用場了;我能想到的使用場景目前來看是對ASP.NET第版本的項目做Url重寫是比較方便,首先我們的項目需要建立在低版本的ASP.NET之上,但是需要添加Url.ReWriter的功能,就需要我們自己去實現(xiàn)這樣的功能;

但是工作量和性能都很難控制好,如果使用這里提供的UrlRoutingHandler進行實現(xiàn)就很方便了,UrlRoutingHandler給我們使用ASP.NETRouting框架的機會同時也不需要關心是否配置了UrlRoutingModule;

public abstract class UrlRoutingHandler : IHttpHandler

根據(jù)代碼看出它是一個抽象類,直接實現(xiàn)IHttpHanlder接口,但是重要的是Proce***equest方法;

protected virtual void Proce***equest (HttpContextBase httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException ("httpContext");
            var rd = RouteCollection.GetRouteData (httpContext);
            if (rd == null)
                throw new HttpException ("The incoming request does not match any route");
            if (rd.RouteHandler == null)
                throw new InvalidOperationException ("No  IRouteHandler is assigned to the selected route");
            RequestContext rc = new RequestContext (httpContext, rd);
            var hh = rd.RouteHandler.GetHttpHandler (rc);
            VerifyAndProce***equest (hh, httpContext);
        }
        protected abstract void VerifyAndProce***equest (IHttpHandler httpHandler, HttpContextBase httpContext);

該方法的邏輯跟UrlRoutingModule里的PostResolveRequestCache方法是差不多的,都會通過全局RouteCollection集合進行匹配當前的RouteData對象;那就足夠說明這個過程不會再通過UrlRoutingModule模塊;方法的最后一行是執(zhí)行一個模板方法:VerifyAndProce***equest ,該方法是留給子類去實現(xiàn)的;

那么這里將路由和執(zhí)行合在一起了,基類負責路由子類負責執(zhí)行,很不錯的設計方法;

總結(jié):這篇文章基本上介紹了跟路由相關的核心對象,但是還有一些其他輔助的類這里并沒有進行講解,當然如果你有興趣可以自己去看看;這篇文章是為了讓我們能對路由的處理流程及結(jié)構(gòu)有個了解,做到能在適當?shù)臅r候進行擴展和查找問題;

作者:王清培

出處:http://wangqingpei557.blog.51cto.com/

本文版權(quán)歸作者和51CTO共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權(quán)利。


網(wǎng)頁標題:.NET/ASP.NETRouting路由(深入解析路由系統(tǒng)架構(gòu)原理)
本文網(wǎng)址:http://weahome.cn/article/ggcphj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部