Contenido del curso
Estructura de una Web API
- 7

Configurar CORS en APIs de .NET
07:08 min - 8

Rutas en APIs .NET con parámetros
12:50 min - 9

Swagger y Scalar para documentar APIs en .NET
14:25 min - 10

Cómo crear middlewares en ASP.NET Core
10:30 min - 11

Inyección de dependencias y logging en .NET
09:18 min - 12

Autenticación básica en APIs con middleware .NET
08:17 min
Arquitectura y Middlewares
- 13

Configurar Entity Framework Core en .NET
07:30 min - 14

Modelos y Fluent API en Entity Framework
10:00 min - 15

Servicios en .NET con Entity Framework
13:51 min - 16

Cómo crear controladores REST en .NET
Viendo ahora - 17

Conectar .NET con SQL Server usando Entity Framework
09:51 min - 18

Conectar .NET con PostgreSQL usando Entity Framework
06:57 min - 19

Capas de Clean Architecture en .NET
09:07 min - 20

Unit tests en .NET con Copilot y xUnit
09:05 min - 21

Qué aprender después de APIs con .NET
02:16 min
Cómo crear controladores REST en .NET
Resumen
Crear controladores en una API .NET es el paso donde toda la arquitectura previa cobra sentido: el AppDbContext, los modelos y los servicios se conectan para exponer endpoints que otras aplicaciones puedan consumir. Aquí aprenderás a estructurar controladores REST para usuarios y tareas, aplicar inyección de dependencias y devolver los códigos HTTP correctos según el patrón REST.
Qué hace un controlador en una API .NET
Un controlador es la capa que expone funciones accesibles vía HTTP y delega la lógica al servicio, que a su vez habla con la base de datos a través del AppDbContext. Esa separación mantiene el código ordenado y testeable.
En la carpeta Controllers creas un nuevo elemento del tipo API Controller vacío. Por convención, la ruta por defecto queda como api/[nombre del controlador], así que un UserController se accede en api/user.
¿Qué diferencia hay entre GET y POST en un controlador? GET sirve para obtener datos sin modificarlos, POST para crear nuevos registros. Ambos pueden compartir la misma ruta, lo que cambia es el verbo HTTP.
Cómo inyectar el servicio en el controlador
Lo primero dentro del controlador es recibir la interfaz del servicio por constructor y guardarla en una variable privada con guion bajo, por convención _userService. Así aplicas inyección de dependencias, un patrón clave en .NET que permite que el framework resuelva automáticamente la implementación correcta en tiempo de ejecución [02:00].
Luego defines los métodos asíncronos que devuelven Task<ActionResult>. Usar ActionResult da flexibilidad para responder con distintos códigos HTTP según el caso.
Cómo implementar GetAll y GetById
El método para obtener todos los registros lleva el atributo [HttpGet] y llama a _userService.GetAllAsync() con await. Como devuelves una lista, lo correcto es nombrar la variable en plural, users, y responder con return Ok(users).
Para obtener uno solo necesitas:
- Atributo
[HttpGet("{id}")]que define la rutaapi/user/{id}. - Parámetro
int idrequerido en la firma del método. - Llamada a
GetByIdAsync(id)para buscar el registro. - Validación con
ifque devuelvaNotFound()si el resultado es nulo.
Esa validación de NotFound es una buena práctica REST: si el cliente busca un id válido pero el elemento no existe, devolver el código 404 es más correcto que regresar un objeto vacío o un null [09:30].
Cómo crear el endpoint POST con CreatedAtAction
El método de creación marca con [HttpPost] y recibe el objeto desde el cuerpo de la petición usando [FromBody]. Internamente llama a _userService.CreateAsync(user) y guarda el resultado.
Aquí viene lo interesante: aunque podrías responder con un simple Ok(), REST tiene un código específico para creaciones exitosas, el 201 Created. Para devolverlo se usa CreatedAtAction, que recibe tres elementos:
- El nombre de la acción a invocar, idealmente con
nameof(GetById)para que sea dinámico. - Un objeto anónimo con el parámetro de ruta, en este caso
new { id = created.Id }. - El objeto completo recién creado.
Con esto, la respuesta no solo confirma la creación: incluye también la URL donde el cliente puede consultar el nuevo registro. Es una práctica que mejora la experiencia de cualquiera que consuma tu API.
¿Qué hace
nameofen C#? Devuelve el nombre de un método o variable como string en tiempo de compilación. Si renombras el método,nameofse actualiza solo y evitas errores por strings desactualizados.
Cómo replicar la estructura para el controlador de tareas
El TaskController sigue el mismo patrón pero inyecta ITaskService en lugar de IUserService. Implementa GetAll, GetById con validación de NotFound, y Create con CreatedAtAction. La lógica es idéntica porque la arquitectura está bien desacoplada: cambiar de entidad solo requiere cambiar el servicio inyectado.
Qué configuración necesita Program.cs para que funcione
Para que los controladores respondan correctamente, el archivo Program.cs debe tener tres piezas activas:
AddControllers()que registra el servicio y resuelve las dependencias.MapControllers()que actúa como middleware para hacer match entre la ruta solicitada y el controlador correspondiente.- La configuración del
AppDbContext, en este caso usando base de datos en memoria para pruebas.
Si falta MapControllers, ninguna ruta encontrará su controlador y la API devolverá un Not Found genérico [12:30].
Cómo probar la API con Swagger
Al ejecutar el proyecto, Swagger aparece como interfaz para probar cada endpoint. Como hay autorización activa, primero te autenticas con las credenciales de ejemplo Platzi y 12345.
El flujo de prueba es directo:
- POST a
api/usercon un cuerpo JSON que incluya elidmanualmente, ya que la base de datos en memoria no genera identificadores automáticos. - Verificar la respuesta 201 Created con el objeto devuelto.
- GET a
api/userpara confirmar que el registro aparece en la lista. - POST a
api/taskreferenciando eliddel usuario creado, con campos como título yisComplete: false.
Swagger a veces muestra una estructura confusa para entidades relacionadas, pero basta con enviar el id del usuario existente para que la relación funcione.
Tu siguiente reto es completar el CRUD: faltan los métodos Update con [HttpPut] y Delete con [HttpDelete]. Cuando los tengas, podrás conectar el proyecto a una base de datos real. ¿Cuál fue la parte más retadora al armar tu primer controlador? Cuéntalo en los comentarios.