为 URL 重写模块开发规则模板
本演练将指导你开发 URL 重写模块的规则模板。 你将创建一个规则模板,该模板可用于生成重写规则,该规则会强制使用网站的特定域。
模板概述
规范域名规则模板可用于简化重写规则的创建,该规则用于强制执行网站的规范域名。 用户可以从“添加规则”对话框中选择此模板:
然后,用户可以提供要使用的域名:
之后,模板将生成重写规则,如下所示:
先决条件
在继续执行本演练之前,建议通过完成文章“如何创建简单的 IIS Manager 模块”中的任务来熟悉 IIS Manager 扩展性的基本概念。
规则模板的 VS2008 项目
此规则模板的完整 Visual Studio 2008 项目可从此处下载。
实现规则模板
为了支持远程管理,所有 IIS Manager UI 组件都遵循特定的设计模式来实现。 模块的实现包含以下部分:
- 客户端用户界面和服务代理
- 用于管理 IIS 配置的服务器端服务
所有特定于用户界面的实现都驻留在客户端上,可能是远程客户端计算机。 实际更改 IIS 配置的所有功能都作为服务在服务器端实现,从而确保它有权访问所有服务器配置 API。 客户端控件通过服务代理与服务交互。
一种良好做法是遵循相同的模式实现规则模板,以便在用户通过 IIS 远程管理器创建规则时,模板有效。 以下部分介绍如何实现规则模板服务和客户端。
实现客户端用户界面
创建模块
首先,需要创建模块,这是客户端中所有扩展性对象的主要入口点。 若要执行该操作:
- 按照“如何创建简单的 IIS Manager 模块”一文中的任务 1 和 2 中所述的步骤创建和配置 Visual Studio 项目。 将项目命名为“CanonicalDomainTemplateClient”。
- 从项目菜单中选择添加引用 ,并添加对位于 \Windows\System32\inetsrv 中的Microsoft.Web.Management.dll 的引用:
- 再次选择 添加引用 并添加对位于 \Program Files\Reference Assemblies\Microsoft\IIS 中的Microsoft.Web.Management.Rewrite.Client.dll的引用。
- 再次选择“添加引用”并添加对 System.Windows.Forms.dll 的引用
- 从“项目”菜单中选择“添加新项”选项。 在“添加新项”对话框中,选择“类”模板,然后键入 CanonicalDomainModule.cs 作为文件的名称。
- 更改代码,使其如下所示:
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 重写规则模板使用的父类。
- 在“项目”菜单中选择“添加新项”选项。 选择类模板并键入 CanonicalDomainFeature.cs 作为文件名。
- 更改代码,使其如下所示:
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;
}
}
}
此代码执行以下操作:
- 定义规则模板的名称和标题
- 将名称、标题和图标传递给基类构造函数,以便在“添加规则”对话框显示所有已注册的规则模板时使用这些名称、标题和图标
- 定义用于呈现模板用户界面的 Run() 方法,即基于 WinForm 的模式对话框 CanonicalDomainForm。 如果在对话框中单击“确定”按钮,则通过调用 Navigate() 方法刷新 URL 重写模块的主 UI 页面。
- 最后,它定义一个帮助程序函数 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 Manager 客户端管道代码都已完成,其余部分为设计和实现规则模板的实际用户界面。 若要完成这些操作,请执行以下步骤:
在“项目”菜单中选择“添加新项”选项。 在“添加新项”对话框中,选择“Windows 窗体”并键入名称 CanonicalDomainForm.cs:
使用 Visual Studio Windows 窗体设计器排列窗体上的控件:
切换到代码视图,并添加将包含对服务代理的引用的类的私有成员:
private CanonicalDomainModuleServiceProxy _serviceProxy;
在同一类中,修改构造函数代码,如下所示:
public CanonicalDomainForm(CanonicalDomainModuleServiceProxy serviceProxy) { _serviceProxy = serviceProxy; InitializeComponent(); }
在同一类中添加将调用服务代理的帮助程序函数,以使用用户指定的参数生成重写规则:
private void GenerateRule(string domainName) { try { _serviceProxy.GenerateRule(domainName); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
为单击“确定”按钮时添加事件处理程序。 在事件处理程序代码中调用帮助程序函数 GenerateRule,将 TextBox 控件的内容作为参数传递。
private void OnOkButtonClick(object sender, EventArgs e) { GenerateRule(_DomainTextBox.Text); }
为规则模板实现服务
若要实现服务,需要创建模块提供程序,这是在 IIS Manager 中注册模块的入口点。 若要执行该操作:
按照“如何创建简单的 IIS Manager 模块”一文中的任务 1 和 2 中所述的步骤创建和配置另一个 Visual Studio 项目。 将项目命名为“CanonicalDomainTemplate”。
从项目菜单中选择添加引用,并将引用添加到位于 \Windows\System32\inetsrv 中的以下程序集:
- Microsoft.Web.Administration.dll
- Microsoft.Web.Management.dll
从“项目”菜单中选择“添加新项”选项。 在“添加新项”对话框中,选择“类”模板,然后键入 CanonicalDomainModuleProvider.cs 作为文件的名称。
更改代码,使其如下所示(请记得将 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。
若要为规则模板创建服务,请执行以下步骤:
- 在“项目”菜单中选择“添加新项”选项。 选择类模板并键入 CanonicalDomainModuleService.cs 作为文件名。
- 更改代码,使其如下所示:
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 Manager 注册规则模板
成功编译规则模板项目并将其放入全局程序集缓存后,需要通过将其信息添加到 administration.config 文件,以将其注册到 IIS Manager。
打开位于 \Windows\System32\inetsrv\config 的 administration.config 文件,并将以下行添加到 <moduleProviders> 部分。 请确保替换 PublicKeyToken:
<add name="CanonicalDomainName" type="CanonicalDomainTemplate.CanonicalDomainModuleProvider, CanonicalDomainTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e4e6d0bc8fe7a06a" />
注意
通过仅将它添加到 moduleProviders 列表,你会注册该模块以仅用于服务器连接。 如果希望为站点连接和应用程序连接启用此模块,请将其添加到以下列表:
<location path=".">
<module>
<add name="CanonicalDomainName" />
</module>
</location>
完成这些步骤后,应能够在 URL 重写模块的“添加规则”对话框中看到“规范域名”规则模板。