Programación, Tecnología y Más...

Programación, Tecnología y Más...

Como Consumir Apis en ASP.NET Core (IHttpClientFactory)

Cuando programas consumir apis es algo que tendrás que hacer muy seguido ya que prácticamente esto se ha vuelto un estándar para conectar aplicaciones. 

Cuando programas en Net Core puedes usar la clase HttpClient para consumir apis pero esta es recomendable usarla cuando realizas pequeñas aplicaciones. Incluso microsoft recomienda usarla en aplicaciones de consola de corta duración o similares.

A Partir de la versión 2.1 de net core microsoft introdujo IHttpClientFactory que viene a resolver todo estos problemas que se podían tener con HttpClient, puedes revisar todos los beneficios que esta trae en la documentación de microsoft  IHttpClientFactory.

Hay varias maneras de usar IHttpClientFactory en nuestros proyectos en este articulo estaré mostrándote uno de los más fáciles y que se usa mucho en la actualidad, llamado Name Clients(clientes nombrados).

Para este ejemplo estaré usando el proyecto que usamos en el artículo anterior en el que aprendimos a usar pruebas a unitarias a proyectos web api en el cual tenemos una pequeña api que cuenta con 2 endpoints uno get para listar empleados y otros post para agregar un empleado Como Hacer Pruebas Unitarias en .Net Core C#.

Lo primero que haremos es dentro de la solución del ejemplo anterior crear un nuevo proyecto de tipo aspnet mvc core al cual nombraremos Employees.Front



Luego de crear el proyecto en nuestro appsettings.json agregaremos un nuevo tag en donde agregaremos la url de nuestra api que consumiremos, en nuestro caso como usaremos la del ejemplo anterior usaremos la ulr en donde se ejecuta nuestra api de employees de manera local.


Como el proyecto lo cree con la versión 6 de .net en nuestra clase Program.cs configuraremos nuestro HttpClient que usaremos( si usas versiones anteriores a la 6 esto lo harias en Startup.cs)
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();


builder.Services.AddHttpClient("EmployeesApi", config =>
{
    config.BaseAddress = new Uri(builder.Configuration["ServicesUrl:Employees"]);
});


var app = builder.Build();

//...
Lo que estamos haciendo en el código anterior es crear un cliente nombrado de httpclient llamado EmployeesApi al cual le configuramos la uri de la api que es leída del appsetting. 
De esta manera cuando usemos este cliente este ya vendrá con la url de nuestra api (puedes definir más configuraciones).

Agregaremos una carpeta Dtos la cual tendrá 3 claseses.
  • GenericResponse: Nos servirá para obtener la respuesta de la api.
  • EmployeesDTO: Nos permitirá obtener los datos del empleado.
  • EmployeeRequest: Nos servirá para poder enviar el objeto que espera el metodo post de nuestra api también nos servirá para aplicar validaciones al formulario


   public class EmployeeRequest
    {
        [Required]
        public string Name { get; set; }
        [Required]
        public int Age { get; set; }
    }

    public class EmployeesDTO
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

    public class GenericResponse
    {
        public string Message { get; set; }
        public HttpStatusCode HttpCode { get; set; }

        public object Data { get; set; }
    }

Crearemos un controlador EmployeesController.

public class EmployeesController : Controller
    {

        private readonly IHttpClientFactory _httpClient;

        public EmployeesController(IHttpClientFactory httpClient)
        {
            _httpClient = httpClient;
        }

        JsonSerializerOptions options = new JsonSerializerOptions() { PropertyNameCaseInsensitive = true };

        // GET: EmployeesController
        public async Task<ActionResult> Index()
        {
            List<EmployeesDTO> employees = new List<EmployeesDTO>();
            try
            {
                var client = _httpClient.CreateClient("EmployeesApi");
                var response = await client.GetAsync("Employees");
                if (response.IsSuccessStatusCode)
                {
                    var content = await  response.Content.ReadAsStringAsync();

                    var result =  JsonSerializer.Deserialize<GenericResponse>(content, options);
                    if(result.HttpCode == System.Net.HttpStatusCode.OK)
                        employees = JsonSerializer.Deserialize<List<EmployeesDTO>>(result.Data.ToString(), options);


                    return View(employees);
                }
                return View();

            }
            catch 
            {
                return View("Error");
            }
        }


        // GET: EmployeesController/Create
        public  ActionResult Create()
        {

            return View();

        }

        // POST: EmployeesController/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(EmployeeRequest employee)
        {
            try
            {
                if(ModelState.IsValid)
                {
                    var client = _httpClient.CreateClient("EmployeesApi");
                    var response = await client.PostAsJsonAsync("Employees", employee);
                    if (response.IsSuccessStatusCode)
                    {
                        var content = await response.Content.ReadAsStringAsync();

                        var result = JsonSerializer.Deserialize<GenericResponse>(content, options);
                        if (result.HttpCode == System.Net.HttpStatusCode.OK)
                            return RedirectToAction(nameof(Index));
                    }
                }
                return View();
            }
            catch
            {
                return View("Error");
            }
        }

    }
Lo que estamos haciendo en el controlador es inyectar IHttpClientFactory para poder usar el cliente http que definimos en nuestro Program.cs. 
Para consumir la api lo que debemos hacer es crear un cliente y este lo hacemos llamando el cliente EmployeesApi que creamos y luego hacemos la peticion al endpoint usando el método GetAsync y PostAsJsonAsync como el cliente http que creamos ya trae la uri de la api solo le pasamos el método que queremos consumir en este caso Employees(cuando haces una petición post tambien debes enviar los datos que espera la api), una vez obtenemos la respuesta de la api nos aseguramos que la respuesta sea exitosa con el método IsSuccessStatusCode(en nuestro caso hacemos una doble validación ya que nuestra api nos devuelve en la respuesta una propiedad status code), para obtener los datos de la respuesta debemos deserializar el json devuelto por nuestra api para este caso usamos JsonSerializer.

Lo último que nos queda por hacer es crear nuestras 2 vistas en donde mostraremos los empleados que obtenemos de la api y otra vista con un pequeño formulario que nos servirá para poder crear un empleado.

Vista Index.

@model  List<Employees.Front.Dtos.EmployeesDTO>

@{
    ViewData["Title"] = "Index";
}

<h2 class="text-center">Employees</h2>

<div class="container">
    <!-- Boton Create  -->
    <a asp-action="Create" asp-controller="Employees" class="btn btn-success "><i class="fas fa-plus"></i> Add</a>
    <br />
    <br />


    <!-- Table employees -->
    <div class="row">
        <div class="col-md-12">

            <table class="table">
                <thead class="thead-dark">
                    <tr>
                        <th>ID</th>
                        <th>NAME</th>
                        <th>AGE</th>
                    </tr>
                </thead>
                <!-- Recorro el modelo para imprimir datos -->
                @foreach (var element in Model)
                {
                    <tr>
                        <td>@element.Id</td>
                        <td>@element.Name</td>
                        <td>@element.Age</td>
                    </tr>
                }
            </table>
        </div>
    </div>

</div>
Vista Create

@model  Employees.Front.Dtos.EmployeeRequest
@{
    ViewData["Title"] = "Create";
}

<h2 class="text-center">Employees</h2>


<div class="container-fluid">
    <form asp-action="Create">
        <div class="form-row">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group col-lg-6">
                <label asp-for="Name" class="control-label"></label>
                <input asp-for="Name" class="form-control" />
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
            <div class="form-group col-lg-6">
                <label asp-for="Age" class="control-label"></label>
                <input asp-for="Age" class="form-control" />
                <span asp-validation-for="Age" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group mt-4">
              <input type="submit" value="Create" class="btn btn-success" />
        </div>
    </form>
</div>

Si ejecutamos nuestra aplicación obtendremos el siguiente resultado(para que te funcione debes asegurarte de tener corriendo el proyecto de la api, es decir debes tener corriendo los 2 proyectos)






puedes descargar el código desde este repositorio

si quieren donarme para una café lo pueden hacer aqui.

Hasta la próxima.

Saludos desde El Salvador...

Publicar un comentario

0 Comentarios