Desenvolvimento - ASP. NET

Consumindo serviços WCF no AJAX

Uma das grandes partes do .NET Framework 3.0 foi o WCF - Windows Communication Foundation. Quando ele foi lançado, várias formas de acessar os serviços WCF também foram disponibilizadas.

por Israel Aéce



function doClick(index, numTabs, id) { document.all("tab" + id, index).className = "tab"; for (var i=1; i Uma das grandes partes do .NET Framework 3.0 foi o WCF - Windows Communication Foundation. Quando ele foi lançado, várias formas de acessar os serviços WCF também foram disponibilizadas. Entre as formas, conhecidas como endpoints, podemos citar algumas, tais como: HTTP, TCP e MSMQ. Com a vinda do ASP.NET AJAX, surgiu a necessidade de consumir serviços WCF diretamente dentro deste tipo de aplicação.

Através do Visual Studio .NET 2008 e o .NET Framework 3.5, a Microsoft se preocupou com a necessidade de consumir serviços WCF no AJAX e aproveitou esta oportunidade para criar um binding. Este binding, chamado de WebHttpBinding, trata-se de um novo tipo de binding que permite a criação de um endpoint para ser consumido por aplicações AJAX. É basicamente algo semelhante ao BasicHttpBinding, com a exceção de que os dados são serializados em formato JSON (JavaScript Object Notation). É bom dizer que esta classe está dentro do namespace System.ServiceModel do Assembly System.ServiceModel.Web.dll.

Para possibilitar a chamada de serviços WCF através do AJAX é necessário, primeiramente, a criação da estrutura do serviço, ou seja, a criação da Interface, decoradas com os atributos ServiceContract e OperationContract; além disso, a criação de um arquivo *.svc para que seja possível acessá-lo. Até este momento, não há nada de diferente em relação a criação de um serviço que será exposta via protocolo HTTP, usando como host o IIS. As mudanças começam efetivamente a partir daqui, ou seja, a configuração do endpoint no arquivo Web.Config e do controle ScriptManager.

Como foi mencionado acima, devemos recorrer a utilização do binding webHttpBinding. O único detalhe que você deve se atentar é na configuração do behavior do endpoint, onde devemos informar o elemento enableWebScript para habilitar o acesso via AJAX. O trecho de código abaixo ilustra a configuração do serviço e do endpoint no arquivo Web.Config:

<system.serviceModel>
  <services>
    <service name="Usuario" behaviorConfiguration="SrvBehavior">
      <endpoint
        address="mex"
        binding="mexHttpBinding"
        contract="IMetadataExchange"/>
      <endpoint
        binding="webHttpBinding"
        behaviorConfiguration="EdpBehavior"
        contract="IUsuario"/>
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="SrvBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="false"/>
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <behavior name="EdpBehavior">
        <enableWebScript />
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>
Default.aspx

Uma vez configurado o serviço, chega o momento de consumí-lo no cliente, ou melhor, através do código Javascript. O primeiro passo é definir um controle ScriptManager na página onde deseja consumir o serviço; esse controle gerencia as bibliotecas e arquivos de scripts e, entre outras funcionalidades, a geração de proxies para o consumo de serviços via AJAX. Esse controle possui uma coleção de serviços chamada Services, onde cada um dos elementos, do tipo ServiceReference, corresponde a um serviço que será exposto e consumido pelo cliente.

O próximo passo é, através do código Javascript, invocar o código no cliente. Assim como acontecia com o Client-Side Callbacks, você cria uma função que servirá como ponto de entrada e será disparada através de um evento, também client-side; na implementação desta função, você efetivamente invocará o serviço WCF, mas na verdade é método do proxy, que foi criado pelo controle ScriptManager. O proxy cria os métodos que são disponibilizados pelo serviço, mas adiciona mais três parâmetros, que são: o ponteiro para um método de callback que será disparado quando o método retornar; um ponteiro para um método que será disparado caso alguma exceção for disparada quando o método for executado e, finalmente, um objeto que servirá como contexto e será passado para todos os métodos durante a execução. O código abaixo mostra a página ASPX devidamente configurada para invocar o serviço WCF:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript">
        function ExibirBoasVindas()
        {
            var proxy = new tempuri.org.IUsuario();
            proxy.BoasVindas("Israel", Resultado, null, null);
        }
        
        function Resultado(result)
        {
            alert(result);
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Services>
                <asp:ServiceReference Path="~/UserService.svc" />
            </Services>
        </asp:ScriptManager>
        <input
            id="Button1"
            type="button"
            value="button"
            onclick="javascript:ExibirBoasVindas();" />
    </form>
</body>
</html>
Web.config

Como podemos notar, definimos o serviço WCF (arquivo *.svc) no interior do controle ScriptManager que será responsável por criar, em tempo de execução, o proxy para o consumo via AJAX. Já o tempuri.org trata-se do namespace padrão, qual você pode customizar através do da propriedade Namespace do atributo ServiceContract e ainda, se você desejar visualizar o proxy que é criado, pode acessar o serviço WCF da seguinte forma: http://localhost:1029/Projeto/UserService.svc/js, ou seja, adicionar o /js no final do endereço do serviço. Isso permitirá que você efetue o download do proxy que é gerado em tempo de execução.

Importante: Também temos uma nova factory definida dentro do namespace System.ServiceModel.Activation, chamada WebScriptServiceHostFactory que está presente no .NET Framework 3.5. Definindo essa factory no atributo ServiceHost do arquivo *.svc, elimina qualquer configuração no arquivo Web.Config da aplicação, já que ela configura todos os requisitos necessários (behaviors, binding, etc.) para o consumo do serviço via AJAX.

Chamadas entre domínios

É importante dizer que o objeto XMLHttpRequest não permite efetuar chamadas para serviços que estão fora dos limites do servidor local. Sendo assim, você não poderá referenciar serviços que estão em outros domínios ou sub-domínios e mudança de protocolos ou portas. Podemos, através da imagem abaixo, visualizar essas restrições:

Figura 1 - Invocando serviços além dos limites da aplicação.

Como podemos ver, não podemos invocar qualquer serviço que está além da aplicação local mas, se por algum motivo, desejarmos fazer isso, então devemos proceder da mesma forma que vimos no decorrer deste artigo porém, o serviço WCF local que devemos criar, servirá de proxy para o serviço que está em algum outro local.

Conclusão: Os serviços WCF fornecem uma grande flexibilidade em cenários que precisam, de alguma forma, expor informações ou componentes para que terceiros possam consumí-los. Finalmente, com a vinda do Visual Studio .NET 2008 e o .NET Framework 3.5, podemos agora invocar esses serviços através de aplicações AJAX, garantindo assim uma interatividade muito melhor, sem a necessidade de recorrer a postbacks para a execução de recursos como estes.
Israel Aéce

Israel Aéce - Especialista em tecnologias de desenvolvimento Microsoft, atua como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. Como instrutor Microsoft, leciona sobre o desenvolvimento de aplicações .NET. É palestrante em diversos eventos Microsoft no Brasil e autor de diversos artigos que podem ser lidos a partir de seu site http://www.israelaece.com/. Possui as seguintes credenciais: MVP (Connected System Developer), MCP, MCAD, MCTS (Web, Windows, Distributed, ASP.NET 3.5, ADO.NET 3.5, Windows Forms 3.5 e WCF), MCPD (Web, Windows, Enterprise, ASP.NET 3.5 e Windows 3.5) e MCT.