En el contexto de C# ASP.NET Core, un controlador es una clase que hereda de ControllerBase procesar solicitudes HTTP entrantes y generar las respuestas correspondientes. Cada método público dentro de un controlador se denomina método de acción, y tiene la responsabilidad específica de manejar una combinación particular de ruta y método HTTP (como GET, POST, PUT, DELETE, etc.).
- Manejar Solicitudes (Requests): Recibe las solicitudes HTTP entrantes (GET, POST, PUT, DELETE, etc.) de los clientes.
- Procesar Lógica de Negocio: Coordina con los “Modelos” (donde reside la lógica de negocio y los datos) para realizar las operaciones necesarias.
- Retornar Respuestas (Responses): Envía la respuesta apropiada al cliente, que puede ser una vista HTML (en el caso de MVC), datos JSON/XML (en el caso de una API), un redireccionamiento, un error, etc.
1. Enrutamiento (Routing) en ASP.NET Core Web API
ASP.NET Core utiliza un sistema de enrutamiento para mapear las URLs entrantes a los métodos de acción de los controladores.
Enrutamiento Convencional: Es el enrutamiento basado en convenciones predefinidas. Por ejemplo, la URL /Home/Index
normalmente mapearía al método Index
del HomeController
.
// En Program.cs o Startup.cs (ASP.NET Core 5 y anteriores)
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Enrutamiento Basado en Atributos: Permite definir rutas directamente sobre los controladores y métodos de acción usando atributos como [Route]
, [HttpGet]
, [HttpPost]
, etc. Esto es muy común y recomendado para APIs web.
Enrutamiento Básico
[ApiController]
[Route("api/[controller]")]
public class ProductosController : ControllerBase
[Route("api/[controller]")]
significa que este controlador responde a /api/productos
.
[controller]
se reemplaza automáticamente por el nombre del controlador sin “Controlle
Parámetros en la Ruta (URL)
[HttpGet("{id}")]
public IActionResult ObtenerPorId(int id)
{
return Ok($"Producto {id}");
}
Solicitud: GET /api/productos/10
Parámetro de ruta: id = 10
Puedes definir múltiples parámetros:
Parámetros de consulta (Query Parameters)
[HttpGet("buscar")]
public IActionResult Buscar([FromQuery] string nombre,
[FromQuery] int pagina = 1)
{
return Ok($"Buscando {nombre}, página {pagina}");
}
Solicitud: GET /api/productos/buscar?nombre=laptop&pagina=2
Parámetros de Ruta
[HttpGet("{id}")]
public IActionResult ObtenerPorId([FromRoute] int id)
{
return Ok($"Producto {id}");
}
Cuerpo de la Solicitud (Body, generalmente en JSON)
public class ProductoDto
{
public string Nombre { get; set; }
public decimal Precio { get; set; }
}
[HttpPost]
public IActionResult Crear([FromBody] ProductoDto producto)
{
return Ok($"Creado {producto.Nombre}");
}
Solicitud:
POST /api/productos
Content-Type: application/json
{
"nombre": "Mouse",
"precio": 29.99
}
Datos de Formulario (Form Data)
[HttpPost("subir")]
public IActionResult Subir([FromForm] string titulo,
[FromForm] IFormFile archivo)
{
return Ok($"Subido {titulo} - {archivo.FileName}");
}
Encabezados (Headers)
[HttpGet("seguro")]
public IActionResult RutaSegura([FromHeader(Name = "X-Api-Key")] string apiKey)
{
if (apiKey != "123456") return Unauthorized();
return Ok("Acceso concedido");
}
2. Tabla resumen de tipos de parámetros
Tipo de parámetro | Atributo | Ejemplo de uso |
---|---|---|
Parámetro de ruta | [FromRoute] | /api/productos/1 |
Cadena de consulta | [FromQuery] | /api/productos?nombre=abc |
Cuerpo de solicitud | [FromBody] | POST con JSON |
Encabezado | [FromHeader] | X-Api-Key: 123456 |
Datos de formulario | [FromForm] | Formularios HTML, subida de archivos |
3. Inyección de Dependencias en Controladores
Una de las características más potentes de ASP.NET Core es su soporte integrado para la inyección de dependencias (DI). Esto te permite inyectar servicios (como servicios de base de datos, loggers, servicios externos) en el constructor de tu controlador, promoviendo un código más desacoplado y testeable.
Para que esto funcione, IProductoService
y su implementación concreta deben estar registrados en el contenedor de inyección de dependencias de ASP.NET Core (generalmente en Program.cs
o Startup.cs
).
public class ProductosController : Controller
{
private readonly IProductoService _productoService;
// Una interfaz para tu servicio
// Inyección de dependencia a través del constructor
public ProductosController(IProductoService productoService)
{
_productoService = productoService;
}
public IActionResult Index()
{
var productos = _productoService.ObtenerTodosLosProductos();
return View(productos);
}
}
4. Atributos Comunes del Controlador
[ApiController]
: Atributo recomendado para controladores de API. Habilita características específicas de API como el enrutamiento de atributos por defecto, la validación automática de modelos y el manejo de errores mejorado.[Route("ruta")]
: Define la plantilla de ruta para un controlador o un método de acción.[HttpGet]
,[HttpPost]
,[HttpPut]
,[HttpDelete]
: Atributos que restringen un método de acción para que solo responda a un tipo específico de solicitud HTTP.[FromBody]
: Indica que un parámetro debe ser deserializado del cuerpo de la solicitud HTTP (común en solicitudes POST/PUT de API).[FromQuery]
: Indica que un parámetro debe ser enlazado desde la cadena de consulta de la URL.[FromRoute]
: Indica que un parámetro debe ser enlazado desde los datos de la ruta.[Authorize]
: Restringe el acceso a un controlador o método de acción solo a usuarios autenticados y/o autorizados.
5. Dónde No Poner Lógica de Negocio
Es una buena práctica mantener los controladores “delgados” (thin controllers
). Esto significa que los controladores deben centrarse en:
- Recibir la solicitud.
- Validar la entrada (hasta cierto punto, la validación del modelo).
- Coordinar con la capa de negocio (servicios, repositorios) para realizar las operaciones.
- Formatear y retornar la respuesta.
La lógica de negocio pesada, la manipulación de datos y la interacción directa con la base de datos deben residir en capas separadas (ej. servicios, repositorios, capas de dominio) para mantener el controlador limpio, testeable y enfocado en su responsabilidad principal.
6. Buenas prácticas
- Valida siempre la entrada del usuario usando
[Required]
,[StringLength]
, etc. - Devuelve códigos de estado HTTP apropiados:
Ok()
,Created()
,NotFound()
,BadRequest()
, etc. - Usa DTOs para evitar exponer directamente tus modelos del dominio.
- Usa enrutamiento por atributos para diseñar APIs REST claras y limpia
Para verificar que las api son funcionales se puede usar postman?, como se puede guardar imágenes con las api en c#?
¿Cuál es la diferencia conceptual entre heredar de Controller vs ControllerBase en ASP.NET Core y en qué escenarios es mas útil cada uno?
¿Qué clase base deben heredar los controladores de API en ASP.NET Core?
Cuál es la diferencia entre FromQuery y FromRoute
¿Por qué es importante marcar el controlador con [ApiController]? ¿Qué cambia si no lo uso?
¿Cuál es la función principal de un controlador en una Web API en ASP.NET Core y cómo se relaciona con el sistema de enrutamiento?
¿Qué atributo se usa para restringir el acceso a usuarios autenticados?
ing. como se maneja la conexión con una base de datos?
¿Por qué se recomienda usar controladores separados para la API y para las vistas en una aplicación web?
¿Qué clase base deben heredar los controladores de API en ASP.NET Core?..