<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      ASP.NET路由系統(tǒng)實現(xiàn)原理:HttpHandler的動態(tài)映射

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

      clip_image002

      目錄
      一、UrlRoutingModule
      一、UrlRoutingModule
      二、PageRouteHandler V.S. MvcRouteHandler
      三、ASP.NET路由系統(tǒng)擴展
              實例演示:通過自定義Route對ASP.NET路由系統(tǒng)進(jìn)行擴展

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

         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屬性,在默認(rèn)的情況下引用這通過RouteTable的靜態(tài)屬性Routes表示的全局路由表。針對請求的HttpHandler的動態(tài)映射就實現(xiàn)在OnApplicationPostResolveRequestCache方法中,具體的實現(xiàn)邏輯非常簡單:通過HttpApplication獲得但前的HTTP上下文,并將其作為參數(shù)調(diào)用RouteCollection的GetRouteData方法得到一個RouteData對象。

      通過RouteData的RouteHandler屬性可以得到一個實現(xiàn)了IRouteHandler的路由處理器對象,而調(diào)用后者的GetHttpHandler方法直接可以獲取對應(yīng)的HttpHandler對象,而我們需要映射到當(dāng)前請求的就是這么一個 HttpHandler。下面的代碼片斷基本上體現(xiàn)了定義在UrlRoutingModule的OnApplicationPostResolveRequestCache方法中的動態(tài)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

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

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

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

         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對象是通過調(diào)用RouteCollection的擴展方法MapRoute方法進(jìn)行注冊的,它對應(yīng)的RouteHandler是一個類型為MvcRouteHandler的對象。如下面的代碼片斷所示,MvcRouteHandler用于獲取處理當(dāng)前請求的HttpHandler是一個MvcHandler對象。MvcHandler實現(xiàn)對Controller的激活、Action方法的執(zhí)行以及對請求的相應(yīng),毫不夸張地說,整個MVC框架實現(xiàn)在MvcHandler之中。

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

      三、 ASP.NET路由系統(tǒng)擴展

      到此為止我們已經(jīng)對ASP.NET的路由系統(tǒng)的實現(xiàn)進(jìn)行了詳細(xì)介紹,總的來說,整個路由系統(tǒng)是通過對HttpHandler的動態(tài)注冊的方式來實現(xiàn)的。具體來說,UrlRoutingModule通過對代表Web應(yīng)用的HttpApplication的PostResolveRequestCache事件的注冊實現(xiàn)了對請求的攔截。對于被攔截的請求,UrlRoutingModule利用注冊的路由表對其進(jìn)行匹配和解析,進(jìn)而得到一個包含所有路由信息的RouteData對象。最終借助該對象的RouteHandler創(chuàng)建出相應(yīng)的HttpHandler映射到當(dāng)前請求。從可擴展性的角度來講,我們可以通過如下三種方式來實現(xiàn)我們需要的路由方式。

      • 通過集成抽象類RouteBase創(chuàng)建自定義Route定制路由邏輯。
      • 通過實現(xiàn)接口IRouteHandler創(chuàng)建自定義RouteHandler定制HttpHandler提供機制。
      • 通過實現(xiàn)IHttpHandler創(chuàng)建自定義HttpHandler來對請求處理。

      實例演示:通過自定義Route對ASP.NET路由系統(tǒng)進(jìn)行擴展

      定義在ASP.NET路由系統(tǒng)中默認(rèn)的路由類型Route建立了定義成文本模板的URL模式與某個物理文件之間的映射,如果我們對WCF REST有一定的了解,應(yīng)該知道其中也有類似的實現(xiàn)。具體來說,WCF REST借助于System.UriTemplate這個對象實現(xiàn)了同樣定義成某個文本模板的URI模式與目標(biāo)操作之間的映射。篇幅所限,我們不能對WCF REST的UriTemplate作詳細(xì)的介紹,有興趣的讀者可以參考《UriTemplate、UriTemplateTable與WebHttpDispatchOperationSelector》。[源代碼從這里下載]

      我們創(chuàng)建一個新的ASP.NET Web應(yīng)用,并且添加針對程序集System.ServiceModel.dll的引用(UriTemplate定義在該程序集中),然后創(chuàng)建如下一個針對UriTemplate的路由類型UriTemplateRoute。

         1: public class UriTemplateRoute:RouteBase
         2: {
         3:     public UriTemplate   UriTemplate { get; private set; }
         4:     public IRouteHandler     RouteHandler { get; private set; }
         5:     public RouteValueDictionary     DataTokens { get; private set; }
         6:  
         7:     public UriTemplateRoute(string template, string physicalPath, object dataTokens = null)
         8:     {
         9:         this.UriTemplate = new UriTemplate(template);
        10:         this.RouteHandler = new PageRouteHandler(physicalPath);
        11:         if (null != dataTokens)
        12:         {
        13:             this.DataTokens = new RouteValueDictionary(dataTokens);
        14:         }
        15:         else
        16:         {
        17:             this.DataTokens = new RouteValueDictionary();
        18:         }
        19:     }
        20:     public override RouteData GetRouteData(HttpContextBase httpContext)
        21:     {
        22:         Uri uri = httpContext.Request.Url;
        23:         Uri baseAddress = new Uri(string.Format("{0}://{1}", uri.Scheme, uri.Authority));
        24:         UriTemplateMatch match = this.UriTemplate.Match(baseAddress, uri);
        25:         if (null == match)
        26:         {
        27:             return null;
        28:         }
        29:         RouteData routeData = new RouteData();
        30:         routeData.RouteHandler = this.RouteHandler;
        31:         routeData.Route = this;
        32:         foreach (string name in match.BoundVariables.Keys)
        33:         { 
        34:             routeData.Values.Add(name,match.BoundVariables[name]);
        35:         }
        36:         foreach (var token in this.DataTokens)
        37:         {
        38:             routeData.DataTokens.Add(token.Key, token.Value);
        39:         }
        40:         return routeData;
        41:     }
        42:     public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        43:     {
        44:         Uri uri = requestContext.HttpContext.Request.Url;
        45:         Uri baseAddress = new Uri(string.Format("{0}://{1}", uri.Scheme, uri.Authority));
        46:         Dictionary<string, string> variables = new Dictionary<string, string>();
        47:         foreach(var item in values)
        48:         {
        49:             variables.Add(item.Key, item.Value.ToString());
        50:         }
        51:  
        52:         //確定段變量是否被提供
        53:         foreach (var name in this.UriTemplate.PathSegmentVariableNames)
        54:         { 
        55:             if(!this.UriTemplate.Defaults.Keys.Any(key=> string.Compare(name,key,true) == 0) && 
        56:                 !values.Keys.Any(key=> string.Compare(name,key,true) == 0))
        57:             {
        58:                 return null;
        59:             }
        60:         }
        61:         //確定查詢變量是否被提供
        62:         foreach (var name in this.UriTemplate.QueryValueVariableNames)
        63:         { 
        64:             if(!this.UriTemplate.Defaults.Keys.Any(key=> string.Compare(name,key,true) == 0) && 
        65:                 !values.Keys.Any(key=> string.Compare(name,key,true) == 0))
        66:             {
        67:                 return null;
        68:             }
        69:         }
        70:  
        71:         Uri virtualPath = this.UriTemplate.BindByName(baseAddress, variables);
        72:         string strVirtualPath = virtualPath.ToString().ToLower().Replace(baseAddress.ToString().ToLower(),"");
        73:         VirtualPathData virtualPathData =  new VirtualPathData(this, strVirtualPath);
        74:         foreach (var token in this.DataTokens)
        75:         {
        76:             virtualPathData.DataTokens.Add(token.Key, token.Value);
        77:         }
        78:         return virtualPathData;
        79:     }
        80: }

      如上面的代碼片斷所示,UriTemplateRoute具有UriTemplate、DataTokens和RouteHandler三個只讀屬性,前兩個通過構(gòu)造函數(shù)的參數(shù)進(jìn)行初始化,后者則是在構(gòu)造函數(shù)中創(chuàng)建的PageRouteHandler對象。

      用于對入棧請求進(jìn)行匹配判斷的GetRouteData方法中,我們解析出基于應(yīng)用的基地址并量連同請求地址作為參數(shù)調(diào)用UriTemplate的Match方法,如果返回的UriTemplateMatch對象不為Null,則意味著URL模板的模式與請求地址匹配。在匹配的情況下我們創(chuàng)建并返回相應(yīng)的RouteData對象,否則直接返回Null。

      在用于生成出棧URL的GetVirtualPath方法中,我們通過定義在URL模板中的模板(包括變量名包含在屬性PathSegmentVariableNames的路徑段變量和包含在QueryValueVariableNames屬性的查詢變量)是否在提供的RouteValueDictionary字段或者默認(rèn)變量列表(通過屬性Defaults表示)從判斷URL模板是否與提供的變量列表匹配。在匹配的情況下通過調(diào)用UriTemplate的BindByName方法得到一個完整的Uri。由于該方法返回的是相對路徑,所以我們需要將應(yīng)用基地址剔除并最終創(chuàng)建并返回一個VirtualPathData對象。如果不匹配,則直接返回Null。

      在創(chuàng)建的Global.asax文件中我們采用如下的代碼對我們自定義的UriTemplateRoute進(jìn)行注冊,選用的場景還是我們上面采用的天氣預(yù)報的例子。我個人具有基于UriTemplate的URI模板比針對Route的URL模板更好用,其中一點就是它在定義默認(rèn)值方法更為直接。如下面的代碼片斷所示,我們直接將默認(rèn)值定義在模板中(("{areacode=010}/{days=2})。

         1: public class Global : System.Web.HttpApplication
         2: {
         3:     protected void Application_Start(object sender, EventArgs e)
         4:     {
         5:         UriTemplateRoute route = new UriTemplateRoute("{areacode=010}/{days=2}",
         6:             "~/Weather.aspx", new { defualtCity = "BeiJing", defaultDays = 2});
         7:         RouteTable.Routes.Add("default", route);
         8:     }
         9: }

      在注冊的路由對應(yīng)的目標(biāo)頁面Weather.aspx的后臺代碼中,我們定義了如下一個GenerateUrl根據(jù)指定的區(qū)號(areacode)和預(yù)報天數(shù)(days)創(chuàng)建一個Url,而Url的生成直接通過調(diào)用RouteTable的Routes屬性的GetVirtualPathData方法完成。生成的URL連同當(dāng)前頁面的RouteData的屬性通過如下所示的HTML輸出來。

         1: <body>
         2:     <form id="form1" runat="server">
         3:     <div>
         4:         <table>
         5:             <tr>
         6:                 <td>Router:</td>
         7:                 <td><%=RouteData.Route != null? RouteData.Route.GetType().FullName:"" %></td>
         8:             </tr>
         9:             <tr>
        10:                 <td>RouteHandler:</td>
        11:                 <td><%=RouteData.RouteHandler != null? RouteData.RouteHandler.GetType().FullName:"" %></td>
        12:             </tr>
        13:             <tr>
        14:                 <td>Values:</td>
        15:                 <td>
        16:                     <ul>
        17:                         <%foreach (var variable in RouteData.Values)
        18:                           {%>
        19:                         <li><%=variable.Key%>=<%=variable.Value%></li>
        20:                         <% }%>
        21:                     </ul>
        22:                 </td>
        23:             </tr>
        24:             <tr>
        25:                 <td>DataTokens:</td>
        26:                 <td>
        27:                     <ul>
        28:                         <%foreach (var variable in RouteData.DataTokens)
        29:                           {%>
        30:                         <li><%=variable.Key%>=<%=variable.Value%></li>
        31:                         <% }%>
        32:                     </ul>
        33:                 </td>
        34:             </tr>
        35:              <tr>
        36:                 <td>Generated Url:</td>
        37:                 <td>
        38:                     <%=GenerateUrl("0512",3)%>
        39:                 </td>
        40:             </tr>
        41:         </table>
        42:     </div>
        43:     </form>
        44: </body>

      由于注冊的URL模板所包含的段均由具有默認(rèn)值的變量構(gòu)成,所以當(dāng)我們請求根地址時,會自動路由到Weather.aspx。下圖是我們在瀏覽器訪問應(yīng)用根目錄的截圖,上面顯示了我們注冊的UriTemplateRoute生成的RouteData的信息和生成URL(/0512/3)。

      clip_image004

      posted @ 2012-03-28 08:15  Artech  閱讀(12763)  評論(14)    收藏  舉報
      主站蜘蛛池模板: av综合亚洲一区二区| 91中文字幕在线一区| 宝坻区| 无码免费大香伊蕉在人线国产| 九九热在线观看视频精品| 老司机亚洲精品一区二区| 99在线国内在线视频22| 丰满岳乱妇久久久| 久久99久久99精品免视看动漫| 久久精品国产亚洲av天海翼| 天天躁日日躁狠狠躁一区| 色偷偷www.8888在线观看| 无码va在线观看| 国产免费午夜福利在线观看| 亚洲精品一区二区美女| 亚洲香蕉视频天天爽| 久久久久久国产精品美女| 欧美不卡无线在线一二三区观| 九九综合九色综合网站| 亚洲综合久久精品国产高清| 久久香蕉国产线看观看怡红院妓院| 少妇高潮灌满白浆毛片免费看| 亚洲人成网站在线播放2019| 婷婷色爱区综合五月激情韩国| 务川| 成人午夜免费无码视频在线观看| 国产成人亚洲欧美二区综合| 2019亚洲午夜无码天堂| 精品综合久久久久久97| 推油少妇久久99久久99久久| 精品一区二区亚洲国产| 亚洲国产午夜理论片不卡| 成人av午夜在线观看| 国产女同一区二区在线| 中文字幕日韩一区二区不卡| 久久亚洲精品中文字幕波多野结衣| 欧美偷窥清纯综合图区| 亚洲另类激情专区小说图片| 无码中文字幕av免费放| 99麻豆久久精品一区二区| 亚洲日韩性欧美中文字幕|