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á
Dividiremos el reto en varias secciones:
Construyamos la arquitectura general del proyecto
Creemos las clases principales
Servicios de Lógica
Controladores Web
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