当前位置:编程学习 > asp >>

ASP.NET路由系统实现原理:HttpHandler的动态映射

我们知道一个请求最终通过一个具体的HttpHandler进行处理,而我们熟悉的用于表示一个Web页面的Page对象就是一个HttpHandler,被用于处理基于某个.aspx文件的请求。我们可以通过HttpHandler的动态映射来实现请求地址与物理文件路径之间的分离。实际上ASP.NET路由系统就是采用了这样的实现原理。如下图所示,ASP.NET路由系统通过一个注册到当前应用的自定义HttpModule对所有的请求进行拦截,并通过对请求的分析为之动态匹配一个用于处理它的HttpHandler。HttpHandler对请求进行处理后将相应的结果写入HTTP回复以实现对请求的相应。 

clip_image002 

目录
一、UrlRoutingModule
一、UrlRoutingModule
二、PageRouteHandler V.S. MvcRouteHandler
三、ASP.NET路由系统扩展
        实例演示:通过自定义Route对ASP.NET路由系统进行扩展
上图所示的作为请求拦截器的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: }

三、 ASP.NET路由系统扩展
到此为止我们已经对ASP.NET的路由系统的实现进行了详细介绍,总的来说,整个路由系统是通过对HttpHandler的动态注册的方式来实现的。具体来说,UrlRoutingModule通过对代表Web应用的HttpApplication的PostResolveRequestCache事件的注册实现了对请求的拦截。对于被拦截的请求,UrlRoutingModule利用注册的路由表对其进行匹配和解析,进而得到一个包含所有路由信息的RouteData对象。最终借助该对象的RouteHandler创建出相应的HttpHandler映射到当前请求。从可扩展性的角度来讲,我们可以通过如下三种方式来实现我们需要的路由方式。
• 通过集成抽象类RouteBase创建自定义Route定制路由逻辑。
• 通过实现接口IRouteHandler创建自定义RouteHandler定制HttpHandler提供机制。
• 通过实现IHttpHandler创建自定义HttpHandler来对请求处理。
实例演示:通过自定义Route对ASP.NET路由系统进行扩展

补充:Web开发 , ASP.Net ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,