ASP.NET 源碼分析之Routing

來源:互聯網
上載者:User
ASP.NET MVC(以下簡稱MVC)中的表單路由在目前的版本中(RC1)實際上使用的是System.Web.Routing(.NET SP1)。
關於System.Web.Routing的單獨詳解可以參看:http://msdn.microsoft.com/zh-cn/magazine/2009.01.extremeaspnet.aspx 的“使用 ASP.NET Web Form路由”。這裡主要是配合ASP.NET MVC再來分析分析。

MVC路由和以前我們在ASP.NET中進行URL重寫(http://msdn.microsoft.com/zh-cn/library/ms972974.aspx)類似的是都是通過HTTP模組來實現的。至於兩者的區別可以參看:使用 ASP.NET Web Form路由(http://msdn.microsoft.com/zh-cn/magazine/2009.01.extremeaspnet.aspx)。

核心代碼:System.Web.Routing命名空間的UrlRoutingModule以及相關的類。

        protected virtual void Init(HttpApplication application)
        {
            //BeginReques、AuthenticateRequest、AuthorizeRequestCache、ResolveRequestCache事件發生之後
            //PostResolveRequestCache事件正好是在未給HttpContent設定Http處理常式的前一個事件
            application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
            //PostMapRequestHandler事件發生時,會為HttpContent設定Http處理常式,所以在該事件中設定自訂Http處理常式最合適不過了
            application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
        }

        private void OnApplicationPostMapRequestHandler(object sender, EventArgs e)
        {
            //將當前HttpContent封裝成HttpContextWrapper對象並賦給HttpContextWrapper的父類HttpContextBase
            HttpContextBase context = new System.Web.HttpContextWrapper(((HttpApplication) sender).Context);
            this.PostMapRequestHandler(context);
        }

        private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
        {
            HttpContextBase context = new System.Web.HttpContextWrapper(((HttpApplication) sender).Context);
            this.PostResolveRequestCache(context);
        }

        public virtual void PostMapRequestHandler(HttpContextBase context)
        {
            //如果PostResolveRequestCache事件處理方法中設定了路由資訊,則根據路由中的配置重寫URL,並將HTTP處理常式設定為路由中的配置中的HTTP處理常式。
            //在MVC中,HTTP處理常式設定為MvcHandler對象(註:MvcHandler對象的RequestContext屬性已經被賦值為System.Web.Routing.RequestContext對象)
            RequestData data = (RequestData) context.Items[_requestDataKey];
            if (data != null)
            {
                context.RewritePath(data.OriginalPath);
                context.Handler = data.HttpHandler;
            }
        }

        public virtual void PostResolveRequestCache(HttpContextBase context)
        {
            //this.RouteCollection 是 UrlRoutingModule的公用屬性,其傳回型別就是System.Web.Routing.RouteCollection
            //this.RouteCollection 屬性的get方法中,通過RouteTable類的靜態屬性Routes返回一個單件的RouteCollection(雖然表面上看RouteTable不象使用單件模式,由於路由表是全域的,所以還是單件。)
            //調用RouteCollection對象的GetRouteData(HttpContextBase httpContext)方法。該方法遍曆自身,搜尋時候與URL匹配的RouteData,如果不匹配返回null
            //如果要瞭解具體的搜尋步驟,可以查看RouteCollection類的GetRouteData方法以及Route類的GetRouteData方法
            RouteData routeData = this.RouteCollection.GetRouteData(context);
            //如果搜尋到匹配的路由配置
            if (routeData != null)
            {
                //首先檢查路由配置中是否設定了路由處理常式(註:路由處理常式中包含HTTP處理常式),在MVC中RouteData的RouteHandler屬性返回的是MvcRouteHandler對象
                IRouteHandler routeHandler = routeData.RouteHandler;
                if (routeHandler == null)
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));
                }
                //StopRoutingHandler類阻止路由處理特定請求
                if (!(routeHandler is StopRoutingHandler))
                {
                    //RequestContext類其實就是將一個HttpContextBase對象和一個RouteData封裝在一起
                    RequestContext requestContext = new RequestContext(context, routeData);
                    //這裡通過路由處理常式的GetHttpHandler方法擷取HTTP處理常式,在MVC中IRouteHandler的GetHttpHandler方法返回的是MvcHandler對象,並將requestContext作為參數傳給了該對象
                    IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
                    if (httpHandler == null)
                    {
                        throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));
                    }
                    //執行個體化一個RequestData對象來儲存請求路徑和HTTP處理常式,並將之存入當前HttpContent的Item集合中
                    context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler };
                    //MVC 在 web.config 為 IIS 7.0 加了如下配置:
                    //<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
                    //轉:這是為了使路由引擎能夠在 IIS 7.0 中進行路由所採用的一種簡單解決方案。實際上 UrlRouting 模組會將傳入 URL 重寫為 ~/UrlRouting.axd,而它會將 URL 重寫回原始的傳入 URL。
                    context.RewritePath("~/UrlRouting.axd");
                }
            }
        }
        public RouteCollection RouteCollection
        {
            get
            {
                if (this._routeCollection == null)
                {
                    this._routeCollection = RouteTable.Routes;
                }
                return this._routeCollection;
            }
            set
            {
                this._routeCollection = value;
            }
        }
        private class RequestData
        {
            [CompilerGenerated]
            private IHttpHandler _HttpHandler;
            [CompilerGenerated]
            private string _OriginalPath;

            public IHttpHandler HttpHandler
            {
                [CompilerGenerated]
                get
                {
                    return this._HttpHandler;
                }
                [CompilerGenerated]
                set
                {
                    this._HttpHandler = value;
                }
            }

            public string OriginalPath
            {
                [CompilerGenerated]
                get
                {
                    return this._OriginalPath;
                }
                [CompilerGenerated]
                set
                {
                    this._OriginalPath = value;
                }
            }
        }



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.