Integrated pipeline 簡介作者:嚴永欽

IIS 7 提供了一種與以往不同的要求處理模式,稱之為整合模式 (Integrated Mode)。本文會針對 IIS 6 及 IIS 7 整合模式在處理 HttpRequest 的運作上做一個簡單的比較,並以靜態檔案存取的差異來說明。

IIS 6 回應 HttpRequest 的運作方式

在 IIS 6 當中,ASP.NET 是以實作 ISAPI Extension 的方式附掛在 IIS 之上。因此當用戶端送出的HttpRequest扺達 IIS 時,IIS 是根據 IASPI 的設定來決定處理此要求的方式(如圖 1)。如果 HttpRequest 所要求的副檔名存在於 ISAPI 對應檔的設定當中,則判定為動態內容;反之則為靜態內容。

點擊放大

圖一:IIS 6 的執行架構

處理靜態檔案的要求時,IIS 會直接讀檔並送出回應(註1)。而動態的要求則是交由 ISAPI 設定中相對應的 ISAPI Extension 進行處理(如圖 2)。必須到了這一步,而且 ISAPI 中相對應的ISAPI Extension 為 aspnet_isapi.dll,ASP.NET 模組才開始發揮它的作用。而這也是 IIS 6 之所以不能夠跟 IIS 7 一樣直接支援 ASP.NET MVC 的原因:因為沒有副檔名,IIS 就無從判斷是要走靜態內容的處理流程或是動態內容的處理流程(註2)

圖二:IIS 6 的 ISAPI Extension 設定

IIS 7 回應 HttpRequest 的運作方式

IIS 7經過大幅度的改造,全新的整合模式改以模組化的方式來處理 HttpRequest,ASP.NET 模組也一併被納入了 HttpRequest 的處理管線中。也就是說,在 IIS 7 的整合模式之下,ASP.NET 模組已經融入到 IIS 的處理流程當中(如圖三),所以不論什麼樣的HttpRequest,開發人員都可以透過實做 IHttpModule,撰寫自訂的 ASP.NET Module來參與整個 Processing 的流程。

圖三:IIS 7 的執行架構

實作 IHttpModule – 計算檔案下載次數

接下來透過一個「計算檔案下載次數」的例子,利用自訂的 HttpModule 類別進行計算,並在 IIS 6 及 IIS 7 的整合模式下執行,用以觀察這兩種模式對於靜態檔案要求的處理上有什麼樣的差異。

一、假想情況:網站中有一個純文字檔,管理人員想統計此檔案總共被下載過多少次。

二、程式概念:

  1. 網站啟動時,設定一全域變數,儲存於 HttpApplicationState 當中,並初始化為 0。
  2. 每次接收到對此檔案的 HttpRequest 時,將全域變數累加 1。

三、程式實作:

Step 1. 使用  Visual Studio,新增一 Web 應用程式,並將專案命名為 DownloadCounting。

點擊放大

圖四:新增專案

Step 2. 開啟專案內的 Default.aspx 並以下內容取代原有內容:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DownloadCounting._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
sample.txt的下載次數:<%=Application["Count"].ToString()%>
</div>

<a href="sample.txt" target="_blank">下載 txt 檔案</a>
</form>
</body>
</html>

Step 3. 加入類別,並命名為 Counting.cs。

點擊放大

圖五:加入新類別

Step 4.  直接將下程式碼取代現有程式碼。

using System;
using System.Web;
using System.IO;

namespace DownloadCounting {
    public class Counting : IHttpModule {
        void IHttpModule.Dispose() {}

        void IHttpModule.Init(HttpApplication context) {
            HttpContext.Current.Application["Count"] = 0;
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }

        void context_BeginRequest(object sender, EventArgs e) {
            string physicallPath = HttpContext.Current.Request.PhysicalPath;
            if (Path.GetFileName(physicallPath) == "sample.txt") {
                int count = Convert.ToInt32(HttpContext.Current.Application["Count"]);
                HttpContext.Current.Application["Count"] = count + 1;
            }
        }
    }
}
		

Step 5. 在根目錄下新增一文字檔,並命名為 sample.txt。

點擊放大

圖六:加入文字檔

Step 6. 在IIS新增一虛擬目錄,並指向此網站。

點擊放大

圖七:新增虛擬目錄 - IIS 6

點擊放大

圖八:新增虛擬目錄 - IIS 7

Step 7. 分別在<httpModules>及<modules>區段加入以下標籤:

<add name="CountingModule" type="DownloadCounting.Counting"/>

Step 8. 執行功能:

  • 開啟瀏覽器,在網址列輸入http://localhost/DownloadCounting/Default.aspx 。
  • 按下頁面下方的超連結(送出下載要求)。
  • Pop up 新視窗之後,在第一個瀏覽器視窗按下重新整理,觀察檔案的下載次數。

四、執行結果:

IIS 6:
畫面中的下載次數會一直保持為 0 次,表示若是靜態檔案的 HttpRequest,則模組內的程式碼並不會執行(如圖 9)。

點擊放大

圖九:IIS 6 的執行畫面

IIS 7:
畫面中的下載次數會確實的持續累加,表示每次回應 HttpRequest 時都會執行模組內的程式碼(如圖 10)。

點擊放大

圖十:IIS 7 的執行畫面

結語

本文使用了一個自訂的 HttpModule 來測試整合模式及傳統模式在處理 HttpRequest 差異。整合模式最大的變革,就是將 ASP.NET 模組也合併在 HttpRequest Processing 的流程當中。在整合模式之下,任何要求的類型都能夠套用到 ASP.NET 模組當中

附註

  1. 在 IIS 6 當中,可藉由設定 ISAPI 的方式,使靜態檔案要求也交由 ASP.NET 模組進行回應。詳細的設定方式可參考 IIS 官網上的文章。網址:http://learn.iis.net/page.aspx/508/wildcard-script-mapping-and-iis-7-integrated-pipeline/
  2. 在 IIS 6 部署 ASP.NET MVC,可參閱:http://blogs.msdn.com/wtchou/archive/2009/09/23/asp-net-mvc-iis6.aspx