程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> ASP.NET路由系統實現原理:HttpHandler的動態映射

ASP.NET路由系統實現原理:HttpHandler的動態映射

編輯:關於ASP.NET

我們知道一個請求最終通過一個具體的HttpHandler進行處理,而我們熟悉的用於表示一個Web頁面的Page對象就是一個HttpHandler,被用於處理基於某個.aspx文件的請求。我們可以通過HttpHandler的動態映射來實現請求地址與物理文件路徑之間的分離。實際上ASP.NET路由系統就是采用了這樣的實現原理。如下圖所示,ASP.NET路由系統通過一個注冊到當前應用的自定義HttpModule對所有的請求進行攔截,並通過對請求的分析為之動態匹配一個用於處理它的HttpHandler。HttpHandler對請求進行處理後將相應的結果寫入HTTP回復以實現對請求的相應。

上圖所示的作為請求攔截器的HttpModule類型為UrlRoutingModule。如下面的代碼片斷所示,UrlRoutingModule對請求的攔截是通過注冊表示當前應用的HttpApplication的PostResolveRequestCache事件實現的。

   1: public class UrlRoutingModule : IHttpModule
2: {
3: //其他成員
4: public RouteCollection RouteCollection { get; set; }
5: public void Init(HttpApplication context)
6: {
7: context.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
8:
9: }
10: private void OnApplicationPostResolveRequestCache(object sender, EventArgs e);
11: }

UrlRoutingModule具有一個類型為RouteCollection的RouteCollection屬性,在默認的情況下引用這通過RouteTable的靜態屬性Routes表示的全局路由表。針對請求的HttpHandler的動態映射就實現在OnApplicationPostResolveRequestCache方法中,具體的實現邏輯非常簡單:通過HttpApplication獲得但前的HTTP上下文,並將其作為參數調用RouteCollection的GetRouteData方法得到一個RouteData對象。

通過RouteData的RouteHandler屬性可以得到一個實現了IRouteHandler的路由處理器對象,而調用後者的GetHttpHandler方法直接可以獲取對應的HttpHandler對象,而我們需要映射到當前請求的就是這麼一個 HttpHandler。下面的代碼片斷基本上體現了定義在UrlRoutingModule的OnApplicationPostResolveRequestCache方法中的動態HttpHandler映射邏輯。

   1: public class UrlRoutingModule : IHttpModule
2: {
3: //其他成員
4: private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
5: {
6: HttpContext context = ((HttpApplication)sender).Context;
7: HttpContextBase contextWrapper = new HttpContextWrapper(context);
8: RouteData routeData = this.RouteCollection.GetRouteData(contextWrapper);
9: RequestContext requestContext = new RequestContext(contextWrapper, routeData);
10: IHttpHandler handler = routeData.RouteHandler.GetHttpHandler(requestContext);
11: context.RemapHandler(handler);
12: }
13: }

二、 PageRouteHandler V.S. MvcRouteHandler

通過前面的介紹我們知道對於調用RouteCollection的GetRouteData獲得的RouteData對象,其RouteHandler來源於匹配的Route對象。對於通過調用RouteCollection的MapPageRoute方法注冊的Route來說,它的RouteHandler是一個類型為PageRouteHandler對象。

由於調用MapPageRoute方法的目的在於實現請求地址與某個.aspx頁面文件之間的映射,所以我們最終還是要創建的Page對象還處理相應的請求,所以PageRouteHandler的GetHttpHandler方法最終返回的就是針對映射頁面文件路徑的Page對象。此外,MapPageRoute方法中還可以控制是否對物理文件地址實施授權,而授權在返回Page對象之前進行。

定義在PageRouteHandler中的HttpHandler獲取邏輯基本上體現在如下的代碼片斷中,兩個屬性VirtualPath和CheckPhysicalUrlAccess表示頁面文件的地址和是否需要對物理文件地址實施URL授權,它們在構造函數中被初始化,而最終來源於調用RouteCollection的MapPageRoute方法傳入的參數。

   1: public class PageRouteHandler : IRouteHandler
2: {
3: public bool CheckPhysicalUrlAccess { get; private set; }
4: public string VirtualPath { get; private set; }
5: public PageRouteHandler(string virtualPath, bool checkPhysicalUrlAccess)
6: {
7: this.VirtualPath = virtualPath;
8: this.CheckPhysicalUrlAccess = checkPhysicalUrlAccess;
9: }
10: public IHttpHandler GetHttpHandler(RequestContext requestContext)
11: {
12: if (this.CheckPhysicalUrlAccess)
13: {
14: //Check Physical Url Access
15: }
16: return (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath(this.VirtualPath, typeof(Page))
17: }
18: }

ASP.NET MVC的Route對象是通過調用RouteCollection的擴展方法MapRoute方法進行注冊的,它對應的RouteHandler是一個類型為MvcRouteHandler的對象。如下面的代碼片斷所示,MvcRouteHandler用於獲取處理當前請求的HttpHandler是一個MvcHandler對象。MvcHandler實現對Controller的激活、Action方法的執行以及對請求的相應,毫不誇張地說,整個MVC框架實現在MvcHandler之中。

   1: public class MvcRouteHandler : IRouteHandler
2: {
3: //其他成員
4: public IHttpHandler GetHttpHandler(RequestContext requestContext)
5: {
6: return new MvcHandler(requestContext)
7: }
8: }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved