c# - ejemplos - Manejo de excepciones en el controlador(ASP.NET MVC)
web forms c# tutorial (4)
Cuando se lanza una excepción por su propio código que se llama desde una acción en un controlador, ¿cómo debería manejarse? Veo muchos ejemplos de mejores prácticas donde no hay en absoluto declaraciones de prueba de captura. Por ejemplo, accediendo a datos desde un repositorio:
public ViewResult Index()
{
IList<CustomModel> customModels = _customModelRepository.GetAll();
return View(customModels);
}
Claramente, este código podría generar una excepción si la llamada es a una base de datos a la que no puede acceder y estamos usando un ORM como Entity Framework, por ejemplo.
Sin embargo, todo lo que puedo ver es que la excepción aumentará y mostrará un mensaje de error desagradable para el usuario.
Soy consciente del atributo HandleError, pero entiendo que se usa principalmente para redirigirlo a una página de error si se produce una excepción que no se maneja.
Por supuesto, este código se puede envolver en un try-catch pero no se separa bien, especialmente si tiene más lógica:
public ViewResult Index()
{
if (ValidationCheck())
{
IList<CustomModel> customModels = new List<CustomModel>();
try
{
customModels = _customModelRepository.GetAll();
}
catch (SqlException ex)
{
// Handle exception
}
if (CustomModelsAreValid(customModels))
// Do something
else
// Do something else
}
return View();
}
Anteriormente, he extraído todo el código que podría generar excepciones como las llamadas a bases de datos en una clase de proveedor de datos que maneja los errores y devuelve los mensajes para mostrar los mensajes al usuario.
Me preguntaba cuál es la mejor manera de manejar esto? No siempre quiero volver a una página de error porque algunas excepciones no deberían hacerlo. En su lugar, debe mostrarse un mensaje de error al usuario con una vista normal. ¿Mi método anterior fue correcto o hay una solución mejor?
Con Asp.Net MVC también puede anular el método OnException para su controlador.
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled)
{
return;
}
filterContext.Result = new ViewResult
{
ViewName = ...
};
filterContext.ExceptionHandled = true;
}
Esto le permite redirigir a una página de error personalizada con un mensaje que hace referencia a la excepción, si así lo desea.
Hago tres cosas para mostrar mensajes más fáciles de usar:
- Aproveche el controlador de excepciones global. En el caso de MVC: Application_Error en Global.asax. Aprenda cómo usarlo aquí: http://msdn.microsoft.com/en-us/library/24395wz3(v=vs.100).aspx
- Subclasifico Exception en una UserFriendlyException. Hago lo mejor que puedo en todas mis clases de servicio subyacentes para lanzar esta UserFriendlyException en lugar de una excepción antigua. Siempre trato de poner mensajes significativos para el usuario en estas excepciones personalizadas. El propósito principal de esto es poder realizar una verificación de tipo en la excepción en el método Application_Error. Para las UserFriendlyExceptions, solo uso el mensaje fácil de usar que he establecido en mis servicios, como "¡Hey! ¡91 grados no es un valor de latitud válido!". Si es una excepción regular, entonces es un caso que no he manejado, así que muestro un mensaje de error más genérico, como "¡Vaya, algo salió mal! ¡Haremos todo lo posible para solucionarlo!".
- También creo un ErrorController que es responsable de proporcionar vistas fáciles de usar o JSON. Este es el controlador cuyos métodos se llamarán desde el método Application_Error.
EDITAR: Pensé que le daría una mención a la API web de ASP.NET ya que está estrechamente relacionada. Debido a que el consumidor de los puntos finales de la API web no necesariamente será un navegador, me gusta tratar los errores de manera un poco diferente. Todavía utilizo la "FriendlyException" (# 2 arriba), pero en lugar de redirigir a un ErrorController, solo dejo que todos mis puntos finales devuelvan algún tipo de tipo base que contenga una propiedad Error. Por lo tanto, si una excepción llega hasta los controladores de la API web, me aseguro de pegar ese error en la propiedad Error de la respuesta de la API. Este mensaje de error será el mensaje amistoso que ha surgido de las clases en las que se basa el controlador API, o será un mensaje genérico si el tipo de excepción no es una FriendlyException. De esa manera, el cliente consumidor simplemente puede verificar si la propiedad Error de la respuesta de la API está vacía. Muestre un mensaje si el error está presente, proceda como de costumbre si no. Lo bueno es que, debido al concepto de mensaje amigable, el mensaje puede ser mucho más significativo para el usuario que un "Error" genérico. mensaje. Utilizo esta estrategia al escribir aplicaciones móviles con Xamarin, donde puedo compartir mis tipos de C # entre mis servicios web y mi aplicación iOS / Android.
Todas las preguntas como esta no son muy constructivas, porque la respuesta siempre es "depende", porque hay muchas formas de tratar el manejo de errores.
A muchas personas les gusta usar el método HandleError, porque cualquier excepción es básicamente no recuperable. Quiero decir, ¿qué vas a hacer si no puedes devolver los objetos? Les vas a mostrar un error de todos modos, ¿verdad?
La pregunta es, cómo quieres mostrarles el error. Si mostrarles una página de error es aceptable, entonces HandleError funciona bien y proporciona un lugar fácil para registrar el error. Si está usando Ajax o quiere algo más sofisticado, entonces necesita desarrollar una forma de hacerlo.
Hablas de una clase DataProvider. Eso es básicamente lo que es su repositorio. ¿Por qué no construir eso en tu repositorio?
Utilicé una anulación de OnException porque tengo varias referencias de proyectos a una que tiene un Controlador que maneja errores:
Seguridad / HandleErrorsController.cs
protected override void OnException(ExceptionContext filterContext)
{
MyLogger.Error(filterContext.Exception); //method for log in EventViewer
if (filterContext.ExceptionHandled)
return;
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
filterContext.Result = new JsonResult
{
Data = new
{
Success = false,
Error = "Please report to admin.",
ErrorText = filterContext.Exception.Message,
Stack = filterContext.Exception.StackTrace
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
filterContext.ExceptionHandled = true;
}