Utilizando o Url Routing no WCF

Quando recorremos à uma das templates para a construção de serviços WCF (WCF Service Application ou WCF Service), ambas utilizam arquivos *.svc que representam o endpoint do serviço. Dentro deste arquivo temos apenas uma diretiva chamada @ServiceHost, que instrui o ASP.NET a como compilar o referido serviço.

Abaixo podemos visualizar um exemplo deste arquivo, que em seu atributo Service, permite apontar o tipo do serviço. Já no atributo CodeBehind, corresponde ao arquivo físico que possui a classe que representa o serviço e, finalmente, temos a atributo Factory, que é omitido por padrão, mas que tem a finalidade de criar instâncias da classe que gerencia o serviço (ServiceHost ou alguma de suas derivadas).

<%@ ServiceHost
    Language=”C#”
    Debug=”true”
    Service=”ServicoDeClientes”
    Factory=”System.ServiceModel.Activation.WebServiceHostFactory”
    CodeBehind=”~/App_Code/ServicoDeClientes.cs” %>

No WCF 4.0, a Microsoft incluiu a possibilidade de criarmos serviços WCF sem a necessidade da presença de um arquivo *.svc. Isso eliminará completamente a necessidade deste arquivo. Mas para poder excluir o arquivo, tudo o que precisamos fazer é elencar os serviços no arquivo Web.config, utilizando o sub-elemento serviceActivations, exposto pelo elemento serviceHostingEnvironment:

<system.serviceModel>
  <serviceHostingEnvironment>
    <serviceActivations>
      <add
        relativeAddress=”~/ServicoDeClientes.svc”
        service=”Servicos.ServicoDeClientes”
        factory=”System.ServiceModel.Activation.WebServiceHostFactory”/>
    </serviceActivations>
  </serviceHostingEnvironment>
</system.serviceModel>

Apesar de ainda precisar especifcar o arquivo no relativeAddress, ele não existe fisicamente. Note também que através do atributo service definimos o nome da classe que corresponde ao serviço e, finalmente, como já era de se esperar, podemos utilizar uma factory específica, que já configura o host com tudo o que é necessário para prepará-lo para receber e processar as requisições para uma determina situação. Com isso temos uma aplicação mais simples, onde tudo o que precisamos desenvolver é o contrato (interface) e o serviço (classe), assim como já fazemos com qualquer outro tipo de serviço WCF.

O maior problema desta técnica é a necessidade de ainda precisar informar a extensão do arquivo quando for efetuar uma requisição, e isso não é legal em um modelo REST. Lembre-se de que a funcionalidade que vimos acima, apenas elimina a necessidade do arquivo físico. Remover a extensão *.svc do atributo relativeAddress, não resolverá, pois vamos nos deparar com uma exceção do tipo ConfigurationErrorsException, dizendo que o valor informado no atributo relativeAddress não possui uma extensão válida.

Além do Url Rewrite Module (que já discuti no final deste artigo), temos agora a possibilidade de integrar o sistema de roteamento de URL do ASP.NET aos serviços WCF. Também na versão 4.0 do WCF, a Microsoft incluiu no assembly System.ServiceModel.Activation uma classe chamada ServiceRoute, que permite especificarmos exatamente os mesmos parâmetros que vimos acima e, automaticamente, será processado pelo handler correspondente (ServiceRouteHandler). Com isso, no evento Application_Start do arquivo Global.asax, devemos registrar mais uma rota, essa específica para o nosso serviço:

protected void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.Add(
        new ServiceRoute(
            “ServicoDeClientes”,
            new WebServiceHostFactory(), 
            typeof(Servicos.ServicoDeClientes)));
}

A string que aparece sendo informada no construtor da classe ServiceRoute, define o nome do recurso para qual estaremos efetuando o roteamento. Os outros dois parâmetros refletem as mesmas configurações que vimos acima. Mas ainda é precisa se atentar a um detalhe: se você estiver utilizando um projeto que não vem com o módulo de roteamento de URL configurado, você terá que fazer isso manualmente, assim como eu mostro abaixo:

<system.web>
  <httpModules>
    <add
      name=”UrlRoutingModule”
      type=”System.Web.Routing.UrlRoutingModule, System.Web” />
  </httpModules>
</system.web>

O único detalhe aqui é a necessidade de habilitar o modelo de compatibilidade com o ASP.NET, caso contrário, esta funcionalidade não poderá ser utilizada. Para habilitar isso no contrato, precisamos recorrer ao atributo AspNetCompatibilityRequirementsAttribute, definindo-o como Allowed (para permitir que ele seja exposto por outros tipos de hosts), e depois devemos habilitar a compatibilidade no arquivo de configuração, através do elemento serviceHostingEnvironment, definindo o atributo aspNetCompatibilityEnabled como True. Abaixo é exibido as duas configurações:

namespace Servicos
{
    [AspNetCompatibilityRequirements(
        RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class ServicoDeClientes : IServico
    {
        //…
    }
}

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled=”true” />
</system.serviceModel>

Depois destas configurações, já podemos acessar o serviço diretamente sem informar a extensão *.svc. É importante dizer que isso só é necessário quando você hospeda o seu serviço no IIS, já que as requisições são sempre realizadas para um arquivo físico. Quando você cria um serviço REST e deseja expor através de algum outro host, nada disso será necessário.