Ejemplos de código funcionales y listos para usar, desde la configuración hasta la persistencia de datos.
Este es el punto de partida de toda aplicación ASP.NET Core (usando el modelo minimalista de .NET 6+).
Program.cs
// 1. Crear el Constructor del WebApplication
var builder = WebApplication.CreateBuilder(args);
// 2. Definir servicios (Contenedor de Inyección de Dependencias)
builder.Services.AddControllers(); // Habilita controladores API/MVC
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 3. Construir la aplicación
var app = builder.Build();
// 4. Configurar el pipeline HTTP (Middleware)
if (app.Environment.IsDevelopment())
{
// Middleware que solo se ejecuta en modo Desarrollo
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
// 5. Mapear endpoints (API, MVC, etc.)
app.MapControllers(); // Rutas automáticas para los controladores
// Endpoint simple de ejemplo (Middleware personalizado)
app.MapGet("/", () => "¡Hola, ASP.NET Core con Gemini!");
// 6. Ejecutar la aplicación
app.Run();
Explicación: El **`builder`** configura los servicios (DI), y el objeto **`app`** configura el *pipeline* de middleware y las rutas (`Map*`).
Un ejemplo de un controlador simple que gestiona una colección de elementos (simulando una lista de tareas).
Controllers/TareasController.cs
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
[ApiController]
[Route("api/[controller]")]
public class TareasController : ControllerBase
{
// Simulación de la base de datos
private static List<string> _tareas = new List<string> { "Comprar leche", "Aprender ASP.NET Core" };
[HttpGet] // GET: api/tareas
public ActionResult<IEnumerable<string>> Get()
{
return Ok(_tareas);
}
[HttpPost] // POST: api/tareas
public IActionResult Post([FromBody] string nuevaTarea)
{
if (string.IsNullOrEmpty(nuevaTarea))
{
return BadRequest("La tarea no puede estar vacía.");
}
_tareas.Add(nuevaTarea);
return CreatedAtAction(nameof(Get), nuevaTarea);
}
[HttpDelete("{id}")] // DELETE: api/tareas/1
public IActionResult Delete(int id)
{
if (id < 0 || id >= _tareas.Count)
{
return NotFound();
}
_tareas.RemoveAt(id);
return NoContent(); // 204 No Content (Éxito sin devolver cuerpo)
}
}
Explicación: Usamos los atributos **`[HttpGet]`**, **`[HttpPost]`**, etc., para mapear los métodos del controlador a los verbos HTTP. **`ControllerBase`** proporciona métodos de resultado HTTP (`Ok`, `NotFound`, `NoContent`).
Pasos necesarios para configurar un contexto de base de datos (usando SQLite in-memory para simplificar).
Program.cs (Adición de servicio)
// ... dentro de la sección de servicios (builder.Services) ...
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlite("Data Source=MiBaseDeDatos.db"));
// Nota: Necesitas instalar el paquete Microsoft.EntityFrameworkCore.Sqlite
Data/AppDbContext.cs (Contexto y Modelo)
using Microsoft.EntityFrameworkCore;
using SuProyecto.Models; // Asumiendo que Tarea.cs está aquí
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
// Un DbSet por cada tabla/entidad que quieras mapear
public DbSet<Tarea> Tareas { get; set; }
}
// Ejemplo de Modelo (Data/Tarea.cs)
public class Tarea
{
public int Id { get; set; }
public string Descripcion { get; set; }
public bool EstaCompleta { get; set; }
}
Explicación: **`AddDbContext`** registra el contexto en el contenedor DI. **`AppDbContext`** hereda de `DbContext` y usa `DbSet` para definir las colecciones que mapean a las tablas.
Cómo consumir el contexto de base de datos o cualquier otro servicio registrado directamente en el constructor del controlador.
Controllers/TareasController.cs (Inyección)
[ApiController]
[Route("api/[controller]")]
public class TareasController : ControllerBase
{
private readonly AppDbContext _context;
// EL CONSTRUCTOR SOLICITA LA DEPENDENCIA
public TareasController(AppDbContext context)
{
_context = context;
}
[HttpGet("{id}")]
public async Task<ActionResult<Tarea>> GetTarea(int id)
{
// USO DE LA DEPENDENCIA INYECTADA
var tarea = await _context.Tareas.FindAsync(id);
if (tarea == null)
{
return NotFound();
}
return tarea;
}
// ... otros métodos CRUD (Create, Update, Delete)
}
Explicación: El contenedor de Inyección de Dependencias (DI) de ASP.NET Core automáticamente resuelve y proporciona una instancia de **`AppDbContext`** al controlador cuando se necesita, siempre y cuando se haya registrado previamente en `Program.cs`.
Ejemplos de cómo asegurar tu API y cómo manejar excepciones de forma centralizada.
Usaremos un middleware personalizado para capturar todas las excepciones y devolver un formato JSON estándar (500 Internal Server Error).
// En Program.cs, justo después de app.UseHttpsRedirection();
if (app.Environment.IsDevelopment())
{
// En desarrollo, usamos el manejo de errores detallado de ASP.NET
app.UseDeveloperExceptionPage();
}
else
{
// En producción, usamos un manejador simple y consistente
app.UseExceptionHandler("/error");
}
// Endpoint que captura errores y devuelve un JSON
app.Map("/error", (HttpContext context) =>
{
var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
// Devolver un objeto de error simple
return Results.Problem(
detail: exceptionHandlerPathFeature?.Error.Message,
title: "Ocurrió un error inesperado en el servidor",
statusCode: 500
);
});
Explicación: **`UseExceptionHandler`** redirige todas las excepciones no controladas a un *endpoint* simple (`/error`), donde se extrae la información y se devuelve un objeto **`ProblemDetails`** (estándar para errores de API).
Pasos para configurar la autenticación basada en tokens, necesaria para proteger tus endpoints.
// 1. Instalar paquetes: Microsoft.AspNetCore.Authentication.JwtBearer
// 2. En Program.cs, dentro de builder.Services.Add...
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
};
});
// 3. Habilitar el middleware de autenticación (ANTES de app.MapControllers)
app.UseAuthentication();
app.UseAuthorization();
using Microsoft.AspNetCore.Authorization;
// ... (otros using)
[ApiController]
[Route("api/[controller]")]
public class ArticulosController : ControllerBase
{
[Authorize] // Este atributo requiere un token válido en el encabezado
[HttpGet]
public IActionResult GetArticulosProtegidos()
{
// Solo usuarios con un token JWT válido llegarán aquí.
return Ok(new { mensaje = "Datos sensibles del usuario autenticado." });
}
}
Explicación: **`AddAuthentication`** configura el esquema de JWT. El middleware **`UseAuthentication`** lee el token. El atributo **`[Authorize]`** en el controlador fuerza la validación de ese token.