.NET

18 ago, 2017

Consumo de APIs em .NET Core: utilizando a Marvel Comics API

Publicidade

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:

Referências

Conteúdos gratuitos sobre ASP.NET Core, .NET Core e C# 7.0