ASP.NET底層機制 (上) HttpModule

在IIS的應用程序映射中,IIS會將對asp和asa文件的請求轉交給asp.dll這個ISAPI來處理
解釋型處理,每次請求都會重新解釋一次,不適用于大流量請求
2.ASP.NET的HTTP請求處理過程

3.在HttpRuntime中請求處理過程
HttpRequest請求:
進入HttpRumtime——通過HttpApplicationFactory,建立HttpApplication實例——進入HttpModule——通過HttpHandlerFactory,建立HttpHandler實例
*這個HttpApplication實例在HttpModule的Init方法中會用到
4.HttpModule工作原理
負責監聽HttpRequest,同時對HttpRequest增添或者過濾掉一部分內容。
HttpModule實現了接口IHttpModule,我們可以自定義實現該接口的類,從而取代HttpModule。
ASP.NET默認的HttpModule如下:
System.Web.SessionState.SessionStateModule;
System.Web.Security.WindowsAuthenticationModule;
System.Web.Security.FormsAuthenticationModule;
System.Web.Security.PassportAuthenticationModule;
System.Web.Security.UrlAuthorizationModule;
System.Web.Security.FileAuthorizationModule;IHttpModule接口分析:
public interface IHttpModule
{
// 銷毀不再被HttpModule使用的資源
void Dispose();
//初始化一個Module,為捕獲HttpRequest做準備
void Init(HttpApplication context);
}編寫自己的HttpModule:
//注意要在這個類庫中添加System.Web引用
using System;
using System.Web;
namespace ClassLibraryModule
{
public class MyHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(this.Application_BeginRequest);
context.EndRequest += new EventHandler(this.Application_EndRequest);
}
public void Dispose() { }

//自己要處理私事的兩個方法
public void Application_BeginRequest(Object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
HttpResponse response = application.Response;
HttpRequest request = application.Request;
response.Write("來自Application_BeginRequest");
}
public void Application_EndRequest(Object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
HttpResponse response = application.Response;
HttpRequest request = application.Request;
response.Write("來自Application_EndRequest");
}
}
}在Web項目中添加這個類庫的引用,同時在Web.config的system.web標簽中添加:
<httpModules>
<add name="Test" type="ClassLibraryModule.MyHttpModule,ClassLibraryModule"></add>
</httpModules>name可以隨意指定,沒有影響。
type有兩個參數,第一個表示具體哪個類,第二個表示是哪個dll
于是該站點下的每個頁面都會Response.Write兩句話——這適合做廣告,只要替換成javascript即可
5.HttpModule內部事件機制
HttpApplication實例有很多事件,BenginRequest和EndRequest分別是HttpModule容器最開始的和最后的事件

注意,EndRequest之后還會觸發PreSendRequestHeaders事件和PreSendRequestContent事件,這不是在HttpModule外的兩個事件,表示HttpModule結束,即將開始向Client發送數據。
HttpModule容器與HttpHandler容器的交互:
HttpModule容器會將HttpRequest傳遞到HttpHandler容器,這個時間點是ResolveRequestCache事件。
HttpModule容器會建立HttpHandler實例作為入口——Session從此生效
觸發AcquireRequestState事件以及PreRequestHandlerExecute事件,
HttpModule容器便將對HttpRequest的控制權轉讓給HttpHandler容器。
HttpHandler容器處理HttpRequest——使用自身的ProcessRequest方法,將對其控制權又還給HttpModule容器——之后Session失效

可以同時加載兩個HttpModule,
<httpModules>
<add name="Test1" type="ClassLibraryModule.MyHttpModule1,ClassLibraryModule1"></add>
<add name="Test2" type="ClassLibraryModule.MyHttpModule2,ClassLibraryModule2"></add>
</httpModules>這時,根據add標簽的先后,依次執行:
Test1.BeginRequest
Test2.BeginRequest
.....
Test1.EndRequest
Test2.EndRequest
利用HttpModule實現當滿足一定條件時終止此次HttpRequest:
在BeginRequest事件中,使用HttpApplication.CompleteRequest()方法
public void Application_BeginRequest(Object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
application.CompleteRequest();
context.Response.StatusCode = 500;
context.Response.StatusDescription = "Internal Server Error";
}在BeginRquest中終止,但是仍然會調用EndRequest事件,以及PreSendRequestHeaders事件和PreSendRequestContent事件——應該說直接跳轉到EndRequest事件,而不會調用這期間的事件
如果有兩個HttpModule,在第一個Module的BeginRequest中終止,僅僅不會調用第二個Module的BeginRequest,但仍然會調用兩個EndRequest事件,以及PreSendRequestHeaders事件和PreSendRequestContent事件。
以上兩句話,可以用下圖來表示:




浙公網安備 33010602011771號