Asp.net mvc應(yīng)用程序生命周期
廣告:
一、iis生命周期
1. 用戶輸入www.53bk.com
2. 到達(dá)服務(wù)器iis,IIS的HTTP.SYS 的內(nèi)置驅(qū)動(dòng)程序來(lái)監(jiān)聽(tīng)來(lái)自外部的 HTTP請(qǐng)求。I
3. iis服務(wù)器的HTTP.SYS交給ISAPI,ISAPI處理網(wǎng)址擴(kuò)展名,ISAPI提交給了aspnet_isapi.dll以后,接著就是只是等待結(jié)果。
4. aspnet_isapi.dll提交給asp.net mvc應(yīng)用程序處理(轉(zhuǎn)到應(yīng)用程序生命周期)。
5. 應(yīng)用程序返回結(jié)果給iis,iis再返回給用戶(實(shí)際是IIS 接收返回的數(shù)據(jù)流,并重新返還給 HTTP.SYS,HTTP.SYS 再將這些數(shù)據(jù)返回給客戶端瀏覽器)。
二、應(yīng)用程序生命周期(這個(gè)是iis生命周期的一部分)
Asp.Net Mvc只是服務(wù)器(IIS)的一個(gè)組成部分而已,它是一個(gè) ISAPI擴(kuò)展
如果文件擴(kuò)展名尚未映射到 ASP.NET,則 ASP.NET 將不會(huì)接收該請(qǐng)求。例如,由于 .htm 文件通常沒(méi)有映射到 ASP.NET,因此 ASP.NET 將不會(huì)對(duì) .htm 文件請(qǐng)求執(zhí)行身份驗(yàn)證或授權(quán)檢查。
1.BeginRequest 在 ASP.NET 響應(yīng)請(qǐng)求時(shí)作為 HTTP 執(zhí)行管線鏈中的第一個(gè)事件發(fā)生
2.AuthenticateRequest 當(dāng)安全模塊已建立用戶標(biāo)識(shí)時(shí)發(fā)生。注:AuthenticateRequest事件發(fā)出信號(hào)表示配置的身份驗(yàn)證機(jī)制已對(duì)當(dāng)前請(qǐng)求進(jìn)行了身份驗(yàn)證。預(yù)訂 AuthenticateRequest 事件可確保在處理附加的模塊或事件處理程序之前對(duì)請(qǐng)求進(jìn)行身份驗(yàn)證
3.PostAuthenticateRequest 當(dāng)安全模塊已建立用戶標(biāo)識(shí)時(shí)發(fā)生
4.AuthorizeRequest 當(dāng)安全模塊已驗(yàn)證用戶授權(quán)時(shí)發(fā)生。
5.PostAuthorizeRequest 在當(dāng)前請(qǐng)求的用戶已獲授權(quán)時(shí)發(fā)生。
6.ResolveRequestCache 當(dāng) ASP.NET 完成授權(quán)事件以使緩存模塊從緩存中為請(qǐng)求提供服務(wù)時(shí)發(fā)生,從而跳過(guò)事件處理程序(例如某個(gè)頁(yè)或 XML Web services)的執(zhí)行。這個(gè)事件還可以用來(lái)判斷正文是不是從Cache中得到的。
7.PostResolveRequestCache 在 ASP.NET 跳過(guò)當(dāng)前事件處理程序的執(zhí)行并允許緩存模塊滿足來(lái)自緩存的請(qǐng)求時(shí)發(fā)生。
(asp.net mvc開(kāi)始第一步工作)
8.PostMapRequestHandler 在 ASP.NET 已將當(dāng)前請(qǐng)求映射到相應(yīng)的事件處理程序時(shí)發(fā)生。 (asp.net mvc開(kāi)始第二步工作)
9.AcquireRequestState 當(dāng) ASP.NET 獲取與當(dāng)前請(qǐng)求關(guān)聯(lián)的當(dāng)前狀態(tài)(如會(huì)話狀態(tài))時(shí)發(fā)生。 (開(kāi)始有Session)這里緩存頁(yè)多用戶只觸發(fā)一次
10.PostAcquireRequestState 在已獲得與當(dāng)前請(qǐng)求關(guān)聯(lián)的請(qǐng)求狀態(tài)(例如會(huì)話狀態(tài))時(shí)發(fā)生。
11. PreRequestHandlerExecute 恰好在 ASP.NET 開(kāi)始執(zhí)行事件處理程序(例如,某頁(yè)或某個(gè) XML Web services)前發(fā)生。
12. ReleaseRequestState 在 ASP.NET 執(zhí)行完所有請(qǐng)求事件處理程序后發(fā)生。該事件將使?fàn)顟B(tài)模塊保存當(dāng)前狀態(tài)數(shù)據(jù)。
13. PostReleaseRequestState 在 ASP.NET 已完成所有請(qǐng)求事件處理程序的執(zhí)行并且請(qǐng)求狀態(tài)數(shù)據(jù)已存儲(chǔ)時(shí)發(fā)生。
14. UpdateRequestCache 當(dāng) ASP.NET 執(zhí)行完事件處理程序以使緩存模塊存儲(chǔ)將用于從緩存為后續(xù)請(qǐng)求提供服務(wù)的響應(yīng)時(shí)發(fā)生。
15. PostUpdateRequestCache 在 ASP.NET 完成緩存模塊的更新并存儲(chǔ)了用于從緩存中為后續(xù)請(qǐng)求提供服務(wù)的響應(yīng)后,發(fā)生此事件。
16. LogRequest 在 ASP.NET 完成緩存模塊的更新并存儲(chǔ)了用于從緩存中為后續(xù)請(qǐng)求提供服務(wù)的響應(yīng)后,發(fā)生此事件。
(僅在 IIS 7.0 處于集成模式并且 .NET Framework 至少為 3.0 版本的情況下才支持此事件)
17. PostLogRequest 在 ASP.NET 處理完 LogRequest 事件的所有事件處理程序后發(fā)生。
(僅在 IIS 7.0 處于集成模式并且 .NET Framework 至少為 3.0 版本的情況下才支持此事件。)
18. EndRequest 在 ASP.NET 響應(yīng)請(qǐng)求時(shí)作為 HTTP 執(zhí)行管線鏈中的最后一個(gè)事件發(fā)生。
在調(diào)用 CompleteRequest 方法時(shí)始終引發(fā) EndRequest 事件。
備注:
我們可以在Global.aspx文件中對(duì)HttpApplication的請(qǐng)求進(jìn)行定制即注入這19個(gè)事件中的某個(gè)事件進(jìn)行邏輯處理操作。在Global.aspx中我們按照"Application_{Event Name}"這樣的方法命名進(jìn)行事件注冊(cè)。
Event Name就是上面19個(gè)事件的名稱。比如Application_EndRequest就用于處理Application的EndRequest事件。
HttpModule
當(dāng)一個(gè)請(qǐng)求轉(zhuǎn)入ASP.net管道時(shí),最終負(fù)責(zé)處理請(qǐng)求的是與資源相匹配的HttpHandler對(duì)象,但是在HttpHandler進(jìn)行處理之前,ASP.NET先會(huì)加載并初始化所有配置的HttpModule對(duì)象。HttpModule初始化的時(shí)候,會(huì)將一些回調(diào)事件注入到HttpApplication相應(yīng)的事件中。所有的HttpModule都實(shí)現(xiàn)了IHttpModule接口,該接口有一個(gè)有一個(gè)Init方法。
public interface IHttpModule
{
// Methods
void Dispose();
void Init(HttpApplication context);
}
看到Init方法呢接受一個(gè)HttpApplication對(duì)象,有了這個(gè)對(duì)象就很容易注冊(cè)HttpApplication中19個(gè)事件中的某個(gè)事件了。這樣當(dāng)HttpApplication對(duì)象執(zhí)行到某個(gè)事件的時(shí)候自然就會(huì)出發(fā)。
HttpHandler
對(duì)于不同的資源類型的請(qǐng)求,ASP.NET會(huì)加載不同的HttpHandler來(lái)處理。所有的HttpHandler都實(shí)現(xiàn)了IhttpHandler接口。
public interface IHttpHandler
{
// Methods
void ProcessRequest(HttpContext context);
// Properties
bool IsReusable { get; }
}
我們看到該接口有一個(gè)方法ProcessRequest,顧名思義這個(gè)方法就是主要用來(lái)處理請(qǐng)求的。所以說(shuō)每一個(gè)請(qǐng)求最終分發(fā)到自己相應(yīng)的HttpHandler來(lái)處理該請(qǐng)求。
ASP.NET MVC 運(yùn)行機(jī)制
asp.net mvc是在什么時(shí)機(jī)獲得了控制權(quán)并對(duì)請(qǐng)求進(jìn)行處理呢?
既然asp.net mvc還是以asp.net運(yùn)行時(shí)為基礎(chǔ)那么它必然要在asp.net應(yīng)用程序的生命周期中對(duì)請(qǐng)求進(jìn)行截獲。第一反應(yīng)當(dāng)然是去web.config里面去翻翻,我們可以看到UrlRoutingModule的配置節(jié):
< add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
用Reflector打開(kāi)這個(gè)程序集,可以看到以下代碼:
protected virtual void Init(HttpApplication application)
{
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
}
看到這里我們的第一個(gè)問(wèn)題實(shí)際上已經(jīng)有了答案:時(shí)機(jī)是在PostResolveRequestCache和PostMapRequestHandler.
PostResolveRequestCache 開(kāi)始的。。!
到UrlRoutingModule實(shí)現(xiàn)了接口IHttpModule,當(dāng)一個(gè)請(qǐng)求轉(zhuǎn)入ASP.NET管道時(shí),就會(huì)加載 UrlRoutingModule對(duì)象的Init()方法。
通過(guò)在全局Web.Config中注冊(cè) System.Web.Routing.UrlRoutingModule,IIS請(qǐng)求處理管道接到請(qǐng)求后,就會(huì)加載 UrlRoutingModule類型的Init()方法。
HttpHandler與HttpModule區(qū)別
HttpHandler,Http請(qǐng)求的處理者 例如ScriptHandler、WebServiceHandler,IHttpHandler的實(shí)現(xiàn)都是為了處理某一類的請(qǐng)求。如ScriptHandler負(fù)責(zé)處理對(duì)腳本的請(qǐng)求。
HttpModule,Http模塊。實(shí)際上就是那19個(gè)標(biāo)準(zhǔn)事件的處理者,或者說(shuō)19個(gè)標(biāo)準(zhǔn)事件的訂閱者
一、HttpHandler的職責(zé) 應(yīng)該這樣理解HttpHanlder:一個(gè)HttpHanlder用于響應(yīng)一類的請(qǐng)求,為一類的請(qǐng)求生成響應(yīng)結(jié)果。
我們經(jīng)常用到的HttpHanlder有哪些?
1. aspx頁(yè)面。
2. asmx服務(wù)文件。
3. ashx文件(一般處理程序)。
4. 實(shí)現(xiàn)IHttpHandler接口的自定義類型。
二、HttpModule的職責(zé)
有時(shí)候有些頁(yè)面需要一些相同的檢查功能,比如身份驗(yàn)證。明顯使用HttpHandler是不方便的,因?yàn)椴皇撬械捻?yè)面都需要去調(diào)用那些相同的功能。
HttpModule的設(shè)計(jì)正是提供了一個(gè)靈活的方法解決這種功能重用的問(wèn)題,它采用事件(觀察者)的設(shè)計(jì)模式,將某些HttpHandler都需要的功能抽取出來(lái),形成不同的觀察者類型,這些觀察者類型可以編譯成類庫(kù)形式,供多個(gè)網(wǎng)站共用。
配置只是告訴ASP.NET,這些HttpModule需要運(yùn)行起來(lái),可能會(huì)用得著。
我們用HttpModule做什么事情?
1. 修改某些請(qǐng)求(例如前面的示例修改了響應(yīng)頭)。
2. 檢查檢查請(qǐng)求(例如身份認(rèn)證檢查)。
HttpModule能處理哪些請(qǐng)求呢?
1. 默認(rèn)是全部進(jìn)入ASP.NET的請(qǐng)求。
2. 如果只需要處理部分請(qǐng)求,那么請(qǐng)自行判斷。
總結(jié): HttpHandler(中文:處理程序)相當(dāng)于一條水管,HttpModule相當(dāng)于一小節(jié)水管。HttpHandler有很多條,一條流油,一條流水等等。HttpModule(中文:http模塊)相當(dāng)于一小截,需要過(guò)濾的長(zhǎng)水管里面都可以裝上。HTTP Module是特殊類型的類,它參與每一次頁(yè)面請(qǐng)求。
附 mvc 代碼:
PostResolveRequestCache:
public virtual void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = this.RouteCollection.GetRouteData(context);
if (routeData != null)
{
IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));
}
if (!(routeHandler is StopRoutingHandler))
{
RequestContext requestContext = new RequestContext(context, routeData);
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));
}
RequestData data2 = new RequestData();
data2.OriginalPath = context.Request.Path;
data2.HttpHandler = httpHandler;
context.Items[_requestDataKey] = data2;
context.RewritePath("~/UrlRouting.axd");
}
}
}
普通asp.net應(yīng)用程序生命周期:
HttpApplication對(duì)象是Asp.net中處理請(qǐng)求的重要對(duì)象,但是,這種類型的對(duì)象實(shí)例不是由程序員來(lái)創(chuàng)建,而是由Asp.net幫助我們創(chuàng)建。為了便于擴(kuò)展處理,Asp.net暴露了大量的事件給程序員,這些事件按照固定的處理順序依次觸發(fā),程序員通過(guò)編寫事件處理方法就可以自定義每一個(gè)請(qǐng)求的擴(kuò)展處理過(guò)程。
HttpApplication的19個(gè)標(biāo)準(zhǔn)事件如下:
事件名稱 | 說(shuō)明 |
BeginRequest | Asp.net處理的第一個(gè)事件,表示處理的開(kāi)始 |
AuthenticateRequest | 驗(yàn)證請(qǐng)求,一般用來(lái)取得請(qǐng)求用戶的信息 |
PostAuthenticateRequest | 已經(jīng)獲取請(qǐng)求用戶的信息 |
AuthorizeRequest | 授權(quán),一般用來(lái)檢查用戶的請(qǐng)求是否獲得權(quán)限 |
PostAuthorizeRequest | 用戶請(qǐng)求已經(jīng)得到授權(quán)--這里開(kāi)始每個(gè)頁(yè)面觸發(fā)一次,包括刷新 |
ResolveRequestCache | 獲取以前處理緩存的處理結(jié)果,如果以前緩存過(guò),那么,不必再進(jìn)行請(qǐng)求的處理工作,直接返回緩存結(jié)果 |
PostResolveRequestCache | 已經(jīng)完成緩存的獲取操作 |
PostMapRequestHandler | 已經(jīng)根據(jù)用戶的請(qǐng)求,創(chuàng)建了處理請(qǐng)求的處理器對(duì)象 |
AcquireRequestState | 取得請(qǐng)求的狀態(tài),一般用于Session --這里緩存頁(yè)多用戶只觸發(fā)一次 |
PostAcquireRequestState | 已經(jīng)取得了Session |
PreRequestHandlerExecute | 準(zhǔn)備執(zhí)行處理程序 |
PostRequestHandlerExecute | 已經(jīng)執(zhí)行了處理程序 |
ReleaseRequestState | 釋放請(qǐng)求的狀態(tài) |
PostReleaseRequestState | 已經(jīng)釋放了請(qǐng)求的狀態(tài) |
UpdateRequestCache | 更新緩存 |
PostUpdateRequestCache | 已經(jīng)更新了緩存 |
LogRequest | 請(qǐng)求的日志操作 |
PostLogRequest | 已經(jīng)完成了請(qǐng)求的日志操作 |
EndRequest | 本次請(qǐng)求處理完成 |
其余的事件則處理應(yīng)用程序請(qǐng)求,這些事件被觸發(fā)的 順序是:
Application_BeginRequest
Application_AuthenticateRequest
Application_AuthorizeRequest
Application_ResolveRequestCache
Application_AcquireRequestState
Application_PreRequestHandlerExecute
Application_PreSendRequestHeaders
Application_PreSendRequestContent
<<執(zhí)行代碼>>
Application_PostRequestHandlerExecute
Application_ReleaseRequestState
Application_UpdateRequestCache
Application_EndRequest
這些事件常被用于安全性方面。
廣告: