URL Rewrite Module 用のルール テンプレートの開発

Ruslan Yakushev

このチュートリアルでは、URL Rewrite Module のルール テンプレートを開発する方法について説明します。 Web サイトに対して特定のドメインの使用を強制する、書き換えルールの生成に使用できるルール テンプレートを作成します。

テンプレートの概要

[Canonical Domain Name] (正規ドメイン名) ルール テンプレートを使用すると、Web サイトに正規ドメイン名を強制するために使用される書き換えルールの作成を簡略化できます。 ユーザーは、このテンプレートを [Add rule(s)] (ルールの追加) ダイアログから選択できます。

[標準ドメイン名] が選択されている [ルールの追加] ダイアログのスクリーンショット。

続いて、ユーザーは使用するドメイン名を指定できます。

[標準ドメイン名] ダイアログで指定された [www.mysite.com] のスクリーンショット。

その後に、そのテンプレートで以下のように書き換えルールを生成します。

ドメイン名、URL、条件、およびアクションのセクションを含む [ルールの編集] ウィンドウのスクリーンショット。

前提条件

このチュートリアルを進める前に、記事「単純な IIS マネージャー モジュールを作成する方法」のタスクを完了して、IIS マネージャーの拡張性の基本的な概念を理解しておくことをお勧めします。

ルール テンプレートの VS2008 プロジェクト

このルール テンプレートの Visual Studio 2008 プロジェクト全体をこちらからダウンロードできます。

ルール テンプレートを実装する

リモート管理をサポートするために、すべての IIS マネージャー UI コンポーネントが特定の設計パターンに従って実装されます。 モジュールの実装は、次の部分から構成されます。

  • クライアント側のユーザー インターフェイスとサービス プロキシ
  • IIS 構成を管理するためのサーバー側サービス

すべてのユーザー インターフェイス固有の実装はクライアント側に置かれ、場合によってはそれがリモート クライアント コンピューターになります。 IIS 構成に実際に変更を加えるすべての機能はサーバー側にサービスとして実装されるため、すべてのサーバー構成 API にアクセスできます。 クライアント側のコントロールでは、サービス プロキシを介してサービスと対話します。

ユーザーが IIS リモート マネージャーを使用してルールを作成するときにテンプレートが機能するよう、同じパターンに従ってルール テンプレートを実装することをお勧めします。 次のセクションでは、ルール テンプレート サービスおよびクライアントを実装する方法について説明します。

クライアント側ユーザー インターフェイスを実装する

モジュールを作成する

まず、モジュールを作成する必要があります。これは、すべての拡張性オブジェクトのクライアント内でのメイン エントリ ポイントです。 その手順を次に示します。

  1. 記事「単純な IIS マネージャー モジュールを作成する方法」のタスク 1 と 2 で説明されている手順に従って、Visual Studio プロジェクトを作成して構成します。 プロジェクトに "CanonicalDomainTemplateClient" という名前を付けます。
  2. [プロジェクト] メニューから [Add References] (参照の追加) を選択し、\Windows\System32\inetsrv にある Microsoft.Web.Management.dll への参照を追加します。
  3. もう一度 [Add References] (参照の追加) を選択し、\Program Files\Reference Assemblies\Microsoft\IIS にある Microsoft.Web.Management.Rewrite.Client.dll への参照を追加します。
  4. [Add Reference] (参照の追加) をもう一度選択し、System.Windows.Forms.dll への参照を追加します
  5. [プロジェクト] メニューからオプション [新しい項目の追加] を選択します。 [新しい項目の追加] ダイアログ ボックスで、クラス テンプレートを選択し、ファイルの名前として「CanonicalDomainModule.cs」と入力します。
  6. 以下のようにコードを変更します。
using System;
using Microsoft.Web.Management.Server;
using Microsoft.Web.Management.Client;
using Microsoft.Web.Management.Iis.Rewrite;

namespace CanonicalDomainTemplate
{
    internal class CanonicalDomainModule: Module
    {
        protected override void Initialize(IServiceProvider serviceProvider, ModuleInfo moduleInfo)
        {
            base.Initialize(serviceProvider, moduleInfo);

            IExtensibilityManager extensibilityManager = (IExtensibilityManager)GetService(typeof(IExtensibilityManager));

            extensibilityManager.RegisterExtension(typeof(RewriteTemplateFeature), new CanonicalDomainFeature(this)); 
        }
    }
}

このコードでは、クラス CanonicalDomainFeature (ルール テンプレート機能を実装します) の新しいインスタンスを初期化します。 このクラスのインスタンスは、RewriteTemplateFeature 型の拡張機能の登録に使用されます。この型が、すべてのルール テンプレートの派生元です。

書き換えテンプレート機能を作成する

ルール テンプレートを実装するクラスを定義する場合、このクラスを RewriteTemplateFeature クラスから派生させる必要があります。 これは、すべての URL 書き換えルール テンプレートで使用される親クラスです。

  1. [プロジェクト] メニューの [新しい項目の追加] オプションを選択します。 クラス テンプレートを選択し、ファイル名として「CanonicalDomainFeature.cs」と入力します。
  2. 以下のようにコードを変更します。
using System;
using Microsoft.Web.Management.Client;
using Microsoft.Web.Management.Iis.Rewrite;
using System.Windows.Forms;
using System.Collections;

namespace CanonicalDomainTemplate
{
    class CanonicalDomainFeature: RewriteTemplateFeature
    {
        private const string FeatureTitle = "Canonical Domain Name";
        private const string FeatureDescription = "Creates a rewrite rule for enforcing canonical domain name for your web site";

        public CanonicalDomainFeature(Module module)
            : base(module, FeatureTitle, FeatureDescription, Resource.domain_icon16, Resource.domain_icon32)
        {
        }

        public override void Run()
        {
            CanonicalDomainModuleServiceProxy serviceProxy = 
                 (CanonicalDomainModuleServiceProxy)Connection.CreateProxy(this.Module, 
                                                                           typeof(CanonicalDomainModuleServiceProxy));
            CanonicalDomainForm form = new CanonicalDomainForm(serviceProxy);
            form.StartPosition = FormStartPosition.CenterParent;
            if (form.ShowDialog() == DialogResult.OK)
            {
                Navigate(GetPageType("Rewrite"));
            }
        }

        /// <summary>
        /// Returns the main page for the specified module
        /// </summary>
        private Type GetPageType(string moduleName)
        {
            IControlPanel controlPanel = (IControlPanel)GetService(typeof(IControlPanel));
            Module module = (Module)Connection.Modules[moduleName];

            if (module != null)
            {
                ICollection pageInfos = controlPanel.GetPages(module);

                foreach (ModulePageInfo pageInfo in pageInfos)
                {
                    if (pageInfo.IsEnabled && !pageInfo.PageType.IsAssignableFrom(typeof(IModuleChildPage)))
                    {
                        return pageInfo.PageType;
                    }
                }
            }

            return null;
        }
    }
}

このコードでは、次のことが行われます。

  1. ルール テンプレートの名前とタイトルを定義します
  2. 名前、タイトル、アイコンを基底クラスのコンストラクターに渡し、[Add rule(s)] (ルールの追加) ダイアログにすべての登録済みルール テンプレートが表示されるときにそれらが使用されるようにします
  3. テンプレート ユーザー インターフェイス (WinForm ベースのモーダル ダイアログの CanonicalDomainForm) のレンダリングに使用する Run() メソッドを定義します。 このダイアログで [OK] ボタンをクリックすると、Navigate() メソッドを呼び出して URL Rewrite Module のメイン UI ページが更新されます。
  4. 最後に、指定されたモジュールのメイン ページの取得に使用されるヘルパー関数 GetPageType を定義します。

サービス プロキシを定義する

リモート クライアントからサービスを呼び出すには、サービス プロキシを指定する必要があります。 これを行うには、CanonicalDomainModuleServiceProxy.cs という名前の別のファイルをプロジェクトに追加し、その中のコードを以下のように変更します。

using System;
using Microsoft.Web.Management.Client;
using Microsoft.Web.Management.Server;

namespace CanonicalDomainTemplate
{
    class CanonicalDomainModuleServiceProxy : ModuleServiceProxy
    {

        public void GenerateRule(string domainName)
        {
            Invoke("GenerateRule", domainName);
        }
    }
}

GenerateRule メソッドの実際のサービス実装は、後で追加されます。

ルール テンプレート ダイアログを実装する

ここで、IIS マネージャーのすべてのクライアント側組み込みコードが完了したので、残りの部分として、ルール テンプレートの実際のユーザー インターフェイスを設計して実装します。 これを行うには、次の手順に従います。

  1. [プロジェクト] メニューの [新しい項目の追加] オプションを選択します。 [新しい項目の追加] ダイアログで、[Windows Form] (Windows フォーム) を選択し、「CanonicalDomainForm.cs」という名前を入力します。
    Windows フォーム テンプレートが選択されている [新しい項目の追加] ダイアログのスクリーンショット。

  2. Visual Studio の Windows フォーム デザイナーを使用して、フォームにコントロールを配置します。
    Visual Studio ウィンドウ フォーム デザイナーの新しいフォームのスクリーンショット。

  3. コード ビューに切り替え、サービス プロキシへの参照を含むことになる、そのクラスのプライベート メンバーを追加します。

    private CanonicalDomainModuleServiceProxy _serviceProxy;
    
  4. 同じクラスで、以下のようにコンストラクター コードを変更します。

    public CanonicalDomainForm(CanonicalDomainModuleServiceProxy serviceProxy)
    {
       _serviceProxy = serviceProxy;
       InitializeComponent();
    }
    
  5. 同じクラスで、サービス プロキシを呼び出してユーザー指定のパラメーターで書き換えルールを生成する、ヘルパー関数を追加します。

    private void GenerateRule(string domainName)
    {
        try
        {
            _serviceProxy.GenerateRule(domainName);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    
  6. [OK] ボタンがクリックされたときのためのイベント ハンドラーを追加します。 イベント ハンドラー コードでヘルパー関数 GenerateRule を呼び出し、TextBox コントロールの内容をパラメーターとして渡します。

    private void OnOkButtonClick(object sender, EventArgs e)
    {
        GenerateRule(_DomainTextBox.Text);
    }
    

ルール テンプレートのサービスを実装する

サービスを実装するには、モジュール プロバイダーを作成する必要があります。これは、IIS マネージャーでモジュールを登録するためのエントリ ポイントです。 その手順を次に示します。

  1. 記事「単純な IIS マネージャー モジュールを作成する方法」のタスク 1 と 2 で説明されている手順に従って、もう 1 つの Visual Studio プロジェクトを作成して構成します。 プロジェクトに "CanonicalDomainTemplate" という名前を付けます。

  2. [プロジェクト] メニューから [Add References] (参照の追加) を選択し、\Windows\System32\inetsrv にある次のアセンブリへの参照を追加します。

    1. Microsoft.Web.Administration.dll
    2. Microsoft.Web.Management.dll
  3. [プロジェクト] メニューからオプション [新しい項目の追加] を選択します。 [新しい項目の追加] ダイアログ ボックスで、クラス テンプレートを選択し、ファイルの名前として「CanonicalDomainModuleProvider.cs」と入力します。

  4. 以下のようにコードを変更します (PublicKeyToken は必ず CanonicalDomainTemplate.Client.dll アセンブリの公開キー トークンに置き換えます)

namespace CanonicalDomainTemplate
{
    internal sealed class CanonicalDomainModuleProvider : ModuleProvider
    {
        public override string FriendlyName
        {
            get
            {
                return Resource.ModuleFriendlyName;
            }
        }

        public override Type ServiceType
        {
            get {
                 return typeof(CanonicalDomainModuleService);
            }
        }

        public override ModuleDefinition GetModuleDefinition(IManagementContext context)
        {
            if (context != null && string.Compare(context.ClientUserInterfaceTechnology, 
            "System.Windows.Forms.Control", StringComparison.OrdinalIgnoreCase) != 0)
            {
                return null;
            }

            return new ModuleDefinition(Name, "CanonicalDomainTemplate.CanonicalDomainModule,
                                               CanonicalDomainTemplate.Client,Version=1.0.0.0,Culture=neutral,
                                               PublicKeyToken={your key}");
        }

        public override bool SupportsScope(ManagementScope scope)
        {
            return true;
        }
    }
}

このコードでは、すべての種類の接続 (サーバー、サイト、アプリケーション) をサポートする ModuleProvider を作成し、CanonicalDomainModule というクライアント側モジュールを登録します。 また、サーバー側で書き換えルールの生成に使用されるモジュール サービス CanonicalDomainModuleService の種類も登録します。

ルール テンプレートのサービスを作成するには、次の手順に従います。

  1. [プロジェクト] メニューの [新しい項目の追加] オプションを選択します。 クラス テンプレートを選択し、ファイル名として「CanonicalDomainModuleService.cs」と入力します。
  2. 以下のようにコードを変更します。
using System;
using System.Collections.Generic;
using Microsoft.Web.Management.Server;
using Microsoft.Web.Administration;

namespace CanonicalDomainTemplate
{
    class CanonicalDomainModuleService : ModuleService
    {

        [ModuleServiceMethod]
        public void GenerateRule(string domainName)
        {
            string sectionPath = "system.webServer/rewrite/rules";
            
            if (ManagementUnit.ConfigurationPath.PathType == ConfigurationPathType.Server)
            {
                sectionPath = "system.webServer/rewrite/globalRules";
            }

            ConfigurationSection rulesSection = ManagementUnit.Configuration.GetSection(sectionPath);
            ConfigurationElementCollection rulesCollection = rulesSection.GetCollection();

            ConfigurationElement ruleElement = rulesCollection.CreateElement("rule");
            ruleElement["name"] = @"Canonical domain for " + domainName;
            ruleElement["patternSyntax"] = @"Wildcard";
            ruleElement["stopProcessing"] = true;

            ConfigurationElement matchElement = ruleElement.GetChildElement("match");
            matchElement["url"] = @"*";

            ConfigurationElement conditionsElement = ruleElement.GetChildElement("conditions");

            ConfigurationElementCollection conditionsCollection = conditionsElement.GetCollection();

            ConfigurationElement addElement = conditionsCollection.CreateElement("add");
            addElement["input"] = @"{HTTP_HOST}";
            addElement["negate"] = true;
            addElement["pattern"] = domainName;
            conditionsCollection.Add(addElement);

            ConfigurationElement actionElement = ruleElement.GetChildElement("action");
            actionElement["type"] = @"Redirect";
            actionElement["url"] = @"http://" + domainName + @"/{R:1}";
            actionElement["appendQueryString"] = true;
            rulesCollection.Add(ruleElement);

            ManagementUnit.Update();
        }
    }
}

このコードでは、正規ドメインにリダイレクトするためのルールを作成します。

ヒント

書き換えルールを生成するためのコードをすばやく取得するには、IIS 7.0 以降用の構成エディターを使用します。これは Administration Pack for IIS に含まれています。 書き換えルールを作成するためのコードの生成方法の詳細については、こちらの記事を参照してください。

ルール テンプレートを IIS マネージャーに登録する

ルール テンプレート プロジェクトが正常にコンパイルされ、グローバル アセンブリ キャッシュに入れられたら、その情報を administration.config ファイルに追加し、それを IIS マネージャーに登録する必要があります。

\Windows\System32\inetsrv\config にある administration.config ファイルを開き、次の行を <moduleProviders> セクションに追加します。 PublicKeyToken は必ず置き換えます。

<add name="CanonicalDomainName" type="CanonicalDomainTemplate.CanonicalDomainModuleProvider, CanonicalDomainTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e4e6d0bc8fe7a06a" />

Note

これを moduleProviders の一覧のみに追加すると、このモジュールはサーバー接続の場合にのみ登録されます。 このモジュールをサイト接続とアプリケーション接続でも有効にする場合は、次の一覧に追加します。

<location path=".">
   <module> 
     <add name="CanonicalDomainName" />
   </module>
</location>

これらの手順が完了すると、URL Rewrite Module の [Add Rule(s)] (ルールの追加) ダイアログに [Canonical Domain Name] (正規ドメイン名) ルール テンプレートが表示されます。