ASP. NET Core Web API -  Usando Refit


 Neste artigo veremos como usar a biblioteca Refit para realizar a comunicação entre APIs na plataforma .NET simplificando o código.

A biblioteca Refit, criada por Paul Betts, é uma blioteca REST inspirada na biblioteca Retrofit que permite representar uma API REST em uma interface e que pode ser usada na plataforma .NET (.NET Core, Xamarin, etc. )

Você pode verificar o código fonte completo da Refit aqui: https://github.com/paulcbetts/refit.

Um dos motivos que o faria usar a biblioteca Refit é que ela é simples, com um código limpo, fácil de entender e manter e tem como objetivo facilitar o consumo de APIs REST.

Para mostrar como ela funciona vamos supor que precisamos consumir um serviço de uma API REST, pode ser qualquer API aderente ao padrão REST. Para este artigo eu vou usar a API de exemplo do meu curso Web API Essencial na Udemy e que esta publicada no endereço: https://catalogo.macoratti.net/index.html

Nesta API os endpoints para acessar os serviços de Categorias estão abertos e assim podemos consumir os endpoints desta API.

Os endpoints expostos por esta API são:

HTTP URL Dados do cliente Retorno
GET /api/{v}/Categorias Sem dados Todas as categorias no formato JSON
GET /api/{v}/Categorias/{id} O id da categoria A categoria do id que foi enviado como parâmetro
POST /api/{v}/Categorias O objeto categoria no formato JSON A nova categoria criada no formato JSON
PUT /api/{v}/Categorias/{id} O id da categoria e objeto categoria no formato JSON Nada
DELETE /api/{v}/Categorias/{id} O id da categoria Nada

Esta API usa o model Categoria :

public class Categoria
{
    public int CategoriaId { get; set; }
    public string? Nome { get; set; }
    public string? ImagemUrl { get; set; }
}

Para consumir esta API usando a abordagem padrão e de forma correta, teríamos que criar um projeto (API, MVC, Console) onde deveríamos registrar o serviço do HttpClientFactory, definir a interface do serviço e sua implementação para consumir os endpoints e usar este serviço em um controlador ou classe de cliente.

No entanto podemos usar a biblioteca Refit e economizar código, e, para mostrar isso, eu vou criar um projeto Web API no VS 2022 chamado RefitApi que vai consumir estes endpoints usando a Refit.

A biblioteca Refit expõe um método de extensão chamado AddRefitClient que retorna IHttpClientBuilder, que permite construir um HttpClient tipado, e assim, a Refit se beneficia de todas as vantagens do IHttpClientFactory.

Para fazer isso temos que :

Criando o projeto Web API

Crie um novo projeto ASP .NET Core Web API chamado RefitApi usando as configurações a seguir:

A seguir vamos criar no projeto as pastas Models e Services e a seguir vamos incluir o pacote Refit.HttpClientFactory.

Na pasta Models vamos criar uma classe Categoria para receber as informações que vamos consumir.

public class Categoria
{
    public int CategoriaId { get; set; }
    public string? Nome { get; set; }
    public string? ImagemUrl { get; set; }
}

Na pasta Services vamos criar a interface ICategoriaRefitService que representa o serviço que, usando os recursos do Refit,  vai consumir os endpoints da API.

using Refit;
using RefitApi.Models;

namespace RefitApi.Services;

public interface ICategoriaRefitService
{
    [Get("/api/1/categorias")]
    Task<IEnumerable<Categoria>> GetCategorias();

    [Get("/api/1/categorias/{id}")]
    Task<Categoria> GetCategoriaId(int id);

    [Post("/api/1/categorias")]
    Task<Categoria> AddCategoria(Categoria categoria);

    [Put("/api/1/categorias/{id}")]
    Task UpdateCategoria(int id,[Body] Categoria categoria);

    [Delete("/api/1/categorias/{id}")]
    Task<Categoria> RemoveCategoria(int id);
}

Neste código estamos definindo os endpoints da API que desejamos acessar usando anotações Get, Post, Put e Delete onde os  parâmetros da chamada, tanto os da URL quanto o corpo da requisição, são definidos como parâmetros do método.

Vamos armazenar a Uri da API que desejamos consumir no arquivo appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ServiceUri": {
    "CategoriasApiUrl": "https://catalogo.macoratti.net/"
  }

}

 

Agora vamos configurar o uso do Refit na classe Program

...
var apiBaseUrl = builder.Configuration["ServiceUri:CategoriasApiUrl"];

builder.Services
    .AddRefitClient<ICategoriaRefitService>()
     .ConfigureHttpClient(c => c.BaseAddress = new Uri(apiBaseUrl));

...

Neste código obtemos o endereço Uri da API que vamos consumir definida no arquivo appsettings.json, e usando o método de extensão AddRefitClient<T>, configuramos o serviço do HttpClient.

Criando o controlador para consumir o API

Temos tudo pronto e já podemos criar o controlador RefitApiController onde vamos injetar uma instância do serviço representada pela interface ICategoriaRefitService. (Note que não precisamos implementar esta interface.)

using Microsoft.AspNetCore.Mvc;
using RefitApi.Models;
using RefitApi.Services;

namespace RefitApi.Controllers;

[Route("[controller]")]
[ApiController]
public class RefitApiController : ControllerBase
{
    private readonly ICategoriaRefitService _categoriaRefitService;

    public RefitApiController(ICategoriaRefitService categoriarefitService)
    {
        _categoriaRefitService = categoriarefitService;
    }

    [HttpGet("categorias")]
    public async Task<IActionResult> GetTodasCategorias()
    {
        var result = await _categoriaRefitService.GetCategorias();

        if (result is null)
            return BadRequest();

        return Ok(result);
    }

    [HttpGet("categorias/{id}")]
    public async Task<IActionResult> GetCategoriaPorId(int id)
    {
        var result = await _categoriaRefitService.GetCategoriaId(id);

        if (result is null)
            return BadRequest();

        return Ok(result);
    }

    [HttpPost("categorias")]
    public async Task<Categoria> CreateCategoria([FromBody] Categoria categoria)
    {
        var result = await _categoriaRefitService.AddCategoria(categoria);

        return result;
    }

    [HttpPut("categorias/{id}")]
    public async Task<ActionResult> UpdateCategoria(int id, [FromBody] Categoria categoria)
    {
        if (categoria.CategoriaId != id)
            return BadRequest("Ids não conferem");

        try
        {
            await _categoriaRefitService.UpdateCategoria(id, categoria);
            return Ok(categoria);
        }
        catch (Exception)
        {
            return BadRequest();
        }
    }

    [HttpDelete("categorias/{id}")]
    public async Task<IActionResult> RemoveCategoria(int id)
    {
        var result = await _categoriaRefitService.RemoveCategoria(id);

        if (result is null)
            return BadRequest();

        return Ok(result);
    }
}

Executando o projeto iremos obter os endpoints exibidos na interface do Swagger a partir dos quais estamos consumindo a API Categorias:

Vimos assim um exemplo básico de utilização da biblioteca Refit que você deve considerar no seu arsenal de ferramentas para tratar com a comunicação entre serviços na plataforma .NET.

Pegue o código do projeto aqui: RefitApi.zip

"Portanto nós também, pois que estamos rodeados de uma tão grande nuvem de testemunhas, deixemos todo o embaraço, e o pecado que tão de perto nos rodeia, e corramos com paciência a carreira que nos está proposta"
Hebreus 12:1

Referências:


José Carlos Macoratti