HttpHandler概述
HttpHandler實際上是ISAPI擴充,負責處理http請求。HttpHandler是http請求的最底層,在該類中實作具體的請求響應。一個HttpHandler能且隻能處理一種類型的檔案或資源。
IIS根據配置可以将很多檔案類型的請求都轉發給aspnet_isapi.dll,而aspnet_isapi則根據asp.net framework配置檔案中的檔案影射,将不同的檔案交給不同的處理程式。
HttpHandler類是實作了接口IHttpHandler的具體類。IHttpHandler接口定義了如果要實作一個HTTP請求的處理所必需實作的一些系統約定,它包含兩個接口函數:
public bool IsReusable
{
get { throw new NotImplementedException(); }
}
public void ProcessRequest(HttpContext context)
{
throw new NotImplementedException();
}
ProcessRequest:放置處理請求的實際代碼
IsReusabel: 以後的請求是否可重用該執行個體
當一個HTTP請求經同HttpModule容器傳遞到HttpHandler容器中時,ASP.NET Framework會調用HttpHandler的PrecessRequest成員方法來對這個HTTP請求進行真正的處理。以一個ASPX頁面為例,正是在這裡一個ASPX頁面才被系統處了解析,并将處理完成的結果繼續經由HttpModule傳遞下去,直至到達用戶端。
HttpHandler注冊
asp.net有很多内置的HttpHandler,在web.config檔案中檢視<httphandlers/>節點:
<httpHandlers>
... ... //略
<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True" />
<add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True" />
<add path="*.asax" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.ascx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*.cs" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" />
<add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler" validate="True" />
... ... //略
</httpHandlers>
要使HttpHandler可用,隻要在應用程式的web.config檔案中,按照以上方式進行相應的配置即可。
定制HttpHandler
public class MyFirstHandler : IHttpHandler,IRequiresSessionState
{
#region IHttpHandler 成員
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.Write("Hello HttpHandler");
context.Session["Test"] = "測試HttpHandler容器中調用Session";
context.Response.Write(context.Session["Test"]);
}
#endregion
}
也可以直接生成.ashx檔案定義HttpHandler,方法是:Add New Item——〉Generic Handler,預設檔案代碼如下
<%@ WebHandler Language="C#" Class="MyHandler" %>
using System;
using System.Web;
public class MyHandler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain;
context.Response.Write("Hello World");
}
public bool IsReusable {
get {
return false;
}
}
}
使用定制的HttpHandler
1 web.config配置
<system.web>
<httpHandlers>
<add path="*.foo" verb="*" type="CustomHandlers.MyHandler,CustomHandlers" />
</httpHandlers>
</system.web>
2 設定ISAPI
在IIS中設定ISAPI來進行檔案與處理程式映射:
- 打開IIS,選擇本範例所用的站點,右鍵,選擇“屬性”。
- 選擇“主目錄”頁籤,點選“配置...”按鈕。
- 點選“添加”,設定“可執行檔案”為“C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/aspnet_isapi.dll”,設定“擴充名”為“.foo”,點“确定”。
- 注意,不要勾選“檢查檔案是否存在”複選框,這樣不用建立檔案,隻要在位址欄輸入任意以.foo字尾結尾的檔案名,均會交由上面建立的Handler去處理,而不管這個檔案是否存在。
進行了這些設定以後,現在IIS就知道如何去處理對.foo字尾名檔案的請求了。
3 使用
1)直接從浏覽器上通路ashx頁面:http://localhost:2694/WebSite2/ModuleAndHandler/MyHandler.ashx
2)程式設計通路: <img src=MyHandler.ashx />,也可以給ashx檔案傳遞參數 <img src=MyHandler.ashx?id=12 />
3)在浏覽器上請求*.foo檔案:http://localhost:2694/WebSite2/ModuleAndHandler/a.foo
第1、2種請求方式需要建立ashx檔案,而第3種是cs類檔案
IHttpHandlerFactory
如果我們有很多個HttpHandler分别映射不同字尾名的請求,這樣我們的Web.config會變得很冗長,或者,我們隻有在程式運作時才能确切地知道使用哪個Handler,這個時候,可以考慮實作 IHttpHandlerFactory來完成這一過程。
實際上,ASP.NET Framework實際不直接将相關的頁面資源HTTP請求定位到一個其内部預設的IHttpHandler容器之上,而定位到了其内部預設的IHttpHandlerFactory上。IHttpHandlerFactory的作用是對IHttpHandler容器進行排程和管理。
IHttpHandlerFactory接口包含兩個函數
public interface IHttpHandlerFactory{
IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated);
void ReleaseHandler(IHttpHandler handler);
}
可見,需要實作兩個方法,分别是 GetHandler() 和 ReleaseHandler()。
- GetHandler(),傳回實作了IHttpHandler接口的類的執行個體。
- ReleaseHandler(),使得Factory可以重複使用一個已經存在的Handler執行個體。
例如,要定義兩個Handler
class HandlerFactory:IHttpHandlerFactory{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated){
string path = context.Request.PhysicalPath;
if (Path.GetExtension(path) == ".rss"){
return new RSSHandler();
}
if (Path.GetExtension(path) == ".atom"){
return new ATOMHandler();
}
return null;
}
public void ReleaseHandler(IHttpHandler handler){
}
}
public class RSSHandler: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{}
public bool IsReusable {
get { return true; }
}
}
public class ATOMHandler: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{}
public bool IsReusable {
get { return true; }
}
}
這時,在Web.Config 中<system.web>節點下進行如下設定即可:
<httpHandlers>
<add path="*.rss,*.atom" type=" RssFeadsLib.HandlerFactory" verb="GET" />
</httpHandlers>
但是,這不能簡化IIS中ISAPI的設定,還是需要手動去對.rss和.atom分别設定。