<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        淺析ASP.NET路由模型工作原理

        來源:懂視網 責編:小采 時間:2020-11-27 22:37:51
        文檔

        淺析ASP.NET路由模型工作原理

        淺析ASP.NET路由模型工作原理:ps:這是針對ASP.NET4.5版本的,好像在最新的5.0版本中加入了OWIN,徹底解耦了和Web服務器的耦合,我還沒有研究過,不敢妄言4.5的模型適用5.0。 action*0x1:大話ASP.NET模型 首先我們先來了解下一個請求的悲歡離合的命運,看看它的一生中所走過的蜿蜒曲折的
        推薦度:
        導讀淺析ASP.NET路由模型工作原理:ps:這是針對ASP.NET4.5版本的,好像在最新的5.0版本中加入了OWIN,徹底解耦了和Web服務器的耦合,我還沒有研究過,不敢妄言4.5的模型適用5.0。 action*0x1:大話ASP.NET模型 首先我們先來了解下一個請求的悲歡離合的命運,看看它的一生中所走過的蜿蜒曲折的

        ps:這是針對ASP.NET4.5版本的,好像在最新的5.0版本中加入了OWIN,徹底解耦了和Web服務器的耦合,我還沒有研究過,不敢妄言4.5的模型適用5.0。

        action*0x1:大話ASP.NET模型

        首先我們先來了解下一個請求的悲歡離合的命運,看看它的一生中所走過的蜿蜒曲折的道路。如下圖所示:

        在如上所示的風光旖旎的畫卷中,我們可以看到一個“請求”從客戶端瀏覽器出發,經歷千山萬水到達服務器,服務器的內核模塊的HTTP.SYS熱情款待了它,對它進行簡單的修飾之后,就和它依依惜別了,因為HTTP.SYS知道它是一個有夢想的“請求”,它應該去它該去的地方,于是就把它送到了IIS。

        IIS是片神奇的土地,這里有一位偉大的神靈叫做inetinfo.exe,于是它便去神靈的居所W3SVC服務(windows服務)祈禱,希望能給他一些指示,神靈通過查閱天書(IIS的配置文件),知道了它不是一般的靜態文件,不能把它直接送回去,應該讓它去它的族人開辦的加工廠(即對應網站的工作進程中)好好修習一番。

        現任加工廠老大叫w3wp.exe,在IIS6以前是aspnet_wp.exe,其因為沒有管理好各個加工廠之間的地盤問題被罷免了(asp.net_wp.exe用一個進程寄宿所有的網站,用應用程序域進行分割的,結果導致網站之間相互影響),現任老大w3wp.exe通過一個網站一個進程的方式把問題解決了,因此順利上位。

        初入加工廠的“請求”拜訪了門衛asp.net_isapi.dll,門衛發現它是第一個過來的“請求”,于是為它打開了工廠的生產車間(即第一個請求到達時,啟動了asp.net運行的環境,后來的請求就可以直接進入這個環境里。),并請車間主任ISAPIRuntime來負責它,主任興高采烈的來歡迎它(即ISAPIRuntime調用ProcessRequest(簡稱PR)方法,訪問當前請求所在的ecb句柄),并讓土里土氣的它換上了統一服裝HttpWorkRequest(即把請求進行簡單的封裝),然后叫來班長HttpRuntime,讓班長安排它的工作。

        班長說:”車間里面有危險,你先穿上安全制服HttpContext?!保赐ㄟ^PR方法把HttpWorkRequest封裝成HttpContext),然后去組長宿舍(HttpApplicationFactory)準備叫一個組長(HttpApplication)來帶領它,結果發現還沒有組長,班長只好去招聘一個新組長。

        每一個組長都是經過嚴格訓練才能上崗的,先要熟讀入廠準則Global.asax(即先編譯Global.asax文件),再通過準則中Application_Start方法考驗(即調用Application_Start方法),如此這般方成為一代組長。每位新任組長第一件事就是把所有的車間模塊裝配好,并創建好車間管道(通過讀取配置文件,加載所有的IHttpModule,并調用他們的Init方法,一般init方法都是注冊管道事件,之后通過BuidStepManager方法,根據經典模式或者集成模式生成對應的StepManager)。

        新任組長見到“請求”,二話不說直接啟動車間管道,將其丟進去。穿著安全制服HttpContext的“請求”要依次通過管道中所有的關卡(asp.net管道模型),其中在第7個關卡之后,生成了IHttpHandler類型的對象,并在第11個關卡之后執行該對象的ProcessRequest方法處理請求,在這里“請求”得到完美的加工塑造,生成了HttpResponse,再通過剩下的管道,實現了夢想的請求就沿著原路返回了。上圖中第11、12個事件之間描述的是WebForm的Page對象處理請求的流程(即頁面生命周期)。

        至此,一個請求的跌宕起伏的人生就說完了,各位觀眾欲知路由模塊具體怎么發揮作用的,還請先捧個人場,右下角點個贊。

        action*0x2:路由模型解析

        通過上文我們知道組長HttpApplication對象會負責組裝所有的IHttpModule,它是如何加載的呢?我們觀察反編譯的代碼:

        private void InitModules()
        {
        HttpModuleCollection modules = RuntimeConfig.GetAppConfig().HttpModules.CreateModules();
        HttpModuleCollection other = this.CreateDynamicModules();
        modules.AppendCollection(other);
        this._moduleCollection = modules;
        this.InitModulesCommon();
        }

        RuntimeConfig.GetAppConfig().HttpModules.CreateModules();通過這行代碼,我們可以清楚的發現它讀取了運行時的配置文件,那么我們打開運行時的配置文件以觀究竟。


        果然在這里add了一個System.WebRouting.UrlRoutingModule類型。接下來我們再用反編譯工具看這個類型的源碼:

        如我們所料UrlRoutingModule實現了IHttpModule接口,我們看看它的Init方法干了些什么?

        protected virtual void Init(HttpApplication application)
        {
        if (application.Context.Items[_contextKey] == null)
        {
        application.Context.Items[_contextKey] = _contextKey;
        application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
        }
        }

        對第7個事件PostResolveRequestCache注冊方法OnApplicationPostResolveRequestCache,那么這個方法又是干啥的呢?

        public virtual void PostResolveRequestCache(HttpContextBase context)
        {
        RouteData routeData = this.RouteCollection.GetRouteData(context);//匹配路由,得到匹配結果RouteData。
        if (routeData != null)
        {
        IRouteHandler routeHandler = routeData.RouteHandler;
        if (routeHandler == null)
        {
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
        }
        if (!(routeHandler is StopRoutingHandler))
        {
        RequestContext requestContext = new RequestContext(context, routeData);
        context.Request.RequestContext = requestContext;
        IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);//獲取處理當前請求的IHttpHandler對象。
        if (httpHandler == null)
        {
        object[] args = new object[] { routeHandler.GetType() };
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), args));
        }
        if (httpHandler is UrlAuthFailureHandler)
        {
        if (!FormsAuthenticationModule.FormsAuthRequired)
        {
        throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3"));
        }
        UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
        }
        else
        {
        context.RemapHandler(httpHandler);//映射:用當前IHttpHandler對象處理請求。
        }
        }
        }
        }

        代碼已經加了注釋,3步走:匹配路由→獲取處理當前請求的IHttpHandler對象→映射:用當前IHttpHandler對象處理請求。之后會在第11、12個事件之間調用IHttpHandler對象的PR方法處理當前請求。

        我們再整理下思路:ASP.NET先注冊了UrlRoutingModule模塊,他就是一個實現了IHttpModule接口的類,其Init方法就是在第7個事件上注冊一個方法,該方法先匹配路由,如果匹配成功了,則用匹配結果RouteData中的IHttpHandler對象映射到當前上下文中,這樣在之后第11、12個事件之間就會調用這個IHttpHandler對象處理請求。

        那么問題來了,Route對象是什么時候注入進去的,IHttpHandler對象又是誰?

        還記得路由規則是怎么添加的嗎?如下面代碼所示:

        public class Global : System.Web.HttpApplication
        {
        protected void Application_Start(object sender, EventArgs e)
        {
        var defaults = new RouteValueDictionary();
        defaults.Add("name", "*");
        //方式一:
        //通過RouteTable的靜態對象Routes新增一個Route類型的對象。
        RouteTable.Routes.Add("app", new Route("app/{name}", defaults, new MyRouteHandler()));
        //方式二:
        //通過RouteTable的靜態對象Routes的擴展方法新增一個路由規則。
        RouteTable.Routes.MapPageRoute("default", "app/{name}", "~/WebForm1.aspx", false, defaults);
        }
        } 

        這是我們經常用的兩種方式添加路由規則,方式一中有我們自己編寫的MyRouteHandler類型的實例作為參數,其實就是通過IRouteHandler接口返回一個IHttpHandler對象。

        /// <summary>
        /// 實現了IRouteHandler接口的類型
        /// </summary>
        internal class MyRouteHandler : IRouteHandler
        {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
        //返回一個Page對象,用于處理請求。
        return new WebForm1();
        }
        } 

        其實這兩種方式沒有本質上的區別,因為方式二中路由規則參數都會實例化一個Route對象的。

        我們分析方式二的源代碼:

        public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens)
        {
        if (routeUrl == null)
        {
        throw new ArgumentNullException("routeUrl");
        }
        Route item = new Route(routeUrl, defaults, constraints, dataTokens, new PageRouteHandler(physicalFile, checkPhysicalUrlAccess));
        this.Add(routeName, item);
        return item;
        } 

        發現所有的路由規則參數都用來實例化一個Route對象了,其中參數physicalFile和checkPhysicalUrlAccess用來實例化PageRouteHandler對象了,其源碼如下:

        public class PageRouteHandler : IRouteHandler
        {
        } 

        這是一個實現了IRouteHandler接口的類型,而這個接口只有一個作用就是返回IHttpHandler對象,源碼如下:

        [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
        public interface IRouteHandler
        {
        // Methods
        IHttpHandler GetHttpHandler(RequestContext requestContext);
        }

        到這里我們的疑問就解開了,原來我們注冊的路由規則都實例化成了Route對象,Route的GetRouteData方法用來匹配路由,路由規則中的physicalFile和checkPhysicalUrlAccess用來實例化一個IHttpHandler實例,用來處理請求。

        總結:ASP.NET的路由模型如下圖所示

        有關ASP.NET路由模型工作原理小編就給大家介紹到這里,希望對大家有所幫助!

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        淺析ASP.NET路由模型工作原理

        淺析ASP.NET路由模型工作原理:ps:這是針對ASP.NET4.5版本的,好像在最新的5.0版本中加入了OWIN,徹底解耦了和Web服務器的耦合,我還沒有研究過,不敢妄言4.5的模型適用5.0。 action*0x1:大話ASP.NET模型 首先我們先來了解下一個請求的悲歡離合的命運,看看它的一生中所走過的蜿蜒曲折的
        推薦度:
        標簽: 原理 路由 模型
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲爆乳无码专区www| 一区二区免费在线观看| 亚洲国产日韩在线| 麻豆安全免费网址入口| 国产电影午夜成年免费视频| 亚洲人成人无码网www国产| 亚洲第一页在线播放| aa午夜免费剧场| 国产成人青青热久免费精品| 久久狠狠高潮亚洲精品| 美女18一级毛片免费看| 国产免费的野战视频| 亚洲日韩亚洲另类激情文学| 最近的中文字幕大全免费8| 亚洲精品国产福利一二区| eeuss在线兵区免费观看| 亚洲国产一成人久久精品| 午夜免费国产体验区免费的| 亚洲欧洲中文日韩久久AV乱码| 国产一级黄片儿免费看| 亚洲AV日韩精品一区二区三区| 亚洲一区二区观看播放| 91成人免费观看网站| 中国china体内裑精亚洲日本| 黄色成人免费网站| 亚洲精华国产精华精华液网站| 免费一级毛片一级毛片aa| 337p日本欧洲亚洲大胆人人| 午夜视频免费观看| 亚洲综合色区中文字幕| 亚洲高清中文字幕免费| 亚洲av无码久久忘忧草| 99久久99这里只有免费费精品 | 美女被艹免费视频| 在线观看亚洲天天一三视| A级毛片成人网站免费看| 亚洲午夜av影院| 久久久久久噜噜精品免费直播 | 亚洲中文精品久久久久久不卡| 又粗又硬又黄又爽的免费视频| 久久久久免费精品国产小说|