Mi primera API REST usando ASPNET Core

Mi primera API REST usando ASPNET Core

Un ejemplo rápido y directo de cómo construir un servicio web usando .NET 8

Vamos a retomar nuestro ejercicio del Blog pasado, si no lo has leído lo dejo por acá

Fundametos de C#

Dividiremos el reto en varias secciones:

  1. Construyamos la arquitectura general del proyecto

  2. Creemos las clases principales

  3. Servicios de Lógica

  4. Controladores Web

  5. Hagámoslo funcionar

Construyamos la arquitectura general del proyecto

En .NET tenemos una forma especial de organizar los proyectos, en primera medida todos nuestro código está escrito principalmente en archivos .cs - existen otros tipos que veremos luego- esos archivos que cumplen una función lógica se agrupan en proyectos, dichos proyectos se pueden agrupar en una solución.

Siendo así tendremos lo siguiente:

  • Una solución

    • Un proyecto para almacenar las clases que representan la información, lo llamaremos Modelos

    • Un proyecto donde almacenaremos las clases que permiten hacer ciertas tareas funcionales del proyecto

    • Un proyecto para el Servicio Web

Y vamos a hacerlo de dos formas: Usando las ayudas de Visual Studio Code y usando la Linea de comandos. Para las ayudas de Visual Studio Code dejo el video explicativo, es corto y directo al problema.

Usando la linea de comando es realmente sencillo y permite hacer a futuro automatizaciones bien interesantes. Para empezar crea una carpeta llamada WebApiEstaciones abre una línea de comandos ubicada en carpeta

Creación de la solución

dotnet new sln -n WebApiEstaciones

Creación del Proyecto de Modelos

dotnet new classlib -n Modelos
dotnet sln add .\Modelos\Modelos.csproj

Creación del Proyecto de Servicios

dotnet new classlib -n Servicios
dotnet sln add .\Servicios\Servicios.csproj

Creación del Proyecto API

dotnet new webapi -n WebApi
dotnet sln add .\WebApi\WebApi.csproj

En cada uno de los comandos anteriores la primera instrucción crea el proyecto y la segunda asocia el proyecto a la solución, recuerda que la solución funciona como un contenedor de Proyectos

Pero esto aún no es suficiente, necesitamos que los proyectos se referencien unos a otros, es decir: El proyecto de Servicios debe ser capaz de conocer las clases públicas de Modelos y el proyecto WebApi debe ser capaz de conocer las clases públicas de Servicios y de Modelos, para hacerlo podemos usar los siguientes comandos.

Esta línea le agrega una referencia a Modelos al proyecto Servicios

dotnet add .\Servicios\Servicios.csproj reference .\Modelos\Modelos.csproj

Hagamos lo mismo con el proyecto WebApi para que conozca a Modelos y Servicios

dotnet add .\WebApi\WebApi.csproj reference .\Modelos\Modelos.csproj
dotnet add .\WebApi\WebApi.csproj reference .\Servicios\Servicios.csproj

¿Se hubiera podido ahorrar todo esto creando todo en un solo proyecto? Si, pero veras en corto tiempo las ventajas de hacerlo asi.

En este punto estamos listos para ejecutar el proyecto y veremos que sale algo bien interesante, en la misma consola escribe

dotnet run --project .\WebApi\WebApi.csproj

Veras que la consola empieza a mostrar lo que .NET está haciendo y nos mostrará la siguiente salida

Si abres el navegador web y escribe las ruta http://localhost:5292 (tambien puedes darle ctrl+clic en la consola)

Si obtienes un error, no hay porque asustarse

Completa en la URL algo como esto http://localhost:5292/swagger/ y verás el resultado

Swagger es una librería que amarás al momento de construir servicios, porque es una forma de "auto-documentar" nuestros servicios web y nos permite probar la funcionalidad que hemos desarrollado.

Si das click en la barra azul que dice /weatherforecast, luego al boton Try it out y luego a Execute

Verás el resultado de la llamada

Creemos las clases principales

¿Recuerdas las clases de Ayer? Estación de Servicio y Combustible. Pues la idea es crearlas ahora para hacerlo, en el proyecto Modelos crea dos archivos: EstacionDeServicio.cs y Combustible.cs

Para hacerlo ubicate en la Carpeta Modelos (En Visual Studio Code) y crea los archivos

Combustible.cs

namespace Modelos;

public class Combustible
{
    public string TipoCombustible { get; set; }
    public double CostoGalon { get; set; }

    public Combustible(string tipoCombustible, double costoGalon)
    {
        this.TipoCombustible = tipoCombustible;
        this.CostoGalon = costoGalon;
    }
}

EstacionDeServicio.cs

namespace Modelos;

public class EstacionDeServicio
{
    public Combustible[] Combustibles { get; set; }
    public bool EstaAbierta { get; set; }
    public string Direccion { get; set; }

    public EstacionDeServicio(bool estaAbierta, string direccion, Combustible[] combustibles)
    {
        this.EstaAbierta = estaAbierta;
        this.Direccion = direccion;
        this.Combustibles = combustibles;
    }
}

Respecto al código, la unica linea que podrás ver diferente es la primera en cada archivo namespace Modelos, esta linea sirve para "unir" las clases en una agrupación lógica. Esto será muy util para organizar nuestro código.

Servicios de Lógica

Como aún no tenemos una base de datos que nos almacene las estaciones de servicio, esto lo construiremos en una próxima publicación, vamos a "simular" una base de datos y para hacerlo vamos a crear en el proyecto Servicios un archivo muy sencillo, en el proyecto Servicios crean un archivo llamado BdEstaciones.cs y escribe el siguiente código

using Modelos;

namespace Servicios;

public class BdEstaciones
{
    private EstacionDeServicio[] estaciones;


    public BdEstaciones()
    {
        this.estaciones = new EstacionDeServicio[0];
    }

    public void AgregarEstacion(EstacionDeServicio estacion)
    {
        Array.Resize(ref this.estaciones, this.estaciones.Length + 1);
        this.estaciones[this.estaciones.Length - 1] = estacion;
    }

    public EstacionDeServicio[] ListarEstaciones()
    {
        return this.estaciones;
    }
}

Quiero explicarte rápidamente este código y te lo dejo en el video

Controladores Web

Vamos a la penúltima parte: Vamos a crear los elementos que permitirán que nuestro servicio web funcione.

Recuerden que posteriormente construiremos una interfaz gráfica para nuestro servicio, tanto web como Móvil, por ahora solo veremos datos.

En el archivo program.cs del Proyecto WebApi, cambia todo el código por este

// Permitimos usar las clases de los proyectos Modelos y Servicios
using Modelos;
using Servicios;

var builder = WebApplication.CreateBuilder(args);

// Adicionamos el servicio de la base de datos de estaciones
// para que este disponible en toda la aplicacion y pueda llamarse en los servicios
// Esto es un singleton, es decir, solo se crea una vez y se usa en toda la aplicacion
builder.Services.AddSingleton<BdEstaciones>();

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();

//Se obtiene el listado de estaciones
app.MapGet("/estaciones", (BdEstaciones bd) =>
{
    var estaciones = bd.ListarEstaciones();
    return estaciones;
})
.WithName("ListaEstaciones")
.WithOpenApi();

//Se agrega una estacion
app.MapPost("/estaciones", (BdEstaciones bd, EstacionDeServicio estacion) =>
{
    bd.AgregarEstacion(estacion);
    return estacion;
})
.WithName("AgregarEstacion")
.WithOpenApi();

app.Run();

Este archivo en particular puede resultarnos ciertamente denso, pero seguro iremos entendiendo.

Quiero centrarme en una parte del código

//Se obtiene el listado de estaciones
app.MapGet("/estaciones", (BdEstaciones bd) =>
{
    var estaciones = bd.ListarEstaciones();
    return estaciones;
})
.WithName("ListaEstaciones")
.WithOpenApi();

//Se agrega una estacion
app.MapPost("/estaciones", (BdEstaciones bd, EstacionDeServicio estacion) =>
{
    bd.AgregarEstacion(estacion);
    return estacion;
})
.WithName("AgregarEstacion")
.WithOpenApi();

fíjate en la linea app.MapGet... esta línea construye un servicio que permite hacer un llamado HTTP Get, es decir, devuelve el listado de estaciones en el formato por defecto JSON

La línea app.MapPost permite agregar una nueva estación al listado.

Si quieres ver la magia, presiona F5 o da click en el botón superior de la ventana del VSCode estando en el archivo Program.cs

Esto lanzará la ejecución del Servicio Web

En este último video de la publicación quiero explicar como funciona, como se armó el Program.cs y explicar un par de detalles.

En la próxima entrega construiremos este ejemplo usando una Base de Datos.

¿Algo por mejorar? ¿Te funcionó? Déjame saber cómo puedo apoyar tu proceso de aprendizaje de .NET

A partir de este momento este código está disponible en GitHub

GitHub