. UrlRouting的理解

 根据对Http Runtime和Http Pipeline的分析,我们知道一个ASP.NET应用程序可以有多个HttpModuel,但是只能有一个HttpHandler,并且通过这个 HttpHandler的BeginProcessRequest(或ProcessRequest)来处理并返回请求,前面的章节将到了再 MapHttpHandler这个周期将会根据请求的URL来查询对应的HttpHandler,那么它是如何查找的呢?

风景

一起我们在做自定义HttpHandler的时候,需要执行URL以及扩展名匹配规则,然后查找HttpHandler的时候就是根据相应的规则来查找哪个HttpHandler可以使用。另一方面我们本系列教材讲的MVC就是通过注册路由(Route)来匹配到对应的Controller和 Action上的,例如Global.asax里的代码:

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

但是在匹配这个之前,MVC首先要接管请求才能处理,也就是说我们要有对应MVC的HttpHandler(后面知道它的名字叫 MvcHandler)被MapRequestHandler周期的处理引擎查找到并且应用上才行,然后后面才能由 Controller/Action执行。另外一方面,由于该URL地址没有扩展名,所以无法进入ASP.NET的RunTime,MVC2的实现方式是:注册通配符(*.*)映射到aspnet_ISPAI.dll,然后通过一个自定义的UrlRoutingModuel来匹配Route规则,再继续处理,但是MVC3的时候,匹配Route规则的处理机制集成到ASP.NET4.0里了,也就是今天我们这篇文章所要讲的主角(UrlRoutingModule)的处理机制。

先来看UrlRoutingModule的源码,无容置疑地这个类是继承于IHttpModule,首先看一下Init方法的代码:

protected virtual void Init(HttpApplication application) {  
      
    //////////////////////////////////////////////////////////////////   
    // Check if this module has been already addded  
    if (application.Context.Items[_contextKey] != null) {   
        return; // already added to the pipeline   
    }  
    application.Context.Items[_contextKey] = _contextKey;   
      
    // Ideally we would use the MapRequestHandler event.  However, MapRequestHandler is not available  
    // in II6 or IIS7 ISAPI Mode.  Instead, we use PostResolveRequestCache, which is the event immediately  
    // before MapRequestHandler.  This allows use to use one common codepath for all versions of IIS.   
    application.PostResolveRequestCache += OnApplicationPostResolveRequestCache;  
}

该代码在PostResolveRequestCache周期事件上添加了我们需要执行的方法,用于URL匹配规则的设置,但是为什么要在这个周期点上添加事件呢?看了注释,再结合我们前面对Pipeline的了解,释然了,要像动态注册自己的HttpHandler,那就需要在 MapRequestHandler之前进行注册自己的规则(因为这个周期点就是做这个事情的),但由于IIS6不支持这个事件,所以为了能让IIS6也能运行MVC3,所以我们需要在这个周期之前的PostResolveRequestCache的事件点上去注册我们的规则,也许如果IIS6被微软废弃以后,就会将这个事件添加到真正的开始点MapRequestHandler上哦。

我们继续来看注册该事件的OnApplicationPostResolveRequestCache方法的代码:

public virtual void PostResolveRequestCache(HttpContextBase context) {   
    // Match the incoming URL against the route table  
    RouteData routeData = RouteCollection.GetRouteData(context);  
      
    // Do nothing if no route found   
    if (routeData == null) {  
        return;   
    }   
      
    // If a route was found, get an IHttpHandler from the route's RouteHandler   
    IRouteHandler routeHandler = routeData.RouteHandler;  
    if (routeHandler == null) {  
        throw new InvalidOperationException(  
            String.Format(   
                CultureInfo.CurrentUICulture,  
                SR.GetString(SR.UrlRoutingModule_NoRouteHandler)));   
    }   
      
    // This is a special IRouteHandler that tells the routing module to stop processing   
    // routes and to let the fallback handler handle the request.  
    if (routeHandler is StopRoutingHandler) {  
        return;  
    }   
      
    RequestContext requestContext = new RequestContext(context, routeData);   
       
    // Dev10 766875    Adding RouteData to HttpContext  
    context.Request.RequestContext = requestContext;   
      
    IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);  
    if (httpHandler == null) {  
        throw new InvalidOperationException(   
            String.Format(  
                CultureInfo.CurrentUICulture,   
                SR.GetString(SR.UrlRoutingModule_NoHttpHandler),   
                routeHandler.GetType()));  
    }   
      
    if (httpHandler is UrlAuthFailureHandler) {  
        if (FormsAuthenticationModule.FormsAuthRequired) {  
            UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);   
            return;  
        }   
        else {   
            throw new HttpException(401, SR.GetString(SR.Assess_Denied_Description3));  
        }   
    }  
      
    // Remap IIS7 to our handler  
    context.RemapHandler(httpHandler);   
}




转载请注明:http://www.shhjfk.com/yyzj/yyzj/14.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了