Desenvolvendo o modelo de regra para o módulo de regravação de URL
por Ruslan Yakushev
Esse passo a passo orientará você sobre como desenvolver um modelo de regra para o módulo regravação de URL. Você criará um modelo de regra que pode ser usado para gerar uma regra de reescrita que impõe o uso de um domínio específico para um site da Web.
Visão geral do modelo
O modelo de regra Nome de Domínio Canônico pode ser usado para simplificar a criação de uma regra de reescrita que é usada para impor o nome de domínio canônico para um site. Os usuários podem escolher esse modelo na caixa de diálogo "Adicionar regra(s)":
Em seguida, os usuários podem fornecer um nome de domínio que desejam usar:
Depois disso, o modelo gerará uma regra de reescrita como abaixo:
Pré-requisitos
Antes de prosseguir com este passo a passo, é recomendável familiarizar-se com os conceitos básicos de extensibilidade do Gerenciador do IIS concluindo as tarefas no artigo "Como criar um módulo simples do Gerenciador do IIS".
Projeto VS2008 para o modelo de regra
O projeto completo do Visual Studio 2008 para este modelo de regra está disponível para download aqui.
Implementando um modelo de regra
Para dar suporte ao gerenciamento remoto, todos os componentes da interface do usuário do Gerenciador do IIS são implementados seguindo um determinado padrão de design. A implementação de um módulo consiste nessas partes:
- Interface do usuário do lado do cliente e proxy de serviço
- Serviço do lado do servidor para gerenciar a configuração do IIS
Toda a implementação específica da interface do usuário reside em um lado do cliente, que pode ser um computador cliente remoto. Todas as funcionalidades que realmente fazem alterações na configuração do IIS são implementadas como um serviço no lado do servidor, garantindo assim que ela tenha acesso a todas as API de configuração do servidor. Os controles do lado do cliente interagem com o serviço por meio do proxy de serviço.
É uma boa prática implementar modelos de regra seguindo o mesmo padrão, para que os modelos funcionem quando os usuários criam regras por meio do Gerenciador Remoto do IIS. As seções a seguir descrevem como implementar o serviço de modelo de regra e o cliente.
Implementando uma interface do usuário do lado do cliente
Criar um módulo
Primeiro, você precisará criar um módulo, é o principal ponto de entrada no cliente para todos os objetos de extensibilidade. Para fazer isso:
- Crie e configure um projeto do Visual Studio seguindo as etapas descritas nas tarefas 1 e 2 do artigo "Como criar um módulo simples do IIS Manager". Nomeie o projeto como "CanonicalDomainTemplateClient".
- Selecione Adicionar Referências no menu Projeto e adicione referências ao Microsoft.Web.Management.dll localizado em \Windows\System32\inetsrv:
- Selecione Adicionar Referência novamente e adicione referência a Microsoft.Web.Management.Rewrite.Client.dll localizado em \Arquivos de Programas\Assemblies de Referência\Microsoft\IIS.
- Selecione Adicionar Referência novamente e adicione referência a System.Windows.Forms.dll
- Selecione a opção Adicionar Novo Item no menu Projeto. Na caixa de diálogo Adicionar Novo Item, selecione o modeloClasse e digite CanonicalDomainModule.cs como o nome do arquivo.
- Altere o código para que ele fique como abaixo:
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));
}
}
}
Esse código inicializa uma nova instância de uma classe CanonicalDomainFeature, que implementará a funcionalidade de modelo de regra. A instância dessa classe é usada para registrar uma extensão do tipo RewriteTemplateFeature, que é um tipo do qual todos os modelos de regra são derivados.
Criar um recurso de modelo de regravação
Ao definir uma classe que implementa o modelo de regra, você precisará derivar essa classe da classe RewriteTemplateFeature. É uma classe pai que é usada por todos os modelos de regra de reescrita de URL.
- Selecione a opção Adicionar Novo Item no menu Projeto. Selecione o modelo de classe e digite CanonicalDomainFeature.cs como o nome do arquivo.
- Altere o código para que ele fique como abaixo:
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;
}
}
}
Este código faz o seguinte:
- Define o nome e o título do modelo de regra
- Passa o nome, o título e os ícones para o construtor de classe base para que eles sejam usados quando a caixa de diálogo "Adicionar regra(s)" exibir todos os modelos de regra registrados
- Define o método Run() usado para renderizar a interface do usuário do modelo, que é a caixa de diálogo modal baseada em WinForm CanonicalDomainForm. Se o botão OK for clicado na caixa de diálogo, a página principal da interface do usuário do módulo Regravação de URL será atualizada chamando o método Navigate().
- Por fim, ele define uma função auxiliar GetPageType que é usada para obter a página principal do módulo especificado.
Definir um proxy de serviço
Para um cliente remoto chamar um serviço, é necessário fornecer um proxy de serviço. Para fazer isso, adicione outro arquivo ao seu projeto chamado CanonicalDomainModuleServiceProxy.cs e altere o código nele para ver como abaixo:
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);
}
}
}
A implementação real do serviço para o método GenerateRule será adicionada posteriormente.
Implementar a caixa de diálogo de modelo de regra
Agora, que todo o código de conexão do lado do cliente do Gerenciador do IIS foi feito, resta projetar e implementar a interface do usuário real para o modelo de regra. Para fazer isso, execute estas etapas:
Selecione a opção Adicionar Novo Item no menu do projeto. Na caixa de diálogo Adicionar Novo Item, selecione "Formulário do Windows" e digite o nome CanonicalDomainForm.cs:
Use o designer de formulários do Visual Studio para organizar controles no formulário:
Alterne para o modo de exibição de código e adicione o membro privado da classe que conterá uma referência a um proxy de serviço:
private CanonicalDomainModuleServiceProxy _serviceProxy;
Na mesma classe, modifique o código do construtor como abaixo:
public CanonicalDomainForm(CanonicalDomainModuleServiceProxy serviceProxy) { _serviceProxy = serviceProxy; InitializeComponent(); }
Na mesma classe, adicione a função auxiliar que chamará o proxy de serviço para gerar a regra de reescrita com os parâmetros especificados por um usuário:
private void GenerateRule(string domainName) { try { _serviceProxy.GenerateRule(domainName); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Adicione um manipulador de eventos para quando o botão OK for clicado. No código do manipulador de eventos, invoque a função auxiliar GenerateRule, passando o conteúdo do controle TextBox como um parâmetro.
private void OnOkButtonClick(object sender, EventArgs e) { GenerateRule(_DomainTextBox.Text); }
Implementando um serviço para o modelo de regra
Para implementar um serviço, você precisará criar um provedor de módulo, que é um ponto de entrada para registro de módulos no Gerenciador do IIS. Para fazer isso:
Crie e configure outro projeto do Visual Studio seguindo as etapas descritas nas tarefas 1 e 2 do artigo "Como criar um módulo simples do IIS Manager". Nomeie o projeto como "CanonicalDomainTemplate".
Selecione Adicionar Referências no menu Projeto e adicione referências aos seguintes assemblies localizados em \Windows\System32\inetsrv:
- Microsoft.Web.Administration.dll
- Microsoft.Web.Management.dll
Selecione a opção Adicionar Novo Item no menu Projeto. Na caixa de diálogo Adicionar Novo Item, selecione o modelo Classe e digite CanonicalDomainModuleProvider.cs como o nome do arquivo.
Altere o código para que ele fique como abaixo (não se esqueça de substituir PublicKeyToken pelo token de chave pública do assembly 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;
}
}
}
Esse código cria um ModuleProvider que dá suporte a todos os tipos de conexões (Servidor, Site e Aplicativo) e registra um módulo do lado do cliente chamado CanonicalDomainModule. Além disso, ele registra o tipo do serviço de módulo CanonicalDomainModuleService que é usado em um lado do servidor para gerar regras de regravação.
Para criar um serviço para o modelo de regra, siga essas etapas:
- Selecione a opção Adicionar Novo Item no menu Projeto. Selecione o modelo de Classe e digite CanonicalDomainModuleService.cs como o nome do arquivo.
- Altere o código para que ele fique como abaixo:
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();
}
}
}
Esse código cria uma regra para redirecionamento para o domínio canônico.
Dica
para obter rapidamente o código e gerar regras de regravação, use o Editor de Configuração para IIS 7.0 e posterior, que está incluído no Pacote de Administração para IIS. Consulte esse artigo para obter mais informações sobre como gerar código para a criação de regras de regravação.
Registrando o modelo de regra no Gerenciador do IIS
Depois que o projeto de modelo de regra tiver sido compilado com êxito e colocado no Cache de Assembly Global, você precisará registrá-lo no Gerenciador do IIS adicionando suas informações ao arquivo administration.config.
Abra o arquivo administration.config localizado em \Windows\System32\inetsrv\config e adicione a linha a seguir à seção <moduleProviders>. Substitua PublicKeyToken:
<add name="CanonicalDomainName" type="CanonicalDomainTemplate.CanonicalDomainModuleProvider, CanonicalDomainTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e4e6d0bc8fe7a06a" />
Observação
Ao adicioná-lo apenas à lista de moduleProviders, você está registrando o módulo somente para conexões de servidor. Se você quiser que esse módulo seja habilitado para conexões de site, bem como conexões de aplicativo, adicione-o à seguinte lista:
<location path=".">
<module>
<add name="CanonicalDomainName" />
</module>
</location>
Depois que essas etapas forem concluídas, você poderá ver o modelo de regra "Nome de Domínio Canônico" na caixa de diálogo Adicionar Regras do módulo regravação de URL.