Aquí tienes el resumen estructurado para el Manejo Global de Excepciones. Este patrón es vital para la seguridad y la profesionalidad de tu API.
🛡️ Apuntes: Global Exception Handling (El “Airbag”)
1. ¿Qué es?
Es un mecanismo centralizado (Middleware) que intercepta cualquier error no controlado que ocurra en tu aplicación antes de que llegue al usuario.
-
Analogía: Es como el airbag de un coche. No evita el accidente, pero si ocurre, evita que el usuario salga herido (viendo datos técnicos sensibles).
-
Diferencia con PHP Legacy: En lugar de poner
try-catchen cada función o configurardisplay_errors, configuras esto una sola vez y protege toda la API.
2. ¿Por qué es obligatorio en un entorno profesional?
Tiene tres objetivos intocables:
-
Seguridad (Security thru Obscurity): Jamás mostrar el Stack Trace (rutas de archivos, líneas de código, nombres de bases de datos) al cliente. Eso es oro para un hacker.
-
Experiencia de Usuario (UX): El cliente siempre recibe una respuesta JSON estructurada y limpia, no una página HTML de error del servidor (el famoso “Yellow Screen of Death”).
-
Observabilidad (Logging): Aunque al usuario le ocultas el error, tú necesitas verlo. Este sistema guarda el error real en los logs (consola o archivo) antes de responder al usuario.
3. La Pieza Clave: IExceptionHandler
En .NET 10 (y desde .NET 8), usamos esta interfaz. Es la forma moderna y performante.
Clase GlobalExceptionHandler.cs (Tu implementación):
C#
public class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) : IExceptionHandler
{
public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
{
// 1. EL LOG (Para ti): Registra la verdad cruda y dura
logger.LogError(exception, "Error crítico: {Message}", exception.Message);
// 2. LA RESPUESTA (Para el usuario): Mentira piadosa y limpia
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError,
Title = "Error Interno",
Detail = "Ha ocurrido un problema inesperado." // Nunca uses exception.Message aquí
};
httpContext.Response.StatusCode = problemDetails.Status.Value;
// 3. Escribir JSON
await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);
return true; // Le dice a .NET: "Yo me encargo, no sigas propagando el error"
}
}
4. El Estándar: ProblemDetails (RFC 7807)
No inventes formatos de error como {"error": "fallo"}. .NET usa el estándar de la industria llamado ProblemDetails.
Tu API siempre responderá así automáticamente:
JSON
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.6.1",
"title": "Error Interno",
"status": 500,
"detail": "Ha ocurrido un problema inesperado."
}
5. Configuración (“Wiring”) en Program.cs
Para que el Airbag funcione, tienes que instalarlo y activarlo. El orden importa mucho.
C#
// 1. Inyección de Dependencias (Builder)
builder.Services.AddExceptionHandler<GlobalExceptionHandler>(); // Registras tu clase
builder.Services.AddProblemDetails(); // Habilitas el estándar JSON
var app = builder.Build();
// 2. Middleware Pipeline (App)
// IMPORTANTE: Debe ir al principio, antes de MapControllers()
app.UseExceptionHandler();
app.MapControllers();
app.Run();
6. Flujo de un Error (El ciclo de vida)
-
Usuario llama a
POST /api/users. -
Tu
UsersControllerllama al Servicio. -
La Base de Datos explota (Excepción).
-
El error sube “burbujeando” hacia arriba.
-
GlobalExceptionHandleratrapa el error al vuelo. -
Escribe el error rojo en tu consola (Log).
-
Devuelve el JSON limpio (ProblemDetails) al usuario con código 500.
-
La aplicación no se cierra, sigue lista para la siguiente petición.
📝 Resumen en una frase
“El Manejador Global permite que el programador vea por qué falló el sistema, mientras que el usuario solo ve que falló el sistema, manteniendo la seguridad intacta.”