溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

ASP.NET Web API 路由對象介紹

發(fā)布時間:2020-06-19 18:36:00 來源:網(wǎng)絡(luò) 閱讀:1058 作者:jinyuan0829 欄目:編程語言

ASP.NET Web API 路由對象介紹

前言

ASP.NETASP.NET MVCASP.NET Web API中這些框架中都會發(fā)現(xiàn)有路由的身影,它們的原理都差不多,只不過在不同的環(huán)境下作了一些微小的修改,這也是根據(jù)每個框架的特性來制定的,今天我們就來看一看路由的結(jié)構(gòu),雖然我在MVC系列里寫過路由的篇幅不過在這里是Web API 路由對象介紹。

 

 

 

ASP.NET Web API路由、管道

  • ASP.NET Web API 開篇介紹示例

  • ASP.NET Web API 路由對象介紹

  • ASP.NET Web API 管道模型

  • ASP.NET Web API selfhost宿主環(huán)境中管道、路由

  • ASP.NET Web API webhost宿主環(huán)境中管道、路由



路由系統(tǒng)概念

路由的結(jié)構(gòu)

1

ASP.NET Web API 路由對象介紹

路由系統(tǒng)中最重要的部分也就是路由對象了,那我們首先就來看一下【路由對象】的定義,不管是在ASP.NET、ASP.NET MVC、還是ASP.NET Web API的路由系統(tǒng)中路由都要有個名稱,其實這個名稱并不是路由對象中的而是在注冊路由信息的時候,添加到路由對象集合的時候需要的名稱,這里也只是當作路由的一部分,這個大家知道就好了。

在生成路由對象的時候我們要給路由賦值URL模板,這也是共同的,也是必須的,至于約束URL模板的條件是可以根據(jù)自己情況來定義的。在生成的同時框架會給路由對象賦值上【路由請求處理程序】用以作為銜接路由系統(tǒng)和框架的主體功能部分。

 

注冊路由到系統(tǒng)框架中

2

ASP.NET Web API 路由對象介紹

在路由定義好之后,我們便會把它注冊到系統(tǒng)框架中。

 

路由對象的URL匹配

3

ASP.NET Web API 路由對象介紹

在路由對象注冊到系統(tǒng)框架中之后,這個時候如果有外部的請求的到達,這個時候路由系統(tǒng)會讓路由對象集合中每個路由對象對這個請求進行匹配,就如圖4一樣。

4

ASP.NET Web API 路由對象介紹

這個時候就是路由對象所要能做出的行為就是URL的匹配,根據(jù)什么來匹配?是根據(jù)在路由對象實例化的時候定義好的URL模板和條件,拿請求信息的URL和自身定義的URL模板進行匹配,假使沒有匹配成功則會返回Null,這個時候框架則會讓下一個路由對象來進行匹配直到有匹配的成功為止,如果這個時候匹配成功了路由則會生成一個【路由數(shù)據(jù)對象】。

 

路由數(shù)據(jù)對象也很重要,因為后續(xù)的框架功能部分都是使用它的,它也是整個路由系統(tǒng)的結(jié)晶,我們看下圖5

5

ASP.NET Web API 路由對象介紹

路由數(shù)據(jù)對象會保持一個生成它的路由對象的引用,然后是Values的是保存著路由對象在經(jīng)過URL匹配后的值,分別表示著URL片段的名字和對應(yīng)的URL真實值,而DataTokens則是在路由對象定義生成的時候直接帶過來的值,當然了路由請求處理程序也是由執(zhí)行生成的路由對象帶來的。

 

ASP.NETASP.NET MVC、ASP.NET Web API這些框架中路由系統(tǒng)都是遵循著上面的所述的這樣一個過程,只不過在不同的框架環(huán)境下使用的類型不同,做的處理也不太一樣,但是整體的流程是一致的,下面附上圖6說明了之間的類型的差異性,還有更多的細節(jié)就不一一展示了。

6

ASP.NET Web API 路由對象介紹

還有在Web API(WebHost)環(huán)境下路由顯示的是這樣實質(zhì)的本質(zhì)其實又是ASP.NET的路由系統(tǒng)在支持的,這個會在后面的Web API系列篇幅中講解。

 

下面簡單的演示一下在各種框架環(huán)境下的路由對象注冊,

ASP.NET

RouteTable.Routes.MapPageRoute(
                "ASP.NETRoute",
                "ProductInfo/{action}/{id}",
                "~/ProductInfo.aspx",
                true,
                newRouteValueDictionary { {"id", RouteParameter.Optional }, { "action", "show" } }
                );


ASP.NET MVC

            RouteTable.Routes.MapRoute(
                "ASP.NETMVCRoute",
                "ProductInfo/{action}/{id}",
                new { controller="Product",action="show",id=RouteParameter.Optional}
                );


ASP.NET Web APIWEBHOST):

            GlobalConfiguration.Configuration.Routes.MapHttpRoute(
               "WebAPIRoute",
               "api/{controller}/{id}", new { id=RouteParameter.Optional }
              );


 

ASP.NET Web APISELFHOST):

HttpSelfHostConfigurationconfiguration=
                newHttpSelfHostConfiguration("http://loacalhost/selfhost");
            using (HttpSelfHostServerselfHostServer=newHttpSelfHostServer(configuration))
            {
                selfHostServer.Configuration.Routes.MapHttpRoute(
                    "DefaultApi", "api/{controller}/{id}", new { id=RouteParameter.Optional});
               
                selfHostServer.OpenAsync();
                Console.Read();
            }


 

ASP.NET Web API路由系列對象

從上圖的圖表中就可以看出,ASP.NET Web API框架在不同的宿主環(huán)境下路由系統(tǒng)中所對應(yīng)的對象類型是不同的,這里就先給大家介紹在SelfHost環(huán)境下的路由系統(tǒng)中的路由對象吧。

 

SelfHost宿主環(huán)境

 

Web API路由對象(System.Web.Http.Routing)

HttpRoute

   // 摘要:
   //     表示自承載(即在 ASP.NET 之外承載)的路由類。
   publicclassHttpRoute : IHttpRoute
   {
        publicHttpRoute(stringrouteTemplate, HttpRouteValueDictionarydefaults, HttpRouteValueDictionaryconstraints, HttpRouteValueDictionarydataTokens, HttpMessageHandlerhandler);
 
        publicIDictionary<string, object>Constraints { get; }
        publicIDictionary<string, object>DataTokens { get; }
        publicIDictionary<string, object>Defaults { get; }
        publicHttpMessageHandlerHandler { get; }
        publicstringRouteTemplate { get; }
        publicvirtualIHttpRouteDataGetRouteData(stringvirtualPathRoot, HttpRequestMessagerequest);
        publicvirtualIHttpVirtualPathDataGetVirtualPath(HttpRequestMessagerequest, IDictionary<string, object>values);
        protectedvirtualboolProcessConstraint(HttpRequestMessagerequest, objectconstraint, stringparameterName, HttpRouteValueDictionaryvalues, HttpRouteDirectionrouteDirection);
    }


可以從上面的定義中看到HttpRoute對象就是代表著在Web API框架中的路由對象了,在HttpRoute類型定義的構(gòu)造函數(shù)中的參數(shù)分別表示著路由模板、路由模板對應(yīng)的默認值、路由匹配條件、注冊的路由附帶的值以及最后的Http請求處理程序,這幾個參數(shù)值也分別對應(yīng)著HttpRoute類型中的幾個屬性,這個自行看一下就明白了。

 

Web API路由對象集合(System.Web.Http)

HttpRouteCollection

HttpRouteCollectionExtensions

 

我們先來看一下HttpRouteCollection類型的擴展類型HttpRouteCollectionExtensions

   publicstaticclassHttpRouteCollectionExtensions
   {
        publicstaticIHttpRouteMapHttpRoute(thisHttpRouteCollectionroutes, stringname, stringrouteTemplate);
        publicstaticIHttpRouteMapHttpRoute(thisHttpRouteCollectionroutes, stringname, stringrouteTemplate, objectdefaults);
        publicstaticIHttpRouteMapHttpRoute(thisHttpRouteCollectionroutes, stringname, stringrouteTemplate, objectdefaults, objectconstraints);
        publicstaticIHttpRouteMapHttpRoute(thisHttpRouteCollectionroutes, stringname, stringrouteTemplate, objectdefaults, objectconstraints, HttpMessageHandlerhandler);
    }


這里大家可以對比上面的路由注冊時的代碼,就可以知道我們在路由集合添加/注冊路由的時候是由HttpRouteCollectionExtensions類型的擴展方法來進行操作的,這個時候我們再看一下方法參數(shù)最多的那個MapHttpRoute()方法的實現(xiàn):

publicstaticIHttpRouteMapHttpRoute(thisHttpRouteCollectionroutes, stringname, stringrouteTemplate, objectdefaults, objectconstraints, HttpMessageHandlerhandler)
        {
            if (routes==null)
            {
                throwSystem.Web.Http.Error.ArgumentNull("routes");
            }
            HttpRouteValueDictionarydictionary=newHttpRouteValueDictionary(defaults);
            HttpRouteValueDictionarydictionary2=newHttpRouteValueDictionary(constraints);
            IDictionary<string, object>dataTokens=null;
            HttpMessageHandlerhandler2=handler;
            IHttpRouteroute=routes.CreateRoute(routeTemplate, dictionary, dictionary2, dataTokens, handler2);
            routes.Add(name, route);
            returnroute;
        }


這里大家就可以看到了,HttpRoute對象的創(chuàng)建操作和添加操作是在這擴展方法里執(zhí)行的,現(xiàn)在我們就可以去看一下HttpRouteCollection類型的定義了,看一下如何創(chuàng)建的IHttpRoute對象:

   publicclassHttpRouteCollection : ICollection<IHttpRoute>, IEnumerable<IHttpRoute>, IEnumerable, IDisposable
   {
        publicHttpRouteCollection();
        publicHttpRouteCollection(stringvirtualPathRoot);
 
        publicvirtualintCount { get; }
        publicvirtualboolIsReadOnly { get; }
        publicvirtualstringVirtualPathRoot { get; }
 
        publicvirtualvoidAdd(stringname, IHttpRouteroute);
        publicIHttpRouteCreateRoute(stringrouteTemplate, objectdefaults, objectconstraints);
        publicIHttpRouteCreateRoute(stringrouteTemplate, IDictionary<string, object>defaults, IDictionary<string, object>constraints, IDictionary<string, object>dataTokens);
        publicvirtualIHttpRouteCreateRoute(stringrouteTemplate, IDictionary<string, object>defaults, IDictionary<string, object>constraints, IDictionary<string, object>dataTokens, HttpMessageHandlerhandler);
        publicvirtualIHttpRouteDataGetRouteData(HttpRequestMessagerequest);
    }


這里只是其中的一部分,下面我們就來看一下具體的實現(xiàn),其實就是實例化一個HttpRoute路由對象根據(jù)用戶配置的參數(shù)信息:

publicvirtualIHttpRouteCreateRoute(stringrouteTemplate, IDictionary<string, object>defaults, IDictionary<string, object>constraints, IDictionary<string, object>dataTokens, HttpMessageHandlerhandler)
        {
            HttpRouteValueDictionarydictionary=newHttpRouteValueDictionary(defaults);
            HttpRouteValueDictionarydictionary2=newHttpRouteValueDictionary(constraints);
            returnnewHttpRoute(routeTemplate, dictionary, dictionary2, newHttpRouteValueDictionary(dataTokens), handler);
        }


這是路由對象集合類型的第一個作用就是添加/注冊路由信息,那么第二個呢?就是根據(jù)請求信息來匹配路由對象,上面也說過了,其實真正根據(jù)請求來匹配的并不是路由對象集合類型(HttpRouteCollection),而是在其中的每個路由,我們看一下HttpRouteCollection的障眼法:

publicvirtualIHttpRouteDataGetRouteData(HttpRequestMessagerequest)
        {
            if (request==null)
            {
                throwSystem.Web.Http.Error.ArgumentNull("request");
            }
            foreach (IHttpRouterouteinthis._collection)
            {
                IHttpRouteDatarouteData=route.GetRouteData(this._virtualPathRoot, request);
                if (routeData!=null)
                {
                    returnrouteData;
                }
            }
            returnnull;
        }


從這里可以看出在路由匹配完成后會返回一個實現(xiàn)IHttpRouteDatarouteData接口的對象,也就是上面所說的路由數(shù)據(jù)對象。

 

Web API路由數(shù)據(jù)對象(System.Web.Http.Routing)

HttpRouteData

 

publicclassHttpRouteData : IHttpRouteData
   {
        publicHttpRouteData(IHttpRouteroute);
        publicHttpRouteData(IHttpRouteroute, HttpRouteValueDictionaryvalues);
 
        publicIHttpRouteRoute { get; }
        publicIDictionary<string, object>Values { get; }
}


其實這里都不用講了,上面都講過了,HttpRouteData對象包含著生成它的路由對象(HttpRoute)的引用,并且Values值就是經(jīng)過匹配過后的路由模板值,key鍵對應(yīng)著Url模板的片段值,value對應(yīng)著的是片段對應(yīng)的真實值。

 

SelfHost環(huán)境下的路由就說到這里,大家看一下如下的示意圖,簡單的表示了在SelfHost環(huán)境下路由的一個處理過程,具體的細節(jié)會在后面的篇幅講解。

7

ASP.NET Web API 路由對象介紹

 

 

WebHost宿主環(huán)境

 

Web API路由對象(System.Web.Http.WebHost.Routing)

HostedHttpRoute

 

   internalclassHostedHttpRoute : IHttpRoute
   {
        //Methods
        publicHostedHttpRoute(stringuriTemplate, IDictionary<string, object>defaults, IDictionary<string, object>constraints, IDictionary<string, object>dataTokens, HttpMessageHandlerhandler);
        publicIHttpRouteDataGetRouteData(stringrootVirtualPath, HttpRequestMessagerequest);
        publicIHttpVirtualPathDataGetVirtualPath(HttpRequestMessagerequest, IDictionary<string, object>values);
 
        //Properties
        publicIDictionary<string, object>Constraints { get; }
        publicIDictionary<string, object>DataTokens { get; }
        publicIDictionary<string, object>Defaults { get; }
        publicHttpMessageHandlerHandler { get; privateset; }
        internalRouteOriginalRoute { get; privateset; }
        publicstringRouteTemplate { get; }
}


從上面的代碼定義中可以看到HostedHttpRoute是程序集內(nèi)部類型,并且是直接繼承自IHttpRoute接口,跟SelfHost環(huán)境中的HttpRoute對象是一點關(guān)系都沒有。

從它定義的內(nèi)部結(jié)構(gòu)來看它跟HttpRoute對象的結(jié)構(gòu)相似,還是那些屬性那些個對象,唯一不同的就是多了個OriginalRoute的只讀屬性(對于外部來說),這個屬性也就是封裝的HttpWebRoute對象,看下封裝時的實現(xiàn)

publicHostedHttpRoute(stringuriTemplate, IDictionary<string, object>defaults, IDictionary<string, object>constraints, IDictionary<string, object>dataTokens, HttpMessageHandlerhandler)
   {
        RouteValueDictionarydictionary= (defaults!=null) ?newRouteValueDictionary(defaults) : null;
        RouteValueDictionarydictionary2= (constraints!=null) ?newRouteValueDictionary(constraints) : null;
        RouteValueDictionarydictionary3= (dataTokens!=null) ?newRouteValueDictionary(dataTokens) : null;
        this.OriginalRoute=newHttpWebRoute(uriTemplate, dictionary, dictionary2, dictionary3, HttpControllerRouteHandler.Instance, this);
        this.Handler=handler;
    }


HostedHttpRoute對象構(gòu)造函數(shù)中可以清楚的看到OriginalRoute屬性是賦值的HttpWebRoute對象的實例,我們現(xiàn)在就來看一下HttpWebRoute對象的定義

   internalclassHttpWebRoute : Route
   {
        //Fields
        internalconststringHttpRouteKey="httproute";
 
        //Methods
        publicHttpWebRoute(stringurl, RouteValueDictionarydefaults, RouteValueDictionaryconstraints, RouteValueDictionarydataTokens, IRouteHandlerrouteHandler, IHttpRoutehttpRoute);
        privatestaticHttpRouteDirectionConvertRouteDirection(RouteDirectionrouteDirection);
        privatestaticRouteValueDictionaryGetRouteDictionaryWithoutHttpRouteKey(IDictionary<string, object>routeValues);
        publicoverrideVirtualPathDataGetVirtualPath(RequestContextrequestContext, RouteValueDictionaryvalues);
        protectedoverrideboolProcessConstraint(HttpContextBasehttpContext, objectconstraint, stringparameterName, RouteValueDictionaryvalues, RouteDirectionrouteDirection);
 
        //Properties
        publicIHttpRouteHttpRoute { get; privateset; }
}


從這里可以看到HttpWebRoute對象繼承自ASP.NET中的Route對象,現(xiàn)在就可以理解為HostedHttpRoute對象持有對ASP.NETRoute對象的引用,而在HostedHttpRoute的構(gòu)造函數(shù)實現(xiàn)中,對OriginalRoute屬性是賦值實例化的時候,在最后傳入了一個HttpControllerRouteHandler類型的路由處理程序,實則是給ASP.NET中的Route對象的路由處理程序(Routehandler屬性)進行的賦值。這里路由的具體的操作后續(xù)篇幅中會有講到一個全面的過程。

 

 

Web API路由對象集合(System.Web.Http.WebHost.Routing

HostedHttpRouteCollection

 

 

internalclassHostedHttpRouteCollection : HttpRouteCollection
        {
            //Fields
            privatereadonlyRouteCollection_routeCollection;
 
            //Methods
            publicHostedHttpRouteCollection(RouteCollectionrouteCollection);
            publicoverridevoidAdd(stringname, IHttpRouteroute);
            publicoverridevoidClear();
            publicoverrideboolContains(IHttpRouteitem);
            publicoverrideboolContainsKey(stringname);
            publicoverridevoidCopyTo(IHttpRoute[] array, intarrayIndex);
            publicoverridevoidCopyTo(KeyValuePair<string, IHttpRoute>[] array, intarrayIndex);
            publicoverrideIHttpRouteCreateRoute(stringuriTemplate, IDictionary<string, object>defaults, IDictionary<string, object>constraints, IDictionary<string, object>dataTokens, HttpMessageHandlerhandler);
            publicoverrideIEnumerator<IHttpRoute>GetEnumerator();
            publicoverrideIHttpRouteDataGetRouteData(HttpRequestMessagerequest);
            publicoverrideIHttpVirtualPathDataGetVirtualPath(HttpRequestMessagerequest, stringname, IDictionary<string, object>values);
            publicoverridevoidInsert(intindex, stringname, IHttpRoutevalue);
            privatestaticNotSupportedExceptionNotSupportedByHostedRouteCollection();
            privatestaticNotSupportedExceptionNotSupportedByRouteCollection();
            publicoverrideboolRemove(stringname);
            publicoverrideboolTryGetValue(stringname, outIHttpRouteroute);
 
            //Properties
            publicoverrideintCount { get; }
            publicoverrideIHttpRoutethis[stringname] { get; }
            publicoverrideIHttpRoutethis[intindex] { get; }
            publicoverridestringVirtualPathRoot { get; }
        }


看到這里的代碼定義,HostedHttpRouteCollection對象同樣也是程序集內(nèi)部類型,繼承自ASP.NET中的RouteCollection對象,這里要說是CreateRoute()方法和GetRouteData()方法返回的分別是HostedHttpRoute對象和HostedHttpRouteData對象,其實在GetRouteData()方法中起初生成的就是Routedata對象,只不過在返回的時候經(jīng)過HostedHttpRouteData對象封裝了一下。

 

Web API路由數(shù)據(jù)對象(System.Web.Http.WebHost.Routing)

HostedHttpRouteData

 

這里我們看一下HostedHttpRouteData類型的定義:

        internalclassHostedHttpRouteData : IHttpRouteData
        {
            //Methods
            publicHostedHttpRouteData(RouteDatarouteData);
 
            //Properties
            internalRouteDataOriginalRouteData { get; privateset; }
            publicIHttpRouteRoute { get; privateset; }
            publicIDictionary<string, object>Values { get; }
        }


從構(gòu)造函數(shù)的定義就可以看出來是HostedHttpRouteData是封裝的RouteData對象,這些路由流程細節(jié)后面篇幅中會有講解。

 

最后我們看一下在WebHost宿主環(huán)境下的路由示意圖。

8

ASP.NET Web API 路由對象介紹

 


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI