程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> MVC系列(8) UrlRouting的理解

MVC系列(8) UrlRouting的理解

編輯:關於ASP.NET

根據對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);   
}

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