寫這篇文章,心裡多少有些不安。主要是因為我對在web.config檔案中對HttpModule進行多個自訂HttpModule的配置與之前一位牛人的見解有些不同【具體參見http://www.cnblogs.com/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.cnblogs.com/Jax/archive/2007/10/02/912884.html
以片1,圖片2,是從以上地址從拷貝下來的。大家可以參見原文。