是否想學習HTTP處理程式程式設計呢?好吧,第一步工作是熟悉IHttpHandler接口。HTTP處理程式隻不過是實作該接口的托管類。更确切地講,同步HTTP處理程式實作IHttpHandler接口;而異步HTTP處理程式實作IHttpAsyncHandler接口。讓我們先看看同步處理程式。
IHttpHandler接口的合同定義了HTTP處理程式以同步方式處理一個HTTP請求需要采取的行動。
1. IHttpHandler接口的成員
IHttpHandler接口隻定義了兩個成員:ProcessRequest和IsReusable,如表2.1所示。ProcessRequest是一個方法,而IsReusable是一個布爾邏輯屬性。
表2.1 IHttpHandler接口的成員
成 員 | 描 述 |
IsReusable | 該屬性獲得一個布爾值,訓示另一個請求是否可以使用該HTTP處理程式的執行個體 |
ProcessRequest | 該方法處理HTTP請求 |
Page類上的IsReusable屬性傳回false,表示需要該HTTP請求的新執行個體來服務一個頁面請求。通常我們使它在所有情況下都傳回false,并根據請求負荷的不同而要求它做一些有意義的處理。那些被用作篩選特殊請求的簡單屏障的處理程式可以将IsReusable設定為true,以節省一些CPU周期。稍後我将用一個具體的執行個體來說明這一點。
ProcessRequest方法具有如下簽名:
void ProcessRequest(HttpContext context);
它以請求的上下文作為輸入,并確定該請求得到服務。在同步處理程式的情況下,當ProcessRequest傳回時,準備把輸出發到用戶端。
2. 一個簡單的HTTP處理程式
再次強調,HTTP處理程式隻是一個實作了IHttpHandler接口的類。請求的輸出是在ProcessRequest方法中建立的,如下面的代碼所示:
using System.Web;
namespace ProAspNet20.Advanced.CS.Components
{
public class SimpleHandler : IHttpHandler
{
// Override the ProcessRequest method
public void ProcessRequest(HttpContext context)
{
context.Response.Write("<H1>Hello, I'm an HTTP handler</H1>");
}
// Override the IsReusable property
public bool IsReusable
{
get { return true; }
}
}
}
我們需要一個能夠調用該處理程式的入口點。在此上下文中,該處理程式代碼的入口點隻不過是一個HTTP終點——即,一個公共的URL。該URL必須有一個惟一的名稱,使IIS和ASP.NET運作庫能夠把它映射到該代碼。注冊時,HTTP處理程式和Web伺服器資源之間的映射是通過web.config檔案建立的。
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="myHandler.aspx"
type="ProAspNet20.Advanced.CS.Components.SimpleHandler" />
</httpHandlers>
</system.web>
</configuration>
<httpHandlers>節列出了目前應用程式可用的處理程式。這些設定訓示,對myHandler.aspx終點的任何輸入請求,由SimpleHandler處理程式負責處理。要注意的是,myHandler.aspx URL不必是伺服器上的實體資源;它隻是一個公共資源辨別符。type屬性引用包含該處理程式的類和程式集,它的标準格式是type[,assemly]。如果該元件在App_Code或其他保留檔案夾中定義,則忽略該程式集資訊。
注意 如果在machine.config檔案中輸入上述設定,則将把SimpleHandler元件注冊成可以從伺服器機器上托管的所有Web應用程式内可調用的元件。
如果調用myHandler.aspx URL,将得到如圖2.2所示的結果。
圖2.2 一個響應myHandler.aspx請求的HTTP處理程式示例
這裡所述的方法是使用HTTP處理程式最快、最簡單的方法,但是有關HTTP處理程式注冊的知識,我們還有很多要了解并且還有很多其他選項可以利用。現在,讓我們考慮一個更複雜的HTTP處理程式示例。
HTTP處理程式與ASP.NET頁面
我們應當利用HTTP處理程式資源來實作應用程式特有的功能,它們需要比正常的Web頁面被更快地處理。在任何情況下,HTTP處理程式傳回一個帶有内容類型和主體的有效的HTTP響應。服務一個.ashx請求,或者一個自定義處理程式托管的任何其他請求,可能會導緻比服務一個.aspx資源更快的代碼。ASP.NET處理一個自定義的處理程式通常更快,因為這不必對使用者代碼引發任何中間事件(例如,Init, Load),不必托管任何視圖狀态,而且也不支援任何回發機制。大概說來,對一個自定義的HTTP處理程式的請求類似于對.aspx資源的請求,其中隻發生呈現步驟。此外,找到服務一個頁面請求所需的正确的HTTP處理程式可能需要更長的時間,因為這要牽涉到一個頁面處理程式工廠的中間對象。
這就是說,我們要記住,ASP.NET頁面隻是一個HTTP處理程式——雖然是一個非常複雜而進階的HTTP處理程式。底層的處理機制完全相同。如果說滿足某種特定需要的自定義的HTTP處理程式通常比頁面更快,這是因為它們通常是為了直接得到給定結果而實作的。例如,假設我們需要顯示從一個資料庫中取出來的一個圖像——這是我們将在第9章中詳細讨論的一個主題,我們仍然需要将一個Image控件綁定到一個服務合适的MIME類型的URL。該URL應當是一個頁面嗎?它當然可以是頁面;但是,如果使用一個自定義的HTTP處理程式,通常會處理得更快。
ASP.NET頁面是一個複雜對象,并由一個自定義的而且必定是複雜的HTTP處理程式(Page類)提供服務。就服務自定義資源而言,一定要使用一個合适的處理程式,隻包
含必需的智能和複雜度。為了說明這一點,假設要運作一個查詢并提供一個資料庫中存儲的一個圖像的位元組,我們不需要任何視圖狀态和回發管理,也不需要向該應用程式激發事件。
應當使用一般的.ashx資源,還是使用一個自定義的擴充呢?這主要取決于需要實作的功能。ASHX方法是為相對簡單的場景設計的,其中幾乎不需要傳遞什麼參數(或者根本不需要參數),并使用查詢字元串來引入它們。如果有一個自定義的文檔要處理,并且該文檔具有以非平面的或複雜的布局進行組織的各種資訊,則最好使用自定義的擴充。