Introducción a la clase
Hemos visto cómo estructurar una aplicación con Clean Architecture y DDD, implementando Entidades, Agregados, Value Objects, Repositorios, Casos de Uso y Controladores. Ahora vamos a construir una API REST completa en C# con ASP.NET Core y Entity Framework Core.
En esta clase, consolidaremos todo lo aprendido mediante un ejemplo práctico, desarrollando una API de gestión de pedidos.
¿Qué obtendrás de esta clase?
- Implementarás una API REST funcional con Clean Architecture y DDD.
- Integrarás EF Core para persistencia de datos.
- Aprenderás a estructurar correctamente un proyecto en C# con buenas prácticas.
- Probarás la API con Postman o Swagger.
Paso 1: Estructura del Proyecto
La estructura de carpetas de nuestra API será la siguiente:
/PedidosAPI
│── /Core
│ ├── /Dominio
│ │ ├── Entidades
│ │ ├── ValueObjects
│ │ ├── Agregados
│ ├── /Aplicacion
│ │ ├── CasosDeUso
│ │ ├── Interfaces
│── /Infraestructura
│ ├── Persistencia
│ ├── Repositorios
│── /Presentacion
│ ├── Controladores
│── /Configuracion
│── Program.cs
│── appsettings.json
Paso 2: Implementar el Dominio (Capa de Core – Dominio)
Entidad Pedido
public class Pedido
{
public int Id { get; private set; }
public string Cliente { get; private set; }
private readonly List<Producto> _productos = new List<Producto>();
public IReadOnlyCollection<Producto> Productos => _productos.AsReadOnly();
public Pedido(int id, string cliente)
{
Id = id;
Cliente = cliente;
}
public void AgregarProducto(Producto producto)
{
_productos.Add(producto);
}
public decimal CalcularTotal()
{
return _productos.Sum(p => p.Precio);
}
}
Value Object Dirección
public class Direccion
{
public string Calle { get; }
public string Ciudad { get; }
public string CodigoPostal { get; }
public Direccion(string calle, string ciudad, string codigoPostal)
{
Calle = calle;
Ciudad = ciudad;
CodigoPostal = codigoPostal;
}
public override bool Equals(object obj)
{
if (obj is Direccion other)
{
return Calle == other.Calle && Ciudad == other.Ciudad && CodigoPostal == other.CodigoPostal;
}
return false;
}
public override int GetHashCode()
{
return HashCode.Combine(Calle, Ciudad, CodigoPostal);
}
}
Paso 3: Implementar la Capa de Aplicación
Interfaz del Repositorio
public interface IPedidoRepository
{
void Guardar(Pedido pedido);
Pedido ObtenerPorId(int id);
}
Caso de Uso – Crear Pedido
public class CrearPedidoUseCase
{
private readonly IPedidoRepository _repository;
public CrearPedidoUseCase(IPedidoRepository repository)
{
_repository = repository;
}
public void Ejecutar(Pedido pedido)
{
_repository.Guardar(pedido);
}
}
Paso 4: Implementar la Capa de Infraestructura
DbContext para EF Core
public class AppDbContext : DbContext
{
public DbSet<Pedido> Pedidos { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Pedido>().HasKey(p => p.Id);
}
}
Repositorio con EF Core
public class PedidoRepository : IPedidoRepository
{
private readonly AppDbContext _context;
public PedidoRepository(AppDbContext context)
{
_context = context;
}
public void Guardar(Pedido pedido)
{
_context.Pedidos.Add(pedido);
_context.SaveChanges();
}
public Pedido ObtenerPorId(int id)
{
return _context.Pedidos.FirstOrDefault(p => p.Id == id);
}
}
Paso 5: Implementar la Capa de Presentación
Controlador REST en ASP.NET Core
[ApiController]
[Route("api/pedidos")]
public class PedidoController : ControllerBase
{
private readonly CrearPedidoUseCase _crearPedidoUseCase;
private readonly IPedidoRepository _pedidoRepository;
public PedidoController(CrearPedidoUseCase crearPedidoUseCase, IPedidoRepository pedidoRepository)
{
_crearPedidoUseCase = crearPedidoUseCase;
_pedidoRepository = pedidoRepository;
}
[HttpPost]
public IActionResult CrearPedido([FromBody] Pedido pedido)
{
_crearPedidoUseCase.Ejecutar(pedido);
return Ok("Pedido creado exitosamente");
}
[HttpGet("{id}")]
public IActionResult ObtenerPedido(int id)
{
var pedido = _pedidoRepository.ObtenerPorId(id);
if (pedido == null)
return NotFound();
return Ok(pedido);
}
}
Paso 6: Configurar la Aplicación en ASP.NET Core
Configurar la Base de Datos y la Inyección de Dependencias
var builder = WebApplication.CreateBuilder(args);
// Configurar Entity Framework Core con SQL Server
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// Configurar inyección de dependencias
builder.Services.AddScoped<IPedidoRepository, PedidoRepository>();
builder.Services.AddScoped<CrearPedidoUseCase>();
var app = builder.Build();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.Run();
Configurar la conexión a la base de datos en appsettings.json
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=PedidosDb;Trusted_Connection=True;"
}
Paso 7: Ejecutar la API y Probar con Postman
- Ejecuta la API con el siguiente comando:
dotnet run
- Crear un Pedido (POST en Postman o cURL)
POST http://localhost:5000/api/pedidos
Content-Type: application/json
{
"id": 1,
"cliente": "Juan Pérez"
}
- Obtener un Pedido (GET en Postman o cURL)
GET http://localhost:5000/api/pedidos/1
Errores comunes al construir una API REST con Clean Architecture
- No usar Repositorios → Solución: Separar la lógica de persistencia en la Capa de Infraestructura.
- No registrar correctamente las dependencias → Solución: Configurar
Program.cs
con la inyección de dependencias adecuada. - No manejar excepciones en la API → Solución: Implementar middleware de manejo de errores.
Cuestionario de Autoevaluación
- ¿Cómo se organiza Clean Architecture en una API REST?
- ¿Cuál es el propósito de los Casos de Uso en Clean Architecture?
- ¿Cómo desacoplar la persistencia en Clean Architecture?
- ¿Cómo probar una API REST sin una base de datos real?
- ¿Qué beneficios tiene usar una arquitectura modular en aplicaciones grandes?
Resumen de la Clase
- Hemos construido una API REST completa con Clean Architecture y DDD en C#.
- Los Casos de Uso permiten mantener la lógica separada de la infraestructura.
- Usamos EF Core para la persistencia y creamos un Controlador REST en ASP.NET Core.
- Nuestro código es modular, escalable y fácil de probar.
Próximo paso
En la siguiente clase pasaremos al siguiente clase, donde veremos Arquitectura Hexagonal + DDD en C#.