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