在ASP.NET、ASP.NET MVC和ASP.NET Web API這些框架中都會發現有路由的身影,它們的原理都差不多,只不過在不同的環境下作了一些微小的修改,這也是根據每個框架的特性來制定的,今天我們就來看一看路由的結構,雖然我在MVC系列里寫過路由的篇幅不過在這里是Web API 路由對象介紹。
圖1
路由系統中最重要的部分也就是路由對象了,那我們首先就來看一下【路由對象】的定義,不管是在ASP.NET、ASP.NET MVC、還是ASP.NET Web API的路由系統中路由都要有個名稱,其實這個名稱并不是路由對象中的而是在注冊路由信息的時候,添加到路由對象集合的時候需要的名稱,這里也只是當作路由的一部分,這個大家知道就好了。
在生成路由對象的時候我們要給路由賦值URL模板,這也是共同的,也是必須的,至于約束URL模板的條件是可以根據自己情況來定義的。在生成的同時框架會給路由對象賦值上【路由請求處理程序】用以作為銜接路由系統和框架的主體功能部分。
圖2
在路由定義好之后,我們便會把它注冊到系統框架中。
圖3
在路由對象注冊到系統框架中之后,這個時候如果有外部的請求的到達,這個時候路由系統會讓路由對象集合中每個路由對象對這個請求進行匹配,就如圖4一樣。
圖4
這個時候就是路由對象所要能做出的行為就是URL的匹配,根據什么來匹配?是根據在路由對象實例化的時候定義好的URL模板和條件,拿請求信息的URL和自身定義的URL模板進行匹配,假使沒有匹配成功則會返回Null,這個時候框架則會讓下一個路由對象來進行匹配直到有匹配的成功為止,如果這個時候匹配成功了路由則會生成一個【路由數據對象】。
路由數據對象也很重要,因為后續的框架功能部分都是使用它的,它也是整個路由系統的結晶,我們看下圖5
圖5
路由數據對象會保持一個生成它的路由對象的引用,然后是Values的是保存著路由對象在經過URL匹配后的值,分別表示著URL片段的名字和對應的URL真實值,而DataTokens則是在路由對象定義生成的時候直接帶過來的值,當然了路由請求處理程序也是由執行生成的路由對象帶來的。
在ASP.NET、ASP.NET MVC、ASP.NET Web API這些框架中路由系統都是遵循著上面的所述的這樣一個過程,只不過在不同的框架環境下使用的類型不同,做的處理也不太一樣,但是整體的流程是一致的,下面附上圖6說明了之間的類型的差異性,還有更多的細節就不一一展示了。
圖6
還有在Web API(WebHost)環境下路由顯示的是這樣實質的本質其實又是ASP.NET的路由系統在支持的,這個會在后面的Web API系列篇幅中講解。
下面簡單的演示一下在各種框架環境下的路由對象注冊,
ASP.NET:
RouteTable.Routes.MapPageRoute( "ASP.NETRoute", "ASP.NET MVC:
RouteTable.Routes.MapRoute( "ASP.NETMVCRoute", "ProductInfo/{action}/{id}", new { controller="Product",action="show",id=RouteParameter.Optional} );ASP.NET Web API(WEBHOST):
GlobalConfiguration.Configuration.Routes.MapHttpRoute( "WebAPIRoute", "api/{controller}/{id}", new { id = RouteParameter.Optional } );ASP.NET Web API(SELFHOST):
HttpSelfHostConfiguration configuration = new HttpSelfHostConfiguration("http://loacalhost/selfhost"); using (HttpSelfHostServer selfHostServer = new HttpSelfHostServer(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框架在不同的宿主環境下路由系統中所對應的對象類型是不同的,這里就先給大家介紹在SelfHost環境下的路由系統中的路由對象吧。
SelfHost宿主環境
Web API路由對象(System.Web.Http.Routing)
HttpRoute
// 摘要: // 表示自承載(即在 ASP.NET 之外承載)的路由類。 public class HttpRoute : IHttpRoute { public HttpRoute(string routeTemplate, HttpRouteValueDictionary defaults, HttpRouteValueDictionary constraints, HttpRouteValueDictionary dataTokens, HttpMessageHandler handler); public IDictionary<string, object> Constraints { get; } public IDictionary<string, object> DataTokens { get; } public IDictionary<string, object> Defaults { get; } public HttpMessageHandler Handler { get; } public string RouteTemplate { get; } public virtual IHttpRouteData GetRouteData(string virtualPathRoot, HttpRequestMessage request); public virtual IHttpVirtualPathData GetVirtualPath(HttpRequestMessage request, IDictionary<string, object> values); protected virtual bool ProcessConstraint(HttpRequestMessage request, object constraint, string parameterName, HttpRouteValueDictionary values, HttpRouteDirection routeDirection); }可以從上面的定義中看到HttpRoute對象就是代表著在Web API框架中的路由對象了,在HttpRoute類型定義的構造函數中的參數分別表示著路由模板、路由模板對應的默認值、路由匹配條件、注冊的路由附帶的值以及最后的Http請求處理程序,這幾個參數值也分別對應著HttpRoute類型中的幾個屬性,這個自行看一下就明白了。
Web API路由對象集合(System.Web.Http)
HttpRouteCollection
HttpRouteCollectionExtensions
我們先來看一下HttpRouteCollection類型的擴展類型HttpRouteCollectionExtensions吧
public static class HttpRouteCollectionExtensions { public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate); public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults); public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints); public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler); }這里大家可以對比上面的路由注冊時的代碼,就可以知道我們在路由集合 添加/注冊 路由的時候是由HttpRouteCollectionExtensions類型的擴展方法來進行操作的,這個時候我們再看一下方法參數最多的那個MapHttpRoute()方法的實現:
public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler) { if (routes == null) { throw System.Web.Http.Error.ArgumentNull("routes"); } HttpRouteValueDictionary dictionary = new HttpRouteValueDictionary(defaults); HttpRouteValueDictionary dictionary2 = new HttpRouteValueDictionary(constraints); IDictionary<string, object> dataTokens = null; HttpMessageHandler handler2 = handler; IHttpRoute route = routes.CreateRoute(routeTemplate, dictionary, dictionary2, dataTokens, handler2); routes.Add(name, route); return route; }這里大家就可以看到了,HttpRoute對象的創建操作和添加操作是在這擴展方法里執行的,現在我們就可以去看一下HttpRouteCollection類型的定義了,看一下如何創建的IHttpRoute對象:
public class HttpRouteCollection : ICollection<IHttpRoute>, IEnumerable<IHttpRoute>, IEnumerable, IDisposable { public HttpRouteCollection(); public HttpRouteCollection(string virtualPathRoot); public virtual int Count { get; } public virtual bool IsReadOnly { get; } public virtual string VirtualPathRoot { get; } public virtual void Add(string name, IHttpRoute route); public IHttpRoute CreateRoute(string routeTemplate, object defaults, object constraints); public IHttpRoute CreateRoute(string routeTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens); public virtual IHttpRoute CreateRoute(string routeTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens, HttpMessageHandler handler); public virtual IHttpR
新聞熱點
疑難解答