O consumo de APIs REST é uma prática extremamente comum nos mais variados tipos de aplicações. Muito deste trabalho consiste no envio de requisições contendo configurações para autenticação como tokens e chaves de acesso, com o consequente recebimento de dados no padrão JSON (o padrão XML representa ainda outra possibilidade).
A implementação de soluções na plataforma .NET não foge a esta regra. No caso específico do .NET Core, temos a classe HttpClient (namespace System.Net.Http), a qual disponibiliza meios para o envio de solicitações HTTP e o posterior tratamento das respostas obtidas.
Este artigo tem por objetivo demonstrar o consumo de APIs REST em uma aplicação ASP.NET Core 1.1. Isto acontecerá através de um exemplo de utilização da Marvel Comics API, um conjunto de recursos gratuitos que permite o acesso a um vasto conteúdo de informações sobre personagens do universo Marvel.
Obtendo o acesso à Marvel Comics API
Para acessar os recursos da Marvel Comics API, serão utilizadas duas chaves: uma pública e outra privada. A geração das mesmas acontecerá por meio do cadastramento de um login no seguinte portal: https://developer.marvel.com/.
Na imagem a seguir é possível observar as informações de uma conta de desenvolvimento para uso da Marvel Comics API. Além das chaves pública e privada, será necessário indicar ainda os domínios de aplicações que utilizarão a API (nota-se ainda um aviso com um limite diário de uso):
A documentação dos diferentes recursos que integram a Marvel Comics API está disponível no seguinte endereço: https://developer.marvel.com/docs.
Esta API faz uso do Swagger para a documentação e teste das funcionalidades existentes, conforme detalhado na próxima imagem:
Exemplo de consumo com o .NET Core
O código-fonte da aplicação apresentada nesta seção já está no GitHub.
A Marvel Comic API será acessada através do seguinte endereço: http://gateway.marvel.com/v1/public/.
Uma classe chamada Personagem será implementada, a fim de facilitar a passagem de informações entre o Controller e a View responsáveis pela exibição de informações:
namespace ExemploMarvelComicsAPI { public class Personagem { public string Nome { get; set; } public string Descricao { get; set; } public string UrlImagem { get; set; } public string UrlWiki { get; set; } } }
A Action Index de HomeController acessará a API da Marvel, empregando para isto uma instância do tipo HttpClient:
- Inicialmente, será configurado o formato utilizado na comunicação (JSON), com isto acontecendo por meio da propriedade DefaultRequestHeaders e de uma instância da classe MediaTypeWithQualityHeaderValue (namespace System.Net.Http);
- Requisições enviadas à API deverão conter como parâmetros um timestamp (sequência de identificação de cada requisição), uma chave pública e um hash criptografado baseado no padrão MD5;
- Para o timestamp será utilizada a propriedade Ticks obtida via data atual do sistema (essa estrutura retornará um valor do tipo long);
- A função GerarHash concatenará o timestamp e as duas chaves (pública e privada), fazendo uso para isto dos tipos Encoding (namespace System.Text), MD5 (namespace System.Security.Cryptography) e BitConverter (namespace System). Como resultado será produzida uma string com o hash esperado pela API;
- A solicitação será enviada à API da Marvel a partir da invocação do método GetAsync do objeto client. Essa operação receberá como parâmetro a URL para consulta à informações de personagens Marvel, estando configurada para retornar detalhes (em inglês) sobre o Capitão América. O resultado desta ação será uma referência do tipo HttpResponseMessage (namespace System.Net.Http);
- A chamada ao método EnsureSuccessStatusCode de HttpResponseMessage fará com que a mensagem recebida seja validada, lançando uma exceção no caso de um eventual problema;
- Ao acionar a operação ReadAsStringAsync via propriedade Content do objeto response será retornada uma string JSON com informações;
- O método DeserializeObject da classe JsonConvert (namespace Newtonsoft.Json) receberá como parâmetro essa string, devolvendo um objeto que será associado à variável dinâmica resultado;
- Uma instância da classe Personagem será finalmente gerada, empregando para isto, dados obtidos através do conteúdo associado à variável resultado. O método View é, então, invocado, recebendo como parâmetro esta última referência.
using System; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Security.Cryptography; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; namespace ExemploMarvelComicsAPI.Controllers { public class HomeController : Controller { public IActionResult Index( [FromServices]IConfiguration config) { Personagem personagem; using (var client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); string ts = DateTime.Now.Ticks.ToString(); string publicKey = config.GetSection("MarvelComicsAPI:PublicKey").Value; string hash = GerarHash(ts, publicKey, config.GetSection("MarvelComicsAPI:PrivateKey").Value); HttpResponseMessage response = client.GetAsync( config.GetSection("MarvelComicsAPI:BaseURL").Value + quot;characters?ts={ts}&apikey={publicKey}&hash={hash}&" + quot;name={Uri.EscapeUriString("Captain America")}").Result; response.EnsureSuccessStatusCode(); string conteudo = response.Content.ReadAsStringAsync().Result; dynamic resultado = JsonConvert.DeserializeObject(conteudo); personagem = new Personagem(); personagem.Nome = resultado.data.results[0].name; personagem.Descricao = resultado.data.results[0].description; personagem.UrlImagem = resultado.data.results[0].thumbnail.path + "." + resultado.data.results[0].thumbnail.extension; personagem.UrlWiki = resultado.data.results[0].urls[1].url; } return View(personagem); } private string GerarHash( string ts, string publicKey, string privateKey) { byte[] bytes = Encoding.UTF8.GetBytes(ts + privateKey + publicKey); var gerador = MD5.Create(); byte[] bytesHash = gerador.ComputeHash(bytes); return BitConverter.ToString(bytesHash) .ToLower().Replace("-", String.Empty); } public IActionResult About() { return View(); } public IActionResult Contact() { return View(); } public IActionResult Error() { return View(); } } }
Na View Index.cshtml serão exibidas as informações obtidas ao acessar a API da Marvel em HomeController:
<h1>Exemplo de utilização - Marvel Comics API</h1> @model Personagem <div style="overflow: hidden; margin-top: 50px;"> <div style="float: left; margin-right: 50px;"> <img src="@Model.UrlImagem" height="200" width="200" /> </div> <div style="margin-left: 50px;"> <h2><a href="@Model.UrlWiki">@Model.Nome</a></h2> <p>@Model.Descricao</p> </div> </div>
Testes
Ao executar a aplicação a partir do Visual Studio 2017, aparecerão informações em inglês sobre o personagem Capitão América: