天天看點

HttpHandler HttpModule入門篇

ASP.Net處理Http Request時,使用Pipeline(管道)方式,由各個HttpModule對請求進行處理,然後到達 HttpHandler,HttpHandler處理完之後,仍經過Pipeline中各個HttpModule的處理,最後将HTML發送到用戶端浏覽器中。

生命周期中涉及到幾個非常重要的對象:HttpHandler,HttpModule,IHttpHandlerFactory,他們的執行順序大緻的執行過程是這樣的:

client端發送頁面請求,被IIS的某個程序截獲,它根據申請的頁面字尾(.aspx)不同,調用不同的頁面處理程式(.asp->asp.dll; .aspx->ISAPI.dll)。而頁面處理程式在處理過程中,則要經曆HttpModule,HttpHandler的處理:前者HttpModule用于頁面處理前和處理後的一些事件的處理,後者HttpHandler進行真正的頁面的處理。

如前所說,HttpModule會在頁面處理前和後對頁面進行處理,是以它不會影響真正的頁面請求。通常用在給每個頁面的頭部或者尾部添加一些資訊(如版權聲明)等。曾經見過一些免費的空間,我們的頁面上傳上去後,浏覽的時候發現,在每個頁面的頭部和尾部多了很多小廣告....如果了解了HttpModule的原理,要做這個就不是很難了~

IHttpModule與IHttpHandler的差別整理

1.先後次序.先IHttpModule,後IHttpHandler. 注:Module要看你響應了哪個事件,一些事件是在Handler之前運作的,一些是在Handler之後運作的

2.對請求的處理上:

   IHttpModule是屬于大小通吃類型,無論用戶端請求的是什麼檔案,都會調用到它;例如aspx,rar,html的請求.

   IHttpHandler則屬于挑食類型,隻有ASP.net注冊過的檔案類型(例如aspx,asmx等等)才會輪到調用它.

3.IHttpHandler按照你的請求生成響應的内容,IHttpModule對請求進行預處理,如驗證、修改、過濾等等,同時也可以對響應進行處理

ASP.Net系統本身配置有很多HttpHandler和HttpModule,以處理aspx等.Net标準的頁面檔案,以及這些頁面檔案中标準的事件處理等。檢視

%System%/Microsoft.NET/Framework/v2.0.50727/CONFIG目錄下的 web.config檔案中的httpHandlers和httpModules節點,可以看到這些配置。如果有興趣,可以使用Reflector檢視.Net系統中相關的類和方法,了解.Net如何處理以及做了什麼處理。

.Net也提供了一套機制來開發自定義的HttpHandler和 HttpModule,均可以用于對HttpRequest的截取,完成自定義的處理。 HttpModule 繼承System.Web.IHttpModule接口,實作自己的HttpModule類。必須要實作接口的兩個方法:Init和Dispose。在 Init中,可以添加需要截取的事件;Dispose用于資源的釋放,如果在Init中建立了自己的資源對象,請在Dispose中進行釋放。

namespace MyModule

{

public class MyHttpModule : IHttpModule

{

public MyHttpModule()

{

}

//Init方法用來注冊HttpApplication 事件。

public void Init(HttpApplication r_objApplication)

{

r_objApplication.BeginRequest += new EventHandler(this.BeginRequest);

}

public void Dispose()

{

}

private void BeginRequest(object r_objSender, EventArgs r_objEventArgs)

{

HttpApplication objApp = (HttpApplication)r_objSender;

objApp.Response.Write("您請求的URL為" + objApp.Request.Path);

}

}

}

将編譯的dll檔案拷貝到web項目的bin目錄下,在web項目的web.config檔案system.web節點中配置:

這樣就将自定義的HttpModule類MyHttpModule插入到了目前web的HttpModule的Pipeline中。 HttpModule主要功能是對Application的各個事件進行截取,在這些事件中完成自己的處理。其實如果自己開發一些項目,直接在 Global.asax中處理已經足夠了。如果是開發一個Framework或者是某些方面的元件,需要在事件中添加處理,開發自定義的 HttpModule,可以避免使用Framework或者元件時,還得手工在Global.asax中添加代碼。目前想到的開發自定義HttpModule的用途,有全局的身份/權限驗證、自定義網站通路/記錄檔的記錄、處于管理/調試等目的對站點進行監控追蹤等。當然,如果是結合自定義的HttpHandler進行Framework的開發,HttpModule可以用于其它的一些特殊的處理。注意要區分大小寫,因為web.config作為一個XML檔案是大小寫敏感的。“type=MyHttpModuleTest.MyHttpModule,MyHttpModule”告訴我們系統将會将http request請求交給位于MyHttpModule.dll檔案中的MyHttpModuleTest.MyHttpModule類去處理。HttpHandler是完全的對Http Request的截取。

首先,繼承System.Web.IHttpHandler接口,實作自己的HttpHandler類。必須要實作接口的ProcessRequest方法和IsReusable屬性。ProcessRequest方法中完成對每個Http Request的處理,發送處理結果的HTML到輸出緩存中。IsReusable屬性被.Net Framework調用,用以确定這個HttpHandler的執行個體是否可以被重用于同類型其它的Request處理。

如果你在自己的HttpHandler類中,需要讀取或者是寫Session值,需要再繼承一個接口IRequiresSessionState。這個接口沒有任何方法,隻是一個标記接口。繼承這個接口之後,就可以在自己的HttpHandler中通路Session,可以在Session中寫入值。

namespace MyHandler

{

public class MyHttpHandler : IHttpHandler, IRequiresSessionState

{

public MyHttpHandler() { }

public bool IsReusable

{

get { return true; }

}

public void ProcessRequest(HttpContext context)

{

HttpResponse objResponse = context.Response;

objResponse.Write("This request is handled by MyHttpHandler");

}

}

}

把編譯的dll檔案拷貝到web項目的bin目錄下。

接下來,這樣來測試一下MyHttpHandler。我們為IIS配置一個以.cc為字尾名的檔案類型,用我們寫的MyHttpHandler來處理。

首先,在IIS站點的Configuration配置裡面,添加一個對.cc字尾名處理的Application Extention Mapping項。

然後,在web項目的web.config節點中配置:

    verb屬性配置這個HttpHandler處理那些HTTP方法,例如GET、POST等,如果是處理所有方法,就用*。path屬性配置HttpHandler對哪些檔案進行處理,例如可以是myfile.cc,如果是處理所有的.cc檔案,就用*.cc。

這樣,這個站點上所有.cc類型檔案的通路,都由MyHttpHandler處理。使用http://localhost/站點虛拟目錄/a.cc通路測試站點,可以看到測試效果。當然,a.cc這個檔案在Web伺服器上是并不存在的。

對HttpHandler的使用,比較典型的有.Net的Web MVC開源項目Maverick。Maverick使用一個Dispatcher類對所有的Http Request進行截取,他以.m作為字尾名向Web伺服器送出請求,在Dispatcher中,将.m的字尾去掉,提取Command Name,然後以這個command name從配置檔案中加載處理的flow,形成一個chain,依次對chain上的各個command和view進行處理,對各個command和 view的處理結果可能會在chain中選擇不同的處理分支,每個處理的Step中将處理結果的HTML寫入Response的緩存中進行輸出。

總體來說,Maverick的架構架構概念很不錯,但也存在明顯的缺陷,以後有時間再詳細的寫寫它的架構和需要改進之處。

總之,将HttpModule、HttpHandler,以及使用Ajax等将用戶端進行封裝結合起來,能夠給web項目的開發帶來非常大的改善空間。

我們經常看到很多網站通路文章的時候才用的是***.html 或***.shtml (如本blog的日志通路效果),其時這寫檔案在伺服器上不存在的,那為什麼會出現這樣的效果呢,是因為Web伺服器上對URL執行了重寫,把通路的 URL根據特定的格式重寫成内部通路頁面來實作的,它的好處是便于使用者了解,同時搜尋引擎也能更好地收入你的網站,當然其它的好處也很多,這裡不做一一介 紹了。

本文所講的是使用Asp.Net中的HttpHandler實作URL重寫的,它所實作的原理請看這裡,本程式可以處理任何Url,因為我在程式中使用了URL過慮,隻有通路檔案名是數字的才進行處理,并指在内部執行一個新的頁面,并輸出資料,代碼如下:

public void ProcessRequest(HttpContext Context)

{

try

{

//申明Request       

HttpRequest Request = Context.Request;

//取來路Url的絕對路徑

string Url = Request.Url.AbsolutePath;

//取通路的Web檔案的開始字元間隔數

int RegStart = Url.LastIndexOf("/") + 1;

//申明一個确定Web檔案名是否全是數字

Regex Reg = new Regex(@"/d+");

//用正規表達式進行比對

if (Reg.IsMatch(Url, RegStart))

{

//如果web檔案名是數字,則判定是查詢相關文章,執行指定頁面

Context.Server.Execute("~/PermaLink.aspx?id=" + Reg.Match(Url, RegStart).Value);

}

}

catch

{

Context.Response.Redirect(Context.Request.Url.ToString());

}

}

當然你首先要做的是先建一個類,并繼承自IHttpHandler,然後把這段代碼拷入,并編譯。在Web項目中若要使用此功能,需要在web.config裡面加上如下語句:

同時,還要在IIS中對Web項目進行配置,在Web項目的屬性中,在主目錄頁籤裡,把執行權限改為"腳本和可執行檔案",然後打開配置,在應用程式擴充裡加上需重寫的檔案格式的擴充。好了,萬事具備,隻欠運作了。

繼續閱讀