最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2016年03月31日 11:25:05   作者:kexxxfeng  
很多人知道Asp.Net中路由怎么用的,卻不知道路由模型內(nèi)部的運(yùn)行原理,今天我就給大家吹下ASP.NET的路由模塊是如何工作的

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

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

首先我們先來了解下一個(gè)請(qǐng)求的悲歡離合的命運(yùn),看看它的一生中所走過的蜿蜒曲折的道路。如下圖所示:

在如上所示的風(fēng)光旖旎的畫卷中,我們可以看到一個(gè)“請(qǐng)求”從客戶端瀏覽器出發(fā),經(jīng)歷千山萬水到達(dá)服務(wù)器,服務(wù)器的內(nèi)核模塊的HTTP.SYS熱情款待了它,對(duì)它進(jìn)行簡單的修飾之后,就和它依依惜別了,因?yàn)镠TTP.SYS知道它是一個(gè)有夢(mèng)想的“請(qǐng)求”,它應(yīng)該去它該去的地方,于是就把它送到了IIS。

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

現(xiàn)任加工廠老大叫w3wp.exe,在IIS6以前是aspnet_wp.exe,其因?yàn)闆]有管理好各個(gè)加工廠之間的地盤問題被罷免了(asp.net_wp.exe用一個(gè)進(jìn)程寄宿所有的網(wǎng)站,用應(yīng)用程序域進(jìn)行分割的,結(jié)果導(dǎo)致網(wǎng)站之間相互影響),現(xiàn)任老大w3wp.exe通過一個(gè)網(wǎng)站一個(gè)進(jìn)程的方式把問題解決了,因此順利上位。

初入加工廠的“請(qǐng)求”拜訪了門衛(wèi)asp.net_isapi.dll,門衛(wèi)發(fā)現(xiàn)它是第一個(gè)過來的“請(qǐng)求”,于是為它打開了工廠的生產(chǎn)車間(即第一個(gè)請(qǐng)求到達(dá)時(shí),啟動(dòng)了asp.net運(yùn)行的環(huán)境,后來的請(qǐng)求就可以直接進(jìn)入這個(gè)環(huán)境里。),并請(qǐng)車間主任ISAPIRuntime來負(fù)責(zé)它,主任興高采烈的來歡迎它(即ISAPIRuntime調(diào)用ProcessRequest(簡稱PR)方法,訪問當(dāng)前請(qǐng)求所在的ecb句柄),并讓土里土氣的它換上了統(tǒng)一服裝HttpWorkRequest(即把請(qǐng)求進(jìn)行簡單的封裝),然后叫來班長HttpRuntime,讓班長安排它的工作。

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

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

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

至此,一個(gè)請(qǐng)求的跌宕起伏的人生就說完了,各位觀眾欲知路由模塊具體怎么發(fā)揮作用的,還請(qǐng)先捧個(gè)人場(chǎng),右下角點(diǎn)個(gè)贊。

action*0x2:路由模型解析

通過上文我們知道組長HttpApplication對(duì)象會(huì)負(fù)責(zé)組裝所有的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();通過這行代碼,我們可以清楚的發(fā)現(xiàn)它讀取了運(yùn)行時(shí)的配置文件,那么我們打開運(yùn)行時(shí)的配置文件以觀究竟。


果然在這里add了一個(gè)System.WebRouting.UrlRoutingModule類型。接下來我們?cè)儆梅淳幾g工具看這個(gè)類型的源碼:

如我們所料UrlRoutingModule實(shí)現(xiàn)了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);
}
}

對(duì)第7個(gè)事件PostResolveRequestCache注冊(cè)方法OnApplicationPostResolveRequestCache,那么這個(gè)方法又是干啥的呢?

public virtual void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = this.RouteCollection.GetRouteData(context);//匹配路由,得到匹配結(jié)果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);//獲取處理當(dāng)前請(qǐng)求的IHttpHandler對(duì)象。
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);//映射:用當(dāng)前IHttpHandler對(duì)象處理請(qǐng)求。
}
}
}
}

代碼已經(jīng)加了注釋,3步走:匹配路由→獲取處理當(dāng)前請(qǐng)求的IHttpHandler對(duì)象→映射:用當(dāng)前IHttpHandler對(duì)象處理請(qǐng)求。之后會(huì)在第11、12個(gè)事件之間調(diào)用IHttpHandler對(duì)象的PR方法處理當(dāng)前請(qǐng)求。

我們?cè)僬硐滤悸罚篈SP.NET先注冊(cè)了UrlRoutingModule模塊,他就是一個(gè)實(shí)現(xiàn)了IHttpModule接口的類,其Init方法就是在第7個(gè)事件上注冊(cè)一個(gè)方法,該方法先匹配路由,如果匹配成功了,則用匹配結(jié)果RouteData中的IHttpHandler對(duì)象映射到當(dāng)前上下文中,這樣在之后第11、12個(gè)事件之間就會(huì)調(diào)用這個(gè)IHttpHandler對(duì)象處理請(qǐng)求。

那么問題來了,Route對(duì)象是什么時(shí)候注入進(jìn)去的,IHttpHandler對(duì)象又是誰?

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

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

這是我們經(jīng)常用的兩種方式添加路由規(guī)則,方式一中有我們自己編寫的MyRouteHandler類型的實(shí)例作為參數(shù),其實(shí)就是通過IRouteHandler接口返回一個(gè)IHttpHandler對(duì)象。

/// <summary>
/// 實(shí)現(xiàn)了IRouteHandler接口的類型
/// </summary>
internal class MyRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
//返回一個(gè)Page對(duì)象,用于處理請(qǐng)求。
return new WebForm1();
}
} 

其實(shí)這兩種方式?jīng)]有本質(zhì)上的區(qū)別,因?yàn)榉绞蕉新酚梢?guī)則參數(shù)都會(huì)實(shí)例化一個(gè)Route對(duì)象的。

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

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;
} 

發(fā)現(xiàn)所有的路由規(guī)則參數(shù)都用來實(shí)例化一個(gè)Route對(duì)象了,其中參數(shù)physicalFile和checkPhysicalUrlAccess用來實(shí)例化PageRouteHandler對(duì)象了,其源碼如下:

public class PageRouteHandler : IRouteHandler
{
} 

這是一個(gè)實(shí)現(xiàn)了IRouteHandler接口的類型,而這個(gè)接口只有一個(gè)作用就是返回IHttpHandler對(duì)象,源碼如下:

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

到這里我們的疑問就解開了,原來我們注冊(cè)的路由規(guī)則都實(shí)例化成了Route對(duì)象,Route的GetRouteData方法用來匹配路由,路由規(guī)則中的physicalFile和checkPhysicalUrlAccess用來實(shí)例化一個(gè)IHttpHandler實(shí)例,用來處理請(qǐng)求。

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

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

相關(guān)文章

  • .NET(C#)連接各類數(shù)據(jù)庫代碼-集錦

    .NET(C#)連接各類數(shù)據(jù)庫代碼-集錦

    .NET(C#)連接各類數(shù)據(jù)庫代碼-集錦...
    2007-03-03
  • .net 刷新頁面后彈出重試框的解決方法

    .net 刷新頁面后彈出重試框的解決方法

    關(guān)閉模式窗口后,需要刷新父頁面,但是模式窗口關(guān)閉后,父頁面總是會(huì)彈出重試消息框,遇到此問題的朋友看下解決方法哈
    2013-04-04
  • .net core EF Core調(diào)用存儲(chǔ)過程的方式

    .net core EF Core調(diào)用存儲(chǔ)過程的方式

    這篇文章主要給大家介紹了關(guān)于.net core EF Core調(diào)用存儲(chǔ)過程的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用.net core EF Core具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • ASP.NET Core WebAPI實(shí)現(xiàn)本地化(單資源文件)

    ASP.NET Core WebAPI實(shí)現(xiàn)本地化(單資源文件)

    這篇文章主要介紹了ASP.NET Core WebAPI實(shí)現(xiàn)本地化(單資源文件),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • .Net 下區(qū)別使用 ByRef/ByVal 的重要性 分享

    .Net 下區(qū)別使用 ByRef/ByVal 的重要性 分享

    這篇文章介紹了.Net 下區(qū)別使用 ByRef/ByVal 的重要性,有需要的朋友可以參考一下
    2013-07-07
  • .NET連接池的問題詳解

    .NET連接池的問題詳解

    這篇文章主要介紹了.NET連接池的問題詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • asp.net(c#)網(wǎng)頁跳轉(zhuǎn)七種方法小結(jié)

    asp.net(c#)網(wǎng)頁跳轉(zhuǎn)七種方法小結(jié)

    在asp.net下,經(jīng)常需要頁面的跳轉(zhuǎn),下面是具體的幾種方法。跳轉(zhuǎn)頁面是大部編輯語言中都會(huì)有的,正面我們來分別介紹一下關(guān)于.net中response.redirect sever.execute server.transfer 三種頁面跳轉(zhuǎn)的方法
    2009-11-11
  • ASP.NET Core緩存靜態(tài)資源示例詳解

    ASP.NET Core緩存靜態(tài)資源示例詳解

    我們?cè)趦?yōu)化Web服務(wù)的時(shí)候,對(duì)于靜態(tài)的資源文件,通常都是通過客戶端緩存、服務(wù)器緩存、CDN緩存,這三種方式來緩解客戶端對(duì)于Web服務(wù)器的連接請(qǐng)求壓力的。下面這篇文章主要給大家介紹了關(guān)于ASP.NET Core緩存靜態(tài)資源的相關(guān)資料,需要的朋友可以參考下。
    2018-02-02
  • 使用Aspose.Cells組件生成Excel文件實(shí)例

    使用Aspose.Cells組件生成Excel文件實(shí)例

    這篇文章主要介紹了使用Aspose.Cells組件生成Excel文件的方法,大家參考使用吧
    2013-11-11
  • 在Apache環(huán)境下成功的運(yùn)行ASP.NET的注意事項(xiàng)

    在Apache環(huán)境下成功的運(yùn)行ASP.NET的注意事項(xiàng)

    在Apache環(huán)境下成功的運(yùn)行ASP.NET的注意事項(xiàng)...
    2007-08-08

最新評(píng)論

炉霍县| 兴仁县| 景洪市| 广河县| 齐齐哈尔市| 安多县| 聊城市| 大悟县| 隆德县| 青冈县| 新兴县| 鞍山市| 财经| 封丘县| 满城县| 西丰县| 孟连| 洛南县| 泌阳县| 舞钢市| 固原市| 临西县| 华宁县| 开鲁县| 鹿泉市| 敦化市| 澄江县| 平陆县| 原平市| 鸡东县| 文昌市| 水城县| 卢氏县| 柳州市| 马鞍山市| 襄垣县| 合山市| 江山市| 旬阳县| 思南县| 封丘县|