重寫HttpModule機制
寫這篇文章,心里多少有些不安。主要是因為我對在web.config文件中對HttpModule進行多個自定義HttpModule的配置與之前一位牛人的見解有些不同【具體參見http://www.rzrgm.cn/Jax/archive/2007/10/02/912884.html】。所以這篇文章僅僅只是我個人淺見,希望對HttpModule機制有深入了解的人能指出我理解有偏差的地方,同時也希望大家積極討論,共同進步。
最近因為用SlickUpload,它做上傳效果確實很拉風,功能也很強。但由于付費,使用之后一直有個div層顯示,并且往它的官網上重定向。所以就萌發了重寫HttpModule機制的想法。
熟悉Asp.Net的朋友都應該知道HttpModule,它是處理客戶端請求中很重要的一個環節。所有客戶端的請求都必須
通過它進行一些前期處理后,再由它交給HttpHandler進行最終處理。HttpHandler調用ProcessRequest()方對http請求進行處理,處理完成以后完成以后,再交給HttpModule,然后再由HttpModule將處理完的Http請求信息轉交給客戶端。處理流程如下圖:
圖1:Http請求到達HttpRuntime:

圖2:HttpModule與HttpHandler處理流程:

整個Http請求處理流程為:HttpRequest-->inetinfo.exe->ASPNET_ISAPI.DLL-->HttpPipeline-->ASPNET_WP.EXE-->
HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()。
HttpModule的工作原理:監聽HttpRequest請求,同時對HttpRequest增添或者過濾一些內容。HttpModule實現了IHttpModule接口。重寫HttpModule的實現即設計一個現實了IHttpModule接口的類。IHttpModule接口包括兩個方法:1、Dispose()。2、Init()。具體代碼如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Web;
6
7 namespace HttpModules
8 {
9 public class ValidaterHttpModuleEvents : IHttpModule
10 {
11 #region IHttpModule 成員
12
13 public void Dispose()
14 {
15 throw new NotImplementedException();
16 }
17
18 public void Init(HttpApplication context)
19 {
20
21 context.BeginRequest += new EventHandler(Application_BeginRequest);
22 context.EndRequest += new EventHandler(context_EndRequest);
23 }
24
25 void context_EndRequest(object sender, EventArgs e)
26 {
27 HttpContext.Current.Response.Write("ValidaterHttpModuleEvents EndRequest </br>");
28 }
29
30 #endregion
31
32 void Application_BeginRequest(object sender, EventArgs e)
33 {
34
35 HttpApplication application = sender as HttpApplication;
36 application.CompleteRequest();
37 //HttpContext.Current.Response.Redirect("http://www.163.com");
38 application.Context.Response.Write("ValidaterHttpModuleEvents Begin Request </br>");
39
40
41 }
42 }
43 }
然后,在Web.Config的System.Web的httpModules配置節中添加如下配置代碼:
<add name="HttpModule" type="HttpModules.ValidaterHttpModuleEvents,HttpModules"/>
name可以隨便指定,Type由【,】分割為兩部分,前一部分指明實現IHttpModule接口類的全名,包括命名空間與類型名,后一部分指明程序集編譯成功后的程序集。
這樣我們在瀏覽器中瀏覽頁面即可看到如下圖:

同樣,如果我們在多個類庫中以相同的方式重寫IHttpModule機制,只需要在httpModules配置節中添加如下配置代碼添加相同的配置節即可。
我在另外一個庫中重寫的代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace HttpModules2
{
public class HttpModulesTest2 : IHttpModule
{
#region IHttpModule 成員
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
public void context_EndRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.Write("HttpModulesTest2 EndRequest </br>");
}
public void context_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.Write("HttpModulesTest2 BeginRequest </br>");
}
#endregion
}
}
然后在配置文件中的配置如下:
<add name="HttpModule" type="HttpModules.ValidaterHttpModuleEvents,HttpModules"/>
<add name="HttpModuleTest2" type="HttpModules2.HttpModulesTest2,HttpModules2"/>
此時的輸出如下:
ValidaterHttpModuleEvents Begin Request
ValidaterHttpModuleEvents EndRequest
HttpModulesTest2 EndRequest
同樣:我再用同樣的方式重寫一個HttpModule,得出的輸出結果類似。稍后,我會給出下載代碼。
由此輸出結果我得出如下結論:多個HttpModule對Http請求進行處理,只有Web.Config中httpModules配置節的第一個IHttpModule的BeginRequest事件會響應,但是httpModules配置節下的所有IHttpModule實例對象的EndRequest事件都會響應。
如果大家看看本文上面的鏈接地址,一定會發現:他說的執行方式是httpModules配置節下的所有重寫HttpModule機制的BeginRequest會按照配置順序執行,然后才是EndRequest也按照配置順序執行。按照我上面的例子就應該是:
1、HttpModule.BeginRequest
2、HttpModuleTest2.BeginRequest
3、HttpModule.EndRequest
4、HttpModuleTest2.EndRequest
而事實上,按照我示例中的輸出,卻并非如此。
以上為個人意見。代碼下載:http://download.csdn.net/source/3466595
(博客園上一直不知道在哪上傳文件,所以一直都發布在CSDN上。)
參考資料:
1、http://hi.baidu.com/5ihuige/blog/item/c1da61a3b9890286461064e6.html
2、http://www.rzrgm.cn/Jax/archive/2007/10/02/912884.html
以上圖片1,圖片2,是從以上地址從拷貝下來的。大家可以參見原文。
浙公網安備 33010602011771號