MSDN Magazine > Home > Issues > 2008 > Launch >  IIS 7.0: 運用端對端擴充性建置 Web 伺服器解決方案
IIS 7.0
運用端對端擴充性建置 Web 伺服器解決方案
Mike Volodarsky

本文探討:
  • IIS 擴充點
  • 建置回應修改模組
  • 新增 IIS 管理員設定
  • 部署模組
本文使用技術:
IIS 7.0、.NET Framework
IIS 7.0 Web 平台在裝載具備豐富功能的應用程式時所支援的應用程式架構技術數量,比先前的 IIS 版本支援數量還多,本身所具備的豐富功能更可讓您立即取用來部署這些應用程式。但是,此時您所見到的 (在 Windows® 安裝程式中) 並不一定就是您所得到的結果。
IIS 7.0 架構主要是用來徹底擴充功能,以便您運用符合自身需求的自訂實作來取代任何一項內建的功能集。因此,IIS 7.0 摒棄了提供外掛程式點的修補作業方式,而改由在公開擴充性模型上實作所有自身的功能來表示充分擴充的承諾。這項設計在平台中隨處可見,從模組化的 Web 伺服器引擎本身到 IIS 管理員主控台的設定系統等俯拾皆是。
在本文中,我將帶您逐步完成共用資源回應修改專案,了解此專案如何透過可設定的回應修改規則即時修改來自 IIS 應用程式的回應,以深入探討 IIS 7.0 擴充性模型。首先,我將利用伺服器的整合式 ASP.NET 擴充性來建置 Web 伺服器模組。接著,我將為 IIS 管理員開發自訂的設定區段並建立自訂的管理頁面,一步步打造出模組的各項部署與管理功能。

擴充 Web 伺服器
IIS 7.0 模組化架構能讓您針對所需的工作負載充分自訂 Web 伺服器功能。您只需安裝應用程式所需的功能,接著產生一台僅執行所需任務的精簡型 Web 伺服器,就可輕易地完成這項工作。
然而,這只是第一步。一般來說,我們所需的 Web 工作負載還需要其他可能尚未內建在 IIS 功能集中的一些功能來配合。或者說,在某些情況下,因為內建的功能彈性不足,導致應用程式本身需要搭配一些自訂的功能集來運作。由於所有的 IIS 7.0 功能都是以公開擴充性 API 為基礎所建置,因此您可以使用最符合您需求的自訂實作項目來取代其中任何一項功能。
IIS 7.0 提供兩個選項供您開發 Web 伺服器模組。首先,您可以使用全新的 C++ 模組 API (大部分的內建功能都是以這個模組為基礎打造的)。此模組 API 會取代 ISAPI 擴充性並篩選掉舊版 IIS 所提供的 API。這項 API 是對 ISAPI 的重大革新,因為它所包含的功能非常豐富,足以支援所有的 IIS 7.0 功能需求,而且大幅提升了程式設計的便利性。如需有關此 API 的革新功能詳細資訊,請造訪:mvolo.com/blogs/serverside/archive/2006/10/07/10-reasons-why-server-development-is-better-with-IIS7.aspx。
再者,IIS 7.0 強調對 ASP.NET 的整合,以方便使用者透過熟悉的 ASP.NET 模組 API 來開發更多 IIS 7.0 模組。在 ASP.NET 整合模式中,這些模組都變成了 IIS 要求處理管線中的一等公民,如 [圖 1] 所示。這樣一來,ASP.NET 模組便可在所有要求處理階段中存取 IIS 內部物件 (例如要求與回應),並處理所有來源類型的要求,而不是僅限於由 ASP.NET 架構所處理的要求。
[圖 1] IIS 7.0 要求處理中的 ASP.NET 模組 (按影像可放大)
這樣一來,例如表單驗證、Login 控制項,以及成員資格服務等功能強大的 ASP.NET 功能便可統一用於整個網站上。如需如何運用 ASP.NET 整合模式為現有應用程式 (非針對 ASP.NET 架構所撰寫) 附加一些價值的深入剖析,請務必參考我為 2008 年 1 月號的 MSDN® Magazine 所撰寫的文章,網址是:msdn.microsoft.com/msdnmag/issues/08/01/PHPandIIS7。
對開發人員來說,ASP.NET 整合模式的真正價值在於能夠使用 Microsoft® .NET Framework 來擴充 IIS Web 伺服器的能力。這個模式對於應用程式的快速發展來說具有重大的意義,因為它能讓您在 .NET Framework、ASP.NET,與其他諸如 Windows Workflow Foundation 等功能豐富的架構上建置應用程式。

回應修改模組
ASP.NET 整合管線可讓 ASP.NET 模組在處理每個要求的期間,執行各式各樣的工作。這些功能包含執行驗證或授權工作,以便在傳出的回應傳送到用戶端之前先行加以修改。
回應修改模組的用途在於執行後者,藉由一群取代規則來即時修改現有的回應。若要這麼做,我們可以充分善用 ASP.NET 回應篩選機制,同時由於執行階段的整合使然,使得這項機制可以針對傳出的回應篩選掉任何內容,包括靜態檔案與 ASP 及 PHP 指令碼。
如果您先前已經開發過 ASP.NET 模組,就會了解到能夠繼續使用一模一樣的 API 來開發 IIS 7.0 之 ASP.NET 模組的優點。事實上,您現有的模組運作方式與在舊版 IIS 的運作方式是一樣的,除非您透過 IIS 7.0 整合模式針對所有要求來執行這些模組。此模組是實作 System.Web.IHttpModule 介面的一個類別,可為一個或多個要求管線事件註冊事件處理常式。回應修改模組也是一樣:
class ResponseModificationModule : IHttpModule
{
  public void Init(HttpApplication app)
  {
    // Wire up the filter in PreRequestHandlerExecute
    app.PreRequestHandlerExecute += 
      new EventHandler(OnPreRequestHandlerExecute);
  }

  public void OnPreRequestHandlerExecute(
    Object source, EventArgs e)
  {
    ...
  }
}
本質上,模組會訂閱 PreRequestHandlerExecute 事件,而此事件剛好就在執行要求處理常式之前發生。OnPreRequestHandlerExecute 方法可用來讀取設定資訊以判斷回應是否具有任何適用的取代規則 (本文稍後將對設定細節有更多的著墨),而且如果真是這樣的話,就會註冊一個回應篩選資料流以便稍後用來篩選傳出的回應,如 [圖 2] 所示。
public void OnPreRequestHandlerExecute(Object source, EventArgs e)
{
  HttpApplication app = (HttpApplication)source;
  HttpContext context = app.Context;

  // Read configuration 
  ResponseModificationConfigurationSection config;
  
  ...

  // Get the list of filters
  ResponseFilterList filters = GetApplicableFilters(context, config);

  // Create the filter and wire it up
  if (null != filters && filters.Count > 0)
  {
    context.Response.Filter = 
      new ChainedBufferedStringResponseFilter(
        context, filters);
  }
}

回應篩選工作是在 ChainedBufferedStringResponseFilter 類別中完成的,此類別的責任是透過回應字元集,然後叫用一個或多個適用此要求的回應篩選條件,將回應位元組轉換為字串。此模組會接著設定 HttpResponse.Filter 屬性,將篩選條件與回應關聯起來。此屬性會接受繼承自 System.IO.Stream 抽象類別的物件,並於稍後利用這些物件來篩選傳出的回應實體內文。
在開發 IIS 整合模式可用的 ASP.NET 模組時,ASP.NET 回應篩選機能剛好是您可以利用的其中一項機制。您也可以重新撰寫 URL、執行要求驗證與授權、修改或發行 Cookie 與回應標頭,與記錄要求等。原本需要搭配原生 ISAPI 開發的工作,現在大部分可以藉由撰寫 ASP.NET 模組來輕易達成。如需建置 IIS 7.0 之 ASP.NET 模組、開發環境選項,以及部署步驟等逐步解說資訊,請造訪:mvolo.com/blogs/serverside/archive/ 2007/08/15/Developing-IIS7-web-server-features-with-the-.NET-framework.aspx。
在開發 IIS 7.0 模組時,您可以運用一些 IIS 功能來協助您進行管理與部署工作。其中一項功能就是在 IIS 7.0 設定檔中指定自訂的模組設定,然後透過應用程式來自動部署該設定,或是使用一些 IIS 7.0 管理工具與 API 來管理這些設定。這麼做對於確保使用者能夠適當設定並管理模組所提供的功能,扮演相當重要的關鍵。

擴充設定
全新的設定系統對於許多使用 IIS 7.0 才能進行的重要部署與管理情況來說,打下了重要的基礎。IIS 7.0 擺脫了以往的以機器為中心的專屬設定存放區角色,改由以結構化 XML 設定檔 (位於與 ASP.NET 設定系統所使用的設定檔相同的位置) 為基礎。此外,IIS 設定資訊的語法與 ASP.NET 設定資訊的語法一模一樣,可以並列放置於 ASP.NET 開發人員非常熟悉且愛用的分散式 web.config 檔案中。
這項設計開啟了許多可能性。首先,它允許應用程式在自身的應用程式內容之外同時指定 IIS 設定資訊,這樣應用程式只需將內容發佈到伺服器便可輕易達到部署的目的。這麼做可確保應用程式運作正常,無需針對每部要部署的伺服器修改以電腦為中心的設定資訊,而且每部伺服器都不需要擁有系統管理員權限。結構化 XML 設定格式,加上將 ASP.NET 設定與 IIS 設定同時放置在單一檔案的能力,讓開發人員能夠非常輕易地撰寫並管理所有與 IIS 相關的設定資訊。使用者可以透過 XML 編輯器 (例如 [記事本] 與 Visual Studio®) 來執行這項工作,或是透過由 IIS 7.0 管理堆疊所提供的設定 API 來加以自動化處理。
還有,IIS 7.0 設定系統可充分擴充,這是它最棒的部分。允許自訂 Web 伺服器功能來發佈設定,以便與 IIS 7.0 設定一同進行設定與管理的功能,在建置完整的 IIS 7.0 解決方案時扮演非常重要的角色。
與 .NET 設定系統不同的是,新增一個全新的 IIS 7.0 設定區段不需要添加任何程式碼,因為所有的 IIS 7.0 設定區段本身已經透過 XML 架構的結構描述來加以定義。事實上,所有內建的 IIS 7.0 設定區段都是使用這項機制來定義的。您可以在 %windir%\system32\inetsrv\config\schema 目錄中的 IIS_Schema.xml 檔案中,找到所有 IIS 設定區段的定義。例如,可允許您針對應用程式設定預設文件的 <defaultDocument> 設定區段,其定義如下:
<sectionSchema name="system.webServer/defaultDocument">
  <attribute name="enabled" type="bool" defaultValue="true" />
  <element name="files">
    <collection addElement="add" clearElement="clear" 
      removeElement="remove" mergeAppend="false">
      <attribute name="value" type="string" isUniqueKey="true"/>
    </collection>
  </element>
</sectionSchema>
這項結構描述會定義屬於設定區段一部分的所有項目與屬性及其型別,以及其他資訊,例如集合定義與屬性驗證行為。如需深入了解結構描述定義的語法,請參閱 IIS_Schema.xml 設定檔上方的註解。

回應修改設定
回應修改模組需要自己的設定區段來設定一系列特定的設定,包括要針對應用程式啟用的篩選規則。若要在 IIS 設定檔中使用此設定區段,首先您必須建立可描述區段結構的結構描述檔 (請參閱 [圖 3])。此檔案會定義 responseModification 區段與其結構,包括啟用的屬性與篩選規則集合以供您加以設定,並運用有關取代目標與取代物等額外資訊來叫用篩選型別。
<configSchema>
  <sectionSchema name="responseModification">
    <attribute name="enabled" type="bool" defaultValue="false" />
    <collection addElement="add" clearElement="clear" 
      removeElement="remove">
      <attribute name="name" type="string" required="true" 
        isUniqueKey="true" validationType="nonEmptyString" />
      <attribute name="conditionType" type="string" required="false" />
      <attribute name="condition" type="string" required="false" />
      <attribute name="replaceType" type="string" required="true" 
        validationType="nonEmptyString" />
      <attribute name="replace" type="string" required="false" />
      <attribute name="replaceWith" type="string" required="false" />
      <attribute name="options" type="string" required="false" />
    </collection>
  </sectionSchema>
</configSchema>

若要安裝此設定區段,您需要執行下列兩個步驟。首先,將包含區段結構描述資訊的 responsemod_schema.xml 檔案複製到 %windir%\system32\inetsrv\config\schema 目錄。接著在伺服器的主要設定檔 applicationHost.config 中,宣告設定區段。如果您希望以程式設計方式來執行此安裝作業,則需要撰寫一些程式碼來執行第二個步驟。
為了簡化 IIS 7.0 設定區段的安裝程序,我特地寫了一個 iisschema.exe 工具,用來自動執行這兩個步驟。如需此工具,請造訪:mvolo.com/blogs/serverside/archive/2007/08/04/IISSCHEMA.EXE-_2D00_-A-tool-to-register-IIS7-configuration-sections.aspx。取得了這項工具後,安裝設定結構描述區段就只需要一個步驟:
IisSchema.exe /install responsemod_schema.xml
現在設定區段結構描述已經安裝好了,而且區段本身也於 applicationHost.config 中宣告完畢,您可以立即開始運用這項結構描述來定義模組的設定資訊。
您可以使用任何一個 IIS 設定工具或 API 來管理此區段的設定,執行步驟就像您在管理任何一個內建的 IIS 7.0 設定區段一樣。例如,我可以使用 AppCmd 這項 IIS 7.0 命令列工具來啟用應用程式的回應修改功能:
%windir%\system32\inetsrv\AppCmd Set Config "Default Web Site/" 
/section:responseModification  /enabled:true 
我也可以將一項規則新增到 responseModification 設定區段的規則集合中:
%windir%\system32\inetsrv\AppCmd Set Config "Default Web Site/" 
"/+[name='StripWhitespace',replaceType=
'Mvolo.ResponseModification.Filters.HtmlDeflate']"
如果您接著開啟位於預設網站根目錄 (通常是 %windir%\inetpub\wwwroot) 中的 web.config 檔,則您會找到下列程式碼:
<configuration>
  <responseModification enabled="true">
    <add name="StripWhitespace" 
      replaceType="Mvolo.ResponseModification.Filters.HtmlDeflate" />
  </responseModification>
</configuration>
如果您曾經修改過應用程式的 web.config 檔來變更模組的設定資訊,然後將其上傳至伺服器的話,則應用程式將會設定來使用新的設定。同理,如果您將應用程式上傳到另一部已安裝設定區段的伺服器的話,則您可以確定應用程式必然會使用所需的設定 (您無須在該伺服器上重新加以設定)。
除了 AppCmd 以外,現在您還可以使用任何一個 IIS 7.0 設定 API 來管理此區段的設定資訊,包括 Managed 的 Microsoft.Web.Administration API、IIS 7.0 Windows Management Instrumentation (WMI) 提供者、IIS 7.0 設定 COM 物件,以及 Windows PowerShell®。除了設定與閱讀此設定資訊之外,您還可以執行任何一項 IIS 7.0 設定系統所支援的管理工作,包括控制將此區段委派給應用程式的方式,以及使用設定加密來保護其內容等等。然而,為了讓此設定資訊發揮功用,您需要能夠從回應修改模組中讀取它。
Microsoft.Web.Administration API 是 IIS 7.0 所推出的全新 .NET Framework API,它可讓程式存取 IIS 7.0 設定資訊。除了允許設定與安裝程式管理設定之外,它同時也是一項可用來從 Managed 模組中讀取設定資訊的 API。
在註冊完設定區段之後,您可以馬上使用此 API 來讀取模組中的設定區段,因為 API 會公開鬆散型別的模型以供讀取設定區段。在您執行這項工作之前,您需要將參考加入 Microsoft.Web.Administration.dll (位於 %windir%\system32\inetsrv 目錄中)。請注意,此 DLL 僅包含在 Windows Vista® 或 Windows Server® 2008 的 IIS 7.0 中,但不包含在 .NET Framework 或 Windows SDK 中。
一旦新增了組件參考之後,我就可以閱讀模組的設定資訊了:
ConfigurationSection section = 
  WebConfigurationManager.GetSection(
    context, 
    "responseModification");

bool enabled = (bool)section["enabled"];
位於 Microsoft.Web.Administration 命名空間的 WebConfigurationManager 類別與位於 System.Web.Configuration 命名空間的 WebConfigurationManager 幾乎是一模一樣的,前者是專門用來取代後者在可讀取 IIS 7.0 設定之 IIS 7.0 Managed 模組中的用途。GetSection 方法可擷取目前 HTTP 要求路徑的設定區段物件。

強型別的設定類別
ConfigurationSection 物件可允許鬆散型別存取任何一個設定區段 (無須撰寫任何額外的程式碼)。您只需從區段物件的索引子中依照名稱來加以擷取,然後將其轉型為預期的型別,便可存取啟用的屬性。
但是,您也可以產生設定區段的強型別包裝函式來提升其功能。您可以使用由 Kanwaljeet Singla (IIS 團隊成員) 所撰寫的工具來快速產生包裝函式,此工具位於:blogs.iis.net/ ksingla/archive/2006/12/04/tool-to-generate-strongly-typed-classes-for-configuration-sections.aspx。這項工具將產生區段的包裝函式類別,如 [圖 4] 所示。此類別只會將基礎的 ConfigurationSection 類別包裝起來,然後提供強型別的屬性來存取基礎設定資料。
class ResponseModificationSection : ConfigurationSection
{
  public bool Enabled
  {
    get { return (bool)this["enabled"]; }
    set { this["enabled"] = value; }
  }

  public ResponseModificationRuleCollection FilterRules
  {
    get 
    { 
      return (ResponseModificationRuleCollection)
        GetCollection(typeof(ResponseModificationRuleCollection)); 
    }
  }
}

如同您從 Enabled 屬性的實作範例中所見一般,包裝設定屬性的方法非常簡潔扼要。包裝子項目與子集合需要進一步實作分別繼承自 ConfigurationElement 與 ConfigurationCollection 的包裝函式類別 (未顯示),方法與實作區段包裝函式類似。
在產生了包裝函式類別之後,您可以將其編譯至個別的組件並在您的模組專案中加以參考,或是單純將其新增為原始程式碼檔案。這樣一來,您就可以型別安全的方式讓模組存取設定區段:
ResponseModificationSection section =
  (ResponseModificationSection)WebConfigurationManager.GetSection(
    context, 
    "responseModification", 
    typeof(ResponseModificationSection)
  );

bool enabled = section.Enabled;
同理,您也可以型別安全方式,開始存取位於每個規則項目上的回應修改規則集合與屬性。這樣一來,您就可以針對設定區段輕鬆地進行程式設計,將弱型別資料存取時常見的型別安全出錯機會降到最低。同時,由於工具會自動產生用來存取基礎資料的所有程式碼,因此您可以將 Visual Studio 設定為每次編譯專案時,就從設定結構描述檔自動建置包裝函式類別。之後,管理設定區段結構描述的變更就會變得非常簡單。

擴充 IIS 管理員
到目前為止,我已經向大家示範如何建立回應修改模組,以及如何加以啟用以讀取可控制其行為的自訂設定區段。您可以將此設定與其他 IIS 設定資訊存放在同一個設定檔中、可以和 web.config 檔案中的應用程式一起部署,也可以使用各種工具與 API (包括 AppCmd.exe 和 Microsoft.Web.Administration) 來加以管理。
到這個階段,您已經可以在任何一個 IIS 環境中部署回應修改模組並加以適當設定了。但是,您也可以為 IIS 管理員主控台提供自訂管理經驗來提升其功能。這麼做有許多好處。它能讓系統管理員透過 IIS 管理員主控台輕鬆地設定模組,完全不需要直接編輯設定檔或是使用任何一項較低階的工具與 API。同時,它可讓您透過 IIS 管理員的遠端管理功能以充分運用其 Web Management Service (WmSvc) 來管理模組設定資訊。
與其他同樣支援遠端管理功能的工具不同的是,IIS 管理員的遠端管理架構可提供下列幾項重要的優勢。首先,它能讓不具有伺服器系統管理員身分的使用者來管理他們可掌控的網站與應用程式。再者,IIS 管理員的遠端機制透過 HTTPS,而不是 DCOM 來運作,後者比較容易透過企業防火牆暴露行蹤。這兩項優勢讓 IIS 管理員成為適合針對 IIS 網站用來進行遠端委派管理的工具,特別是在共用的 Web 裝載環境中更是如此。
依據 IIS 7.0 的設計精神,IIS 管理員所提供的可擴充架構可做為大部分內建的 IIS 管理員功能基礎。為了協助執行遠端管理工作,每項管理功能都包含下列兩大部分:在 IIS 管理員中提供 UI 經驗的用戶端元件,以及負責提供實際管理服務的伺服器端元件。
伺服器端服務分別位於 IIS 管理員中 (在本機管理情況下) 或是 Web Management Service 中 (在遠端管理情況下)。在遠端管理情況中,IIS 管理員會針對用戶端機器上的 IIS 管理員元件,以及在目標伺服器機器上的 WmSvc 中執行的服務,處理兩者之間的必要通訊。

建立服務
用戶端與伺服器元件通常會實作為兩個不同且互不參考的 .NET 組件。用戶端與伺服器元件之間的所有通訊,都是藉由 IIS 管理員 ModuleServiceProxy 抽象層使用弱型別的屬性包與基本的 .NET 型別來交換必要資訊而達成的。
伺服器組件通常包含 Microsoft.Web.Management.Server.ModuleProvider 類別的實作 (以針對各項服務與用戶端模組執行必要的註冊),以及 Microsoft.Web.Management.Server.ModuleService 類別的實作 (以將服務方法公開來執行必要的管理工作)。
我的 Mvolo.ResponseModificationUI.Server.dll 組件包含了 ResponseModificationModuleProvider 類別,後者負責註冊 ResponseModificationModuleService 服務類別與用戶端 ResponseModificationModule 模組類別,如 [圖 5] 所示。
public sealed class ResponseModificationModuleProvider : 
  ConfigurationModuleProvider
{
  public override Type ServiceType
  {
    get { return typeof(ResponseModificationModuleService); }
  }

  public override ModuleDefinition 
    GetModuleDefinition(IManagementContext context)
  {
    return new ModuleDefinition(Name,
      "Mvolo.ResponseModification.UI.Client.ResponseModificationModule,"+
      "Mvolo.ResponseModificationUI.Client," +
      "Version=1.0.0.0, Culture=neutral," +
      "PublicKeyToken=309ac0e1b5482072");
  }

  protected override string ConfigurationSectionName
  {
    get { return "responseModification"; }
  }
}

ResponseModificationModuleService 類別係衍生自 ConfigurationModuleProvider 類別,後者會依據基礎設定區段的委派狀態,提供內建的支援以控制 IIS 管理員功能委派。您所需要做的,就是供應設定區段名稱 responseModification,然後 IIS 管理員就會視任何一個特定的設定路徑區段是否已鎖定或解除鎖定來自動切換功能的委派狀態。Microsoft.Web.Management 架構所提供的其他一些 ModuleProvider 基底類別可支援 IIS 管理員工具的各種不同委派情況。
GetModuleDefinition 方法會傳回將來會在用戶端上執行個體化的 IIS 管理員模組型別,以便註冊必要的 IIS 管理員 UI 元件,例如管理頁面本身。
請注意,用戶端的 ResponseModificationModule 類別型別是一個字串,而不是 Type 物件,因為伺服器組件可能無法參考日後將載入遠端用戶端機器之 IIS 管理員中的用戶端組件。這個缺點是因為用戶端與伺服器元件可能會在不同的程序中執行,而且無法共用自訂型別所導致。
ResponseModificationModuleService 類別會負責實作管理功能並公開服務方法,以便由 IIS 管理員中的管理頁面所叫用 (請參閱 [圖 6])。
public sealed class ResponseModificationModuleService : ModuleService
{
  [ModuleServiceMethod]
  public ArrayList GetFilterRules()
  {
    ArrayList items = new ArrayList();

    ResponseModificationSection section = 
      (ResponseModificationSection)ManagementUnit.Configuration
        .GetSection("responseModification",
          typeof(ResponseModificationSection));

    foreach (ResponseModificationRuleElement rule in section.Rules)
    {
      items.Add(GetPropertyBag(rule));
    }

  return items;
  }
  ...
}  

GetFilterRules 方法是該服務所公開的數項方法之一,而此服務會透過設定系統以及其他可能位於伺服器本機上的資源來執行管理工作。此服務一律在伺服器上執行個體化,因此它一定會運用本機資源,而且不需要擔心遠端管理情況中需要存取不同資源的問題。請注意,我目前再次使用 Microsoft.Web.Administration API 來存取 responseModification 設定區段,而且使用針對模組所建立的強型別 ResponseModificationConfigurationSection 包裝函式來存取設定。
ManagementUnit 屬性是本機伺服器的一個中央進入點,用以公開一系列允許存取設定系統的物件與其他由 Microsoft.Web.Management 架構所建立且以伺服器為中心的管理物件,以協助進行伺服器管理工作。在本機設定管理工作的最佳實務上,服務實作應該一律使用管理單元,而不是建立自己的設定系統。
GetFilterRules 之類的方法可以使用 ArrayList 之類的基本型別將資訊轉接至用戶端元件,藉此將資訊傳回用戶端。同時,您無法透過在伺服器或用戶端組件中定義的強型別類別來進行通訊,因為這些類別原本就有不同的用途,而且不應該彼此互相參考。ResponseModificationModuleService 同時可定義類似 GetFilterRules 的其他服務方法,包括 EditFilterRule、AddFilterRule,與 DeleteFilterRule,以支援回應修改模組頁面可能會要求的必要管理操作。

建立模組頁面
用戶端元件可定義由 IIS 管理員工具提供給使用者的實際 GUI 管理功能。用戶端組件通常包含下列類別的實作:
  • Microsoft.Web.Management.Client.Module 類別,負責註冊任何必要的 IIS 管理員頁面與其他 UI 擴充功能。
  • Microsoft.Web.Management.Client.ModulePage 類別,說明 IIS 管理員所顯示的實際管理頁面。
  • Microsoft.Web.Management.Client.ModuleServiceProxy 類別,提供用戶端元件一個本機 Proxy 類別以叫用由 ModuleService 所公開的服務方法。
Mvolo.ResponseModificationUI.Client.dll 組件包含 ResponseModificationModule 類別,如 [圖 7] 所示 (請勿與負責在 IIS 要求處理管線中提供模組服務的實際 IHttpModule 類別混淆),可在 IIS 管理員中註冊所有需要的 UI 元件時提供主要進入點。此類別會註冊 ResponseModificationModulePage 類別,以描述實際的管理頁面。
public sealed class ResponseModificationModule : Module
{
  protected override void Initialize(IServiceProvider serviceProvider, 
    ModuleInfo moduleInfo)
  {
    base.Initialize(serviceProvider, moduleInfo);

    IControlPanel controlPanel =
      (IControlPanel)GetService(typeof(IControlPanel));

    controlPanel.RegisterPage(
      new ModulePageInfo(this,
      typeof(ResponseModificationModulePage),
      Resources.PageTitle,
      Resources.PageDescription,
      null,
      null,
      Resources.PageText
      ));
  }
}

在每一次使用 IIS 管理員進行管理連線的生命週期當中,會建立一個模組實作,以針對連線註冊所有必要的管理頁面與 UI 項目。ResponseModificationModule 會註冊 ResponseModificationModulePage 類別,後者可定義管理頁面的內容。
老實說,我並不熱衷於 GUI 程式設計,而是比較喜歡撰寫不需要介面開發的低階伺服器程式碼。還好,Microsoft.Web.Management 架構提供了一系列基底類別與支援類別供我實作一些看起來很普通的管理頁面,包括可供我用在 ResponseModificationModulePage 的 Microsoft.Web.Management.Client.Win32.ModuleListPage 類別。
此類別可提供內建的清單檢視以便檢視並管理項目清單,包括排序清單並與清單項目互動。我只需要進行最少的自訂作業就可以建立包含一份回應修改規則清單的管理頁面 (請參閱 [圖 8] 的中央面板)。
[圖 8] IIS 管理員中的回應修改頁面 (按影像可放大)
接下來,我會建立一份動作清單並顯示於右側面板中,以便允許新增、編輯並移除回應修改規則。我採用 Microsoft.Web.Management.Client.TaskList 類別的優點來建立這份工作清單 (如 [圖 8] 中的右側面板所示)。
我只需要稍加修改,就可以產生回應修改功能,如 [圖 8] 所示。您可以在回應修改架構的原始程式碼中檢視 UI 細節。
初始頁面的建立,乃至由動作面板所觸發的新增、編輯與刪除作業,都可藉由叫用 ResponseModificationModuleServiceProxy 類別上的方法來執行,後者可針對下列模組服務所公開的模組方法提供本機 Proxy:
public sealed class ResponseModificationModuleServiceProxy : 
  ModuleServiceProxy
{
  public ArrayList GetFilterRules()
  {
    return (ArrayList)Invoke("GetFilterRules");
  }

  public void AddFilterRule(PropertyBag bag)
  {
    Invoke("AddFilterRule", bag);
  }

  ...
} 
IIS 管理員會透過通訊通道 (可能是本機共用記憶體通道或是遠端伺服器的 HTTPS 通道),自動將模組服務 Proxy 類別的呼叫轉接至關聯的模組服務。

部署擴充功能
若要部署 IIS 管理員擴充功能,請注意您必須先在伺服器上的 IIS 管理員設定檔中 (%windir%\system32\inetsrv\config\administration.config) 註冊模組提供者類型。[圖 9] 所示的設定預設會註冊並啟用模組提供者,以便用於所有網站上。請注意,構成擴充功能的用戶端與伺服器組件 (Mvolo.ResponseModificationUI.Server.dll 與 Mvolo.ResponseModificationUI.Client.dll) 兩者必須同時註冊到全域組件快取中 (GAC),因此必須具備強式名稱且經過簽署。這是安裝 IIS 管理員擴充功能的必要條件。
<moduleProviders>
  ...

  <!-- Mvolo ResponseModification -->
  <add name="ResponseModification" 
    type="Mvolo.ResponseModification.UI.Server
        .ResponseModificationModuleProvider, 
      Mvolo.ResponseModificationUI.Server, 
      Version=1.0.0.0, Culture=neutral, 
      PublicKeyToken=895e90205a14f2aa, 
      processorArchitecture=MSIL" />
</moduleProviders>

<!-- For all Sites -->
<location path=".">
  <modules>
    ...
    <add name="ResponseModification" />
  </modules>
</location>

當您透過 IIS 管理員來進行伺服器的遠端管理時,每次當用戶端組件不存在用戶端時,該工具就會自動提示使用者下載用戶端組件,而這項機制目前僅適用於使用來自 iis.net/ downloads/?tabid=34&g=6&i=1524 網站上的遠端 IIS 管理員工具並從 Windows Vista SP1、Windows XP,或 Windows Server 2003 用戶端來管理 Windows Server 2008 上的 IIS 7.0 的情況。在接受此安裝之前,請務必同時信任您所連接的伺服器與 IIS 管理員擴充功能出版者,否則安裝時可能會允許未受信任的程式碼使用您的使用者帳戶權限在您的機器上執行。

整合一切
在部署了模組並安裝好設定區段結構描述與 IIS 管理員擴充功能之後,回應修改功能已經大致就緒了。您現在可以針對伺服器上任何一個應用程式啟用其功能,並使用任何一項 IIS 7.0 設定工具與 API 來加以設定。
此外,您可以使用 IIS 管理員工具,同時針對本機伺服器與遠端伺服器上的應用程式快速管理其回應修改規則。透過 IIS 管理員委派支援,您甚至可以設定哪位使用者可以針對某部伺服器上的特定網站遠端建立並管理回應修改規則。
為了實際示範回應修改功能,[圖 10] 說明了我如何為 Qdig 影像圖庫應用程式設定規則 (詳細說明請參閱 msdn.microsoft.com/msdnmag/issues/08/01/PHPandIIS7)。[圖 11] 說明了我如何在不修改應用程式的實際原始程式碼情況下,使用回應修改架構所提供的 Mvolo.ResponseModification.Filters.RegExReplace 篩選條件聰明地將頁首與頁尾內容插入網站的所有頁面中。
<responseModification enabled="true">
  <add name="Header" 
    conditionType=
      "Mvolo.ResponseModification.Conditions.ContentTypeCondition"
    condition="text/html" 
    replaceType="Mvolo.ResponseModification.Filters.RegExReplace" 
    replace="&lt;body([^>]*)>" 
    replaceWith="&lt;body$1>&lt;h1 align=&quot;center&quot;>
      Welcome to my gallery!&lt;/h1>" 
    options="IgnoreCase" />
  
  <add name="Footer" 
    conditionType=
      "Mvolo.ResponseModification.Conditions.ContentTypeCondition"
    condition="text/html" 
    replaceType="Mvolo.ResponseModification.Filters.RegExReplace" 
    replace="&lt;/body>" 
    replaceWith="&lt;h3 align=&quot;center&quot;>
      Copyright mvolo 2007&lt;/h3>&lt;/body>" 
    options="IgnoreCase"  />
 </responseModification>

[圖 11] 使用回應修改來修改回應 
您也可以使用回應修改模組,藉由實作取代篩選條件輕鬆地實作任何數量的自訂內容插入、超連結替換,與其他回應修改配置工作。接著,您可以針對這些篩選條件進行全域部署,或是搭配應用程式一起部署,然後透過 responseModification 設定區段中的設定規則來加以設定。

自己動手操作
當您不可能藉由修改應用程式的原始程式碼 (這麼做會比即時修改回應要來得有效率多了) 來獲致相同的結果時,只要運用回應修改功能就可以創造出許多不一樣的變化。例如,我同時透過這項功能,將小型指令碼插入 HTML 回應中以將影像標籤變更為使用高度壓縮的影像版本,然後使用高品質的影像版本即時加以取代以針對連線速度緩慢的用戶端提供較快的回應速度,進而提升其瀏覽品質。這項功能同時運用了自訂影像處理常式,以透過 Microsoft Windows 影像元件 API 並針對靜態影像提供具有任何所需壓縮層級的 JPEG 影像。[圖 11] 說明了實際的結果,包括頁首、頁尾,與預先載入的低品質影像 (就在影像使用較高解析度版本自動取代之前載入)。
即時修改回應不管是在 CPU 的資源使用還是記憶體的需求上都是一件浩大的工程,因為必須同時配置多重大型的緩衝區才足夠存放回應的轉換版本。由於這項工作的資源損耗極大,因此在實際執行的網站上,必須視使用的回應修改篩選條件類型與數量,以及應用程式的效能需求才能決定是否要執行這項工作。
如需深入了解使用回應修改架構的詳細資訊,您應該直接從回應修改開發網站 (www.mvolo.com/responsemod) 下載這個架構與其原始程式碼。在您了解了回應篩選條件的運作方式,而且已經可以在效能需求與資源負擔的平衡考量下開始運用這些條件時,請在回應修改開發網站上尋找更多可用的範例加以參考。如需深入了解 IIS 7.0 擴充功能的詳細資訊,請務必造訪 iis.net 與我的部落格 (mvolo.com),這個部落格內容是專為開發與使用 IIS 7.0 所撰寫的。

Mike Volodarsky 是 Microsoft Web 平台與工具小組的技術專案經理。過去這四年來,他一直在推動 ASP.NET 2.0 和 IIS 7.0 核心功能集的設計與開發。現在,他則專注於協助客戶在 Windows Server 2008 中運用這些技術所帶來的強大功能。

Page view tracker