Logo

dev-resources.site

for different kinds of informations.

Utilizando HttpClient con IHttpClientFactory en .Net 6

Published at
10/21/2022
Categories
spanish
csharp
latam
Author
airarrazabald
Categories
3 categories in total
spanish
open
csharp
open
latam
open
Author
13 person written this
airarrazabald
open
Utilizando HttpClient con IHttpClientFactory en .Net 6

Para los que están entrando o ya llevamos un tiempo en el mundo de .Net y necesitan consumir una api rest, es muy común que hayan utilizado HttpClient para realizarlo. Hay otras librerías como RestSharp que también permiten consumir servicios, pero RestSharp sigue utilizando HttpClient.

Uno de los grandes problemas que nos podemos encontrar al implementar HttpClient es la mala implementación, volviendo nuestra aplicación inestable, como en el siguiente código:



using(var client = new HttpClient())
{
    //Realizamos solicitudes HTTP
}


Enter fullscreen mode Exit fullscreen mode

En este post no profundizaremos en los errores que pueden ocasionarse con una mala implementación, nos centraremos en como realizar una implementación mas limpia y estable con IHttpClientFactory.

Definición de IHttpClientFactory

La documentación de Microsoft nos define lo siguiente:

Se trata de una interfaz que se usa para configurar y crear HttpClient instancias en una aplicación mediante inserción de dependencias (DI). También proporciona extensiones para el middleware basado en Polly a fin de aprovechar los controladores de delegación en HttpClient.

Lo que quiere decir que a través de esta interfaz generaremos instancias que podremos inyectar en nuestro servicio o clase en donde utilizaremos IHttpClientFactory asegurando una mayor estabilidad y de forma centralizada.

Tambien nos menciona Polly, que en resumen es una librería que nos permite realizar reintentos de request cuando el codigo http de un response coincida con algún codigo que le indiquemos. Es mucho mas sencilla su implementación con IHttpClientFactory, pero la política de reintentos ya es material para otro post.

Implementemos la interfaz

Ahora que ya sabemos el concepto básico de IHttpClientFactory, procedamos a implementarlo en el código

Prerequisitos

  • Visual Studio 2022

1. Creando el proyecto

  1. Lo primero es crear un proyecto con la plantilla de tipo ASP .NET Core Web API

  2. El nombre no es relevante pero para esta ocasión será HttpClientApi

  3. Seleccionamos el framework .NET 6.0 y habilitamos compatibilidad con OpenAPI (swagger)

2. Estructura del proyecto

La estructura del proyecto quedar según la siguiente imagen, creando carpetas por cada capa de nuestra aplicación. Esto es solo para efecto de ejemplo, ya que en vez de carpetas podríamos generar librerías de clases por cada capa.

Estructura del proyecto

3. Implementemos IHttpClientFactory

Ya tenemos lista nuestra estructura !!!
Ahora vamos al código

Clases de la capa Models



namespace HttpClientApi.Models;

public class Bird
{
    public string Uid { get; set; }
    public Name Name { get; set; }
    public Images Images { get; set; }
    public Links _Links { get; set; }
    public int Sort { get; set; }
}


Enter fullscreen mode Exit fullscreen mode


namespace HttpClientApi.Models;

public class Images
{
    public string Main { get; set; }
    public string Full { get; set; }
    public string Thumb { get; set; }
}


Enter fullscreen mode Exit fullscreen mode


namespace HttpClientApi.Models;

public class Links
{
    public string Self { get; set; }
    public string Parent { get; set; }
}



Enter fullscreen mode Exit fullscreen mode


namespace HttpClientApi.Models
{
    public class Name
    {
        public string Spanish { get; set; }
        public string English { get; set; }
        public string Latin { get; set; }
    }
}



Enter fullscreen mode Exit fullscreen mode

Ahora  debemos modificar el appsettings.json para dejar la url que consumiremos con nuestro HttpClient:

appsettings.json:



{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Endpoint": {
    "UrlBirds": "https://aves.ninjas.cl/api/birds"
  }
}


Enter fullscreen mode Exit fullscreen mode
  • Agregamos la propiedad Endpoint:UrlBirds donde se encuentra la url.

Para implementar IHttpClientFactory modificaremos el archivo Program.cs

Program.cs:



using HttpClientApi.Services;

var builder = WebApplication.CreateBuilder(args);

var configuration = builder.Configuration;
builder.Services.AddControllers();

builder.Services.AddHttpClient<IBirdsService, BirdsService>(client =>
{
    client.BaseAddress = new Uri(configuration.GetValue<string>("Endpoint:UrlBirds"));
    client.Timeout = TimeSpan.FromSeconds(20);
    client.DefaultRequestHeaders.Add("HEADER_API_KEY", "claveficticia");
});
// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();


Enter fullscreen mode Exit fullscreen mode
  • En el codigo primero traemos la configuración que permitirá traer la url desde appsettings.json


var configuration = builder.Configuration;


Enter fullscreen mode Exit fullscreen mode
  • En el siguiente bloque implementamos IHttpClientFactory


builder.Services.AddHttpClient<IBirdsService, BirdsService>(client =>
{
    client.BaseAddress = new Uri(configuration.GetValue<string>("Endpoint:UrlBirds"));
    client.Timeout = TimeSpan.FromSeconds(20);
    client.DefaultRequestHeaders.Add("HEADER_API_KEY", "claveficticia");
});


Enter fullscreen mode Exit fullscreen mode
  • Con el metodo AddHttpClient le indicamos la interfaz y la clase donde inyectaremos el HttpClient.

  • Luego vamos a asignar tres propiedades BaseAddress, Tiemout, DefaultRequestHeaders

    • BaseAddress: asignamos la url.
    • Timeout: asignamos el máximo tiempo de respuesta de una solicitud.
    • DefaultRequestHeaders: Agregamos una cabecera extra a nuestro Request, que para efectos prácticos puede ser una api key.

Llamando al servicio:

Tenemos una interfaz y una clase en la carpeta Services

IBirdsService:



using HttpClientApi.Models;

namespace HttpClientApi.Services
{
    public interface IBirdsService
    {
        Task<List<Bird>> Get();
    }
}


Enter fullscreen mode Exit fullscreen mode
  • La interfaz con el metodo Get nos permitirá implementar la inyección de dependencia.

BirdsService:



using HttpClientApi.Models;

namespace HttpClientApi.Services
{
    public class BirdsService : IBirdsService
    {
        private readonly HttpClient _httpClient;

        public BirdsService(HttpClient httpClient) => (_httpClient) = (httpClient);

        public async Task<List<Bird>> Get()
        {
            var listBirds = await _httpClient.GetFromJsonAsync<List<Bird>>(_httpClient.BaseAddress);

            return listBirds;
        }
    }


Enter fullscreen mode Exit fullscreen mode
  • La clase BirdsService implementa la interfaz IBirdsService.
  • En el constructor declaramos HttpClient httpClient para que pueda ser inyectado desde el Program.cs como lo vimos en el codigo de mas arriba.

Listo ya tenemos el servicio conectado solo nos falta llamarlo desde el controlador BirdsController



using HttpClientApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace HttpClientApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BirdsController : ControllerBase
    {
        private readonly IBirdsService _birdsService;

        public BirdsController(IBirdsService birdsService) => _birdsService = birdsService;

        [HttpGet]
        public async Task<IActionResult> Get()
        {
            return Ok(await _birdsService.Get());
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

Y listo ahora ya estamos en condiciones de realizar el get  Birds

Conclusiones

  • Como vimos en el ejemplo y por la experiencia que tengo utilizándolo es mucho mas limpio con AddHttpCLient. Por que como vimos en la clase BirdsService en ningún momento declaramos la url, el timeout o si fuera necesario alguna cabecera adicional.
  • Le damos la responsabilidad a la inyección de dependencia que lo haga.
  • Para agregar IHttpClientFactory en este ejemplo lo hicimos directo en el Program.cs pero si quisieras dejar este archivo mas limpio podemos alojar esta configuración en otro archivo .cs, con la implementación ya lista como un metodo estático y solo la llamamos desde Program.cs. Esto es una buena opción cuando necesitas inyectar distintos servicios, es ahi donde nuestro código se nos puede extender.
  • Administra la agrupación y la duración de las instancias de HttpClientMessageHandler subyacentes. La administración automática evita los problemas comunes de DNS (Sistema de nombres de dominio) que se producen al administrar la duración de HttpClient de forma manual. Esto quiere decir que los problemas que indicamos al principio de este post, que nos provocaba trabajar con HttpClient de forma manual del riesgo de solicitudes que queden abiertas y colapso de los sockets, ya no existirían.
latam Article's
30 articles in total
Favicon
Registro 000 - ¿Listo para Flutter? Sigue Mi Aventura en el Desarrollo de una App con Clean Architecture
Favicon
Pro{gramadores}, pro{ductivos} y pro{crastinadores}.
Favicon
Cuidados Esenciales en Go: Cómo utilizar las funciones Marshal() y Unmarshal() de manera segura para JSON
Favicon
¡Go! - Tomando los primeros pasos con el lenguaje Go.
Favicon
Pre-AWS Summit CDMX 2023
Favicon
Acelerando la lectura de datos con Databricks
Favicon
Patrón de diseño: MVC | Explicación completa y simple
Favicon
Conquering the US Market: Tips for Uruguayan Software Companies
Favicon
Mis podcasts Favoritos en 2023
Favicon
¿Qué es GitHub Pages?
Favicon
Building a Second Brain | El mejor libro que leí en 2022
Favicon
LATAM será potencia en Open Source
Favicon
Utilizando HttpClient con IHttpClientFactory en .Net 6
Favicon
Mejorar el rendimiento de mis aplicaciones .Net 6 con REDIS
Favicon
The companies should have a multi-cloud strategy?
Favicon
Beneficios de unirse a la comunidad de AWS Community Builder
Favicon
Cómo responder al "¿Por qué te gustaría trabajar aquí?"
Favicon
Redis en Docker Container
Favicon
¿Por qué se necesitan más AWS Community Builders en Latinoamérica?
Favicon
Las 4+3 Aplicaciones que uso diario en Mac
Favicon
¿Prefieres trabajar con mercenarios o con misioneros?
Favicon
🔑 Habilidad Técnica: 6. Conocimiento de tecnologías complementarias 🧠
Favicon
💙 Habilidad Suave: 1. Comunicación 🗣
Favicon
Cosas que he aprendido dando mentorías a personas que están cambiando de carrera
Favicon
En Tech... ¿Los empleadores valoran la universidad o las habilidades técnicas?
Favicon
🔑 Habilidad Técnica: 5. Emplear Patrones de diseño 📏 📐
Favicon
🔑 Habilidad Técnica: 4. Desarrollo de pruebas automatizadas 🔁
Favicon
🔑 Habilidad Técnica: 3. Control de versiones y code review (Git) 🧑‍💻
Favicon
🔑 Habilidad Técnica: 2. Conocimiento de frameworks 🧱
Favicon
🔑 Habilidad Técnica: 1. Buscar en Internet y Leer el Manual

Featured ones: