En el desarrollo de aplicaciones web, es esencial contar con un mecanismo consistente para devolver resultados de las API. Esto simplifica la integración con los clientes front-end y facilita el manejo de errores. En .NET Core, el enfoque para envolver las respuestas difiere del utilizado en .NET Framework, por lo que se requiere una adaptación específica.
Para lograrlo, se define una estructura de respuesta estandarizada que incluye un código de estado, un mensaje y los datos resultantes. Además, se implementa un filtro de acción que intercepta las respuestas de los controladores y las transforma al formato unificado.
Definición de códigos de respuesta
Primero, se crea un enumerado para rperesentar los posibles estados de una respuesta. Cada valor está decorado con un atributo para controlar su serialización JSON.
public enum EstadoRespuesta
{
[JsonProperty("1000")]
Exito = 1000,
[JsonProperty("2000")]
SesionExpirada = 2000,
[JsonProperty("3000")]
Excepcion = 3000,
[JsonProperty("4000")]
ErrorSistema = 4000
}
Clase genérica para respuestas
A continuación, se modela la estructura de respuesta mediante una clase genérica. Esta encapsula el código de estado, un mensaje descriptivo y los datos de la operación.
public class RespuestaGenerica<T>
{
public T Datos { get; set; } = default(T);
public EstadoRespuesta Estado { get; set; } = EstadoRespuesta.Exito;
public string Mensaje { get; set; } = "Operación exitosa";
public void ConfigurarExito(T datos, string mensaje = null)
{
Estado = EstadoRespuesta.Exito;
Datos = datos;
Mensaje = mensaje ?? "Operación exitosa";
}
public void ConfigurarError(string mensaje, EstadoRespuesta estado = EstadoRespuesta.Excepcion)
{
Estado = estado;
Mensaje = mensaje;
}
}
Filtro de acción para el empaquetado
Se implementa un filtro que hereda de ActionFilterAttribute y sobreescribe el método OnActionExecuted. Este filtro solo procesa respuestas exitosas de tipo ObjectResult, ignorando excepciones y otros tipos de resultados como archivos o contenido directo. Las excepciones se manejan en un middleware separado.
public class FiltroEmpaquetadoRespuesta : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext contexto)
{
if (contexto.Exception == null)
{
if (contexto.Result is ObjectResult resultadoObjeto)
{
var respuestaEmpaquetada = new RespuestaGenerica<object>();
respuestaEmpaquetada.ConfigurarExito(resultadoObjeto.Value);
contexto.Result = new ObjectResult(respuestaEmpaquetada);
}
}
base.OnActionExecuted(contexto);
}
}
Integración del filtro
Para aplicar el filtro globalmente, se registra durante la configuración de los servicios en el método ConfigureServices del archivo Startup.cs.
services.AddMvc(opciones =>
{
opciones.Filters.Add<FiltroEmpaquetadoRespuesta>();
});
Ejemplo de respuesta resultante
Al consumir una API que utiliza este filtro, las respuestas tendrán un formato coherente, como se muestra en el siguiente ejemplo JSON.
{
"datos": {
"identificador": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"nombreUsuario": "ejemplo123",
"correo": "usuario@dominio.com"
},
"estado": 1000,
"mensaje": "Operación exitosa"
}