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