Consumindo RESTful WebServices em C# com WCF e JSON (parte 1/2)

Introdução

Faz realmente muito tempo que não escrevo um artigo sobre desenvolvimento de sistemas mais técnico. Quem me conhece, sabe do meu passado bem próximo de linguagens como Pascal, Delphi, Java e C#. Já escrevi muitos artigos quando trabalhava na Borland, e alguns deles sobre WebServices. WebServices, lembram? Aquela tecnologia super moderna que permite a publicação e consumo de serviços e metadados (WSDL) via Web trafegando pacotes em XML? Pois é… super moderno não?

Na verdade, não. Apesar de se ainda suportar WebServices SOAP por aí, a tendência da Web 2.0 é a de se manter as coisas o mais simples e fáceis possíveis (KISS, entende?). Além disso, com o advento do AJAX e do browser como a plataforma cliente preferida da Web 2.0, o consumo de XMLs passou a ser uma coisa um pouco, por assim dizer, pesada para ser feita em AJAX, que normalmente faz uso de JavaScript.

Este conjunto de novos requisitos tecnológicos fez surgir dois novos “animais” magrinhos para a implementação de serviços via web, que estão rapidamente suplantando os WebServices SOAP convencionais (e gordinhos):

  • WebServices RESTful (versus SOAP-based)
  • JSON (versus XML)

Este é o primeiro de dois artigos que exploram as capacidades do WCF para comunicação com RESTFul WebServices e JSON.

WebServices RESTful

O protocolo SOAP é extremamente rico e cheio de funcionalidades. Via SOAP você consegue descrever objetos e mensagens de forma fortemente tipada, utilizando XML. Contudo, a infraestrutura para suporte a WebServices SOAP é bem pesada e, como já citei, pouco aderente a clientes “leves” como JavaScript rodando em um browser.

Com o objetivo de tornar a invocação de métodos remotos e de troca de dados um processo mais leve, surgiu o conceito de WebServices RESTful. Estes WebServices não seguem um protocolo complexo como o SOAP, mas devem seguir as características REST definidas por Roy T. Fielding. Basicamente, WebServices RESTFul são stateless e acessados a partir de operações HTTP padrão (GET, POST, PUT, DELETE) e retornam qualquer conteúdo (normalmente XML, JSON ou outro mime type).

Outra característica interessante desse tipo de WebServices é a de que a infraestrutura existente de servidores web pode ser utilizada, sem a necessidade de se incluir application servers, gateways, proxies, etc. (contudo, não há proibição de usá-los). O melhor é que servidores web existentes (Apache, IIS, etc.) suportam caching, autenticação, criptografia, etc.  sem grande necessidade de programação ou configuração, o que aumenta a performance e diminui a necessidade de recursos dos serviços.

JSON

Como uma alternativa ao XML, Douglas Crockford criou o JSON, que se tornou um RFC oficial (RFC 4627). A sua sintaxe é bem mais leve que o XML e é facilmente “parseavel” por qualquer linguagem de desenvolvimento. Baseia-se em um subset do JavaScript. Segue um exemplo de um bloco JSON:

  1: {"menu": {
  2:   "id": "file",
  3:   "value": "File",
  4:   "popup": {
  5:     "menuitem": [
  6:       {"value": "New", "onclick": "CreateNewDoc()"},
  7:       {"value": "Open", "onclick": "OpenDoc()"},
  8:       {"value": "Close", "onclick": "CloseDoc()"}
  9:     ]
 10:   }
 11: }}

WCF – Acessando a API do Twitter


Como exemplo de uso de WebServices RESTful com JSON, vou utilizar a api do Twitter, mais especificamente a chamada “statuses/public_timeline”.


Para começar, em seu Visual Studio 2008 ou Visual C# 2008 Express, crie um projeto Console.


Adicione referências aos assemblies abaixo:



  • System.ServiceModel.dll
  • System.ServiceModel.Web.dll

Ótimo! Estamos prontos para definir o contrato de dados


Definido o contrato de dados


Vamos utilizar o atributo DataContract para definir nosso “contrato de dados” com o serviço “statuses/public_timeline” em uma nova classe assim:

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: using System.ServiceModel;
  6: using System.Runtime.Serialization;
  7: 
  8: namespace TwitterClientPlayground
  9: {
 10:     [DataContract]
 11:     public class Status
 12:     {
 13:         [DataMember(Name = "text")]
 14:         public string text {get; set;}
 15: 
 16:         [DataContract]
 17:         public class User
 18:         {
 19:             [DataMember(Name = "screen_name")]
 20:             public string screenName {get; set;}
 21:         }
 22:         [DataMember (Name="user")]
 23:         public User user { get; set; }
 24: 
 25: 
 26:     }
 27: }

Você pode ver acima que a classe é uma classe C# como qualquer outra, com anotações em seus membros. A anotação “DataContract” define que a classe deve ser utilizada como contrato de dados pelo WCF. “DataMember” define membros do contrato de dados.


Uma questão interessante é que quando estamos utilizando uma “nested class”, esta também precisa ser marcada com “DataContract” (ver a classe “User” acima).


Definindo o contrato de serviço


O contrato de serviços é equivalente a um “stub” SOAP criado pelo “Add Web Reference” do IDE. Segue o nosso exemplo abaixo:

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: using System.ServiceModel;
  6: using System.ServiceModel.Web;
  7: 
  8: namespace TwitterClientPlayground
  9: {
 10:     [ServiceContract]
 11:     public interface ITwitterClient
 12:     {
 13:         [OperationContract]
 14:         [WebGet(
 15:             ResponseFormat = WebMessageFormat.Json,
 16:             UriTemplate="statuses/public_timeline.json"
 17:             )]
 18:         List<Status> Statuses_PublicTimeLine();
 19:     }
 20: }

O atributo “ServiceContract” define uma interface que irá ser utilizada pelo WCF como contrato de serviços entre o cliente e o servidor. “OperationContract” define uma operação e “WebGet” indica que a operação (método) será equivalente a uma chamada HTTP GET e permite que configuremos detalhes como o formato da resposta em ResponseFormat(no caso, JSON) e o fragmento da URI para acesso ao serviço em UriTemplate. A UriTemplate suporta parâmetros (entre chaves {}), que devem ter o mesmo nome do parâmetro do método sendo anotado, quando a operação do serviço assim o requerer. No caso, “statuses/public_timeline” não aceita parâmetros.


Conclusão


Por enquanto, neste artigo, procurei explicar os conceitos de WebServices RESTful e JSON, bem como a definição de contratos WCF para o consumo deste tipo de WebServices. No próximo artigo, iremos finalmente utilizar os contratos aqui definidos para efetuarmos chamadas ao WebService do Twitter.


Até lá!

1 comentários:

Vinicius Câmara disse...

Olá Daniel,
Parabéns pelo Blog. Excelentes artigos.

Meu nome é Vinicius Câmara e certa vez você visitou a empresa em que trabalhava para um serviço de consultoria Borland (Delphi).
Gostaria de saber se você ainda desempenha este papel, mesmo fora da Borland.
Aguardo o seu retorno

Obrigado,

Email: vinicius.camara@isiengenharia.com.br