直播中
剛剛吃完晚飯,正好在鍵盤上面鍛煉一下手指。
接著上回繼續(xù)寫這個“日記”:
Chapter Two -- HttpModule是如何工作的?
我們上回說到,一個來自于客戶端的Http Request被截獲后經(jīng)過層層轉(zhuǎn)交(怎么都在踢皮球?呵呵)到達了HttpModule這個“請求監(jiān)聽器”。
HttpModule就類似于安插在ASPNET_WP.EXE進程中的一個竊聽器,稍微有些常識的人都會很自然的想象得到竊聽器是用來做什么的,而我們的HttpModule
可以說是作竊聽器的絕好人選了,但是需要明確的是,HttpModule絕對不是簡單的監(jiān)聽器,它可以做到更多的東西,比如它可以對截獲的請求增加一些內(nèi)容
等等。
另外需要明白的是,當一個Http Request到達HttpModule的時候,整個ASP.NET Framework系統(tǒng)還并沒有對這個請求做任何的真正處理,但是我們可以
在這個Http Request傳遞到真正的請求處理中心(HttpHandler)之前附加一些我們需要的信息在這個Http Request至上,或者針對我們截獲的這個Http
Request信息作一些額外的工作,或者在某些情況下干脆終止?jié)M足一些條件的Http Request,從而可以起到一個Filter過濾器的作用,而不僅僅是一個竊聽器了。
通過查閱MSDN(不要去相信.NET SDK自帶的那個QuickStarts Web文檔,正式版本中竟然在很多地方?jīng)]有更新這個文檔,很多東西在正式版本是無效的),
你會發(fā)現(xiàn)系統(tǒng)HttpModule實現(xiàn)了一個叫做IHttpModule的接口,很自然的就應當想到,只要我們自己的類能夠?qū)崿F(xiàn)IHttpModule接口,不就可以完全替代系統(tǒng)的
HttpModule了嗎?完全正確。
在我們開始自己的HttpModule類之前,我先來告訴你系統(tǒng)中的那個HttpModule是什么樣子的,ASP.NET系統(tǒng)中默認的HttpModule有以下幾個:
System.Web.Caching.OutputCacheModule
System.Web.SessionState.SessionStateModule
System.Web.Security.WindowsAuthenticationModule
System.Web.Security.FormsAuthenticationModule
System.Web.Security.PassportAuthenticationModule
System.Web.Security.UrlAuthorizationModule
System.Web.Security.FileAuthorizationModule
好了,我們來開始我們自己的HttpModule構(gòu)建歷程吧。
1)打開VS.NET新建一個“Class Library”項目,將它命名為MyHttpModule。
2)引用System.Web.dll文件
在代碼區(qū)域敲入:
using System;
using System.Web;
namespace MyHttpModuleTest
{
/// <summary>
/// 說明:用來實現(xiàn)自定義HttpModule的類
/// 作者:uestc95
/// 聯(lián)系:uestc95@263.net
/// </summary>
public class MyHttpModule:IHttpModule
{
/// <summary>
/// 說明:構(gòu)造器方法
/// 作者:uestc95
/// 聯(lián)系:uestc95@263.net
/// </summary>
public MyHttpModule()
{
}
/// <summary>
/// 說明:實現(xiàn)IHttpModule接口的Init方法
/// 作者:uestc95
/// 聯(lián)系:uestc95@263.net
/// </summary>
/// <param name="application">HttpApplication類型的參數(shù)</param>
public void Init(HttpApplication application)
{
application.BeginRequest +=new EventHandler(this.Application_BeginRequest);
application.EndRequest +=new EventHandler(this.Application_EndRequest);
}
/// <summary>
/// 說明:自己定義的用來做點事情的私有方法
/// 作者:uestc95
/// 聯(lián)系:uestc95@263.net
/// </summary>
/// <param name="obj">傳遞進來的對象參數(shù)</param>
/// <param name="e">事件參數(shù)</param>
private void Application_BeginRequest(Object obj,EventArgs e)
{
HttpApplication application=(HttpApplication)obj;
HttpContext context=application.Context;
HttpResponse response=context.Response;
HttpRequest request=context.Request;
response.Write("我來自Application_BeginRequest,:)");
}
/// <summary>
/// 說明:自己定義的用來做點事情的私有方法
/// 作者:uestc95
/// 聯(lián)系:uestc95@263.net
/// </summary>
/// <param name="obj">傳遞進來的對象參數(shù)</param>
/// <param name="e">事件參數(shù)</param>
private void Application_EndRequest(Object obj,EventArgs e)
{
HttpApplication application=(HttpApplication)obj;
HttpContext context=application.Context;
HttpResponse response=context.Response;
HttpRequest request=context.Request;
response.Write("我來自Application_EndRequest,:)");
}
/// <summary>
/// 說明:實現(xiàn)IHttpModule接口的Dispose方法
/// 作者:uestc95
/// 聯(lián)系:uestc95@263.net
/// </summary>
public void Dispose(){}
}
}
3)在VS.NET中編譯之后,你會得到MyHttpModule.dll這個文件。
4)接下來我們的工作就是如何讓ASPNET_WP.exe進程將http request交給我們自己寫的這個HttpModule呢?方法就是配置web.config文件。
在web.config文件中增加如下幾句話:
<httpModules>
<add name="test" type="MyHttpModuleTest.MyHttpModule,MyHttpModule"/>
</httpModules>
注意要區(qū)分大小寫,因為web.config作為一個XML文件是大小寫敏感的?!皌ype=MyHttpModuleTest.MyHttpModule,MyHttpModule”告訴我們
系統(tǒng)將會將http request請求交給位于MyHttpModule.dll文件中的MyHttpModuleTest.MyHttpModule類去處理。而這個DLL文件系統(tǒng)將會自動
到\bin子目錄或者系統(tǒng)全局程序集緩沖區(qū)(GAC)搜尋。我們可以將我們剛才得到的DLL文件放在bin子目錄中,至于后者,你可以通過.NET SDK正式版
自帶的Config工具做到,我們不詳細說了。
好了,我們的用來截獲http request請求的HttpModule就完成并且裝配完成了,你可以試著在你的web項目中建立一個新的WebForm,運行看看呢?:)
最后,我們假設(shè)一個使用這個HttpModule的場合。A站點提供免費的ASP.NET虛擬空間給大家,但是A站點的管理者并不想提供免費的午餐,他想要在每一個
頁面被瀏覽的時候自動彈出自己公司的廣告(就像現(xiàn)在的www.X63.com一樣),我總不能時刻監(jiān)視所有用戶的所有頁面吧,并且想要在每一個頁面手動添加
一段JS代碼,工作量是不可想象的,也是不現(xiàn)實的。那末好了,只要我們的HttpModule一旦被掛接完成,這一切都將是輕而易舉的事情了,只要我們在每一個
Http Request被我們捕獲的時候,給他增加上一些JS就好了!
我們上面提到在Init()方法中使用了兩個事件BeginRequest和EndRequest,這兩個事件分別是Init()中可以處理的所有事件的最開始事件和最終事件,在他們
中間還有一些其它的事件可以被我們利用,可以查閱MSDN。
另外在我關(guān)閉EditPlus之前,需要敲下如下的話:
在HttpModule中可以正常使用Response,Request,Server,Application,但是不能操作任何與Session有關(guān)代碼!
為什么呢?自己考慮一下吧,下回看看原因在哪里,另外再給出一個問題,你能發(fā)現(xiàn)系統(tǒng)默認的那幾個HttpModule在哪里配置的呢?找找看。
下回我們看看HttpHandler部分以及如何同HttpModule相配合的東東。
See you later.
(待續(xù),歡迎探討:uestc95@263.net)