try net mvc log handling errors error custom catch asp application_error all asp.net-mvc logging exception-handling log4net

handling - ASP.Net MVC Exception Logging combinado con manejo de errores



mvc catch exception in view (1)

Estoy buscando una solución simple para hacer el Registro de Excepciones combinado con el Manejo de Errores en mi aplicación ASP.Net MVC 1.0.

He leído muchos artículos, incluidas las preguntas publicadas aquí en StackOverflow, que ofrecen diferentes soluciones para diferentes situaciones. Todavía no puedo encontrar una solución que se adapte a mis necesidades.

Aquí están mis requisitos:

  1. Para poder usar el atributo [HandleError] (o algo equivalente) en mi Controlador, para manejar todas las excepciones que podrían producirse desde cualquiera de las Acciones o Vistas. Esto debería manejar todas las excepciones que no se manejaron específicamente en ninguna de las Acciones (como se describe en el punto 2). Me gustaría poder especificar a qué Vista se debe redirigir a un usuario en casos de error, para todas las acciones en el Controlador.

  2. Quiero poder especificar el atributo [HandleError] (o algo equivalente) en la parte superior de Acciones específicas para detectar excepciones específicas y redirigir a los usuarios a una Vista apropiada para la excepción. Todas las demás excepciones aún deben ser manejadas por el atributo [HandleError] en el Controlador.

  3. En los dos casos anteriores, quiero que las excepciones se registren utilizando log4net (o cualquier otra biblioteca de registro).

¿Cómo hago para lograr lo anterior? He leído acerca de cómo hacer que todos mis Controladores se hereden de un controlador base que reemplaza el método OnException, y en el que hago mi registro. Sin embargo, esto generará problemas al redirigir a los usuarios a las Vistas apropiadas, o lo hará desordenado.

He leído sobre cómo escribir mi propia Acción de filtro que implementa IExceptionFilter para manejar esto, pero esto entrará en conflicto con el atributo [HandleError].

Hasta ahora, mi opinión es que la mejor solución es escribir mi propio atributo que se hereda de HandleErrorAttribute. De esa manera, obtengo toda la funcionalidad de [HandleError], y puedo agregar mi propio registro log4net. La solución es la siguiente:

public class HandleErrorsAttribute: HandleErrorAttribute { private log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public override void OnException(ExceptionContext filterContext) { if (filterContext.Exception != null) { log.Error("Error in Controller", filterContext.Exception); } base.OnException(filterContext); } }

¿Funcionará el código anterior para mis requisitos? Si no es así, ¿qué solución cumple con mis requisitos?


Todavía estoy un poco confundido con las diferentes soluciones que existen y cómo los atributos pueden interferir entre sí, pero opté por esta solución:

public class LogErrorsAttribute: FilterAttribute, IExceptionFilter { #region IExceptionFilter Members void IExceptionFilter.OnException(ExceptionContext filterContext) { if (filterContext != null && filterContext.Exception != null) { string controller = filterContext.RouteData.Values["controller"].ToString(); string action = filterContext.RouteData.Values["action"].ToString(); string loggerName = string.Format("{0}Controller.{1}", controller, action); log4net.LogManager.GetLogger(loggerName).Error(string.Empty, filterContext.Exception); } } #endregion }

Todavía utilizo el atributo [HandleError] como se explica en la pregunta original, y simplemente decoro cada controlador con un atributo [LogErrors].

Esto funciona para mí, ya que mantiene el registro de errores en un solo lugar y no hace que se registren excepciones duplicadas varias veces (lo que ocurrirá si extiendo [HandleError] y uso el atributo en varios lugares).

No creo que sea posible combinar el Registro de excepciones y el Manejo de errores en un atributo o clase, sin que sea muy tedioso y complejo, ni afecte el uso de [HandleError]

Pero esto funciona para mí, ya que decoro cada controlador solo una vez, con el atributo [LogErrors], y decoro Controladores y Acciones con [HandleError] exactamente como quiero, sin que interfieran entre sí.

Actualizar:

Aquí hay un ejemplo de cómo lo uso:

[LogErrors(Order = 0)] [HandleError(Order = 99)] public class ContactController : Controller { public ActionResult Index() { return View(Views.Index); } public ActionResult Directions() { return View(Views.Directions); } public ActionResult ContactForm() { FormContactMessage formContactMessage = new FormContactMessage(); return View(Views.ContactForm,formContactMessage); } [HandleError(ExceptionType = typeof(SmtpException), View = "MessageFailed", Order = 1)] [AcceptVerbs(HttpVerbs.Post)] public ActionResult ContactForm(FormContactMessage formContactMessage) { if (ModelState.IsValid) { if (formContactMessage.IsValid) { SmtpClient client = new SmtpClient(); MailAddress recipientAddress = new MailAddress(Properties.Settings.Default.ContactFormRecipientEmailAddress); MailAddress senderAddress = new MailAddress(Properties.Settings.Default.ContactFormSenderEmailAddress); MailMessage mailMessage = formContactMessage.ToMailMessage(recipientAddress, senderAddress); client.Send(mailMessage); return View("MessageSent"); } else { ModelState.AddRuleViolations(formContactMessage.GetRuleViolations()); } } return View(Views.ContactForm, formContactMessage); } private static class Views { public static string Index { get { return "Index"; } } public static string Directions { get { return "Directions"; } } public static string ContactForm { get { return "ContactForm"; } } } }

En el código anterior, las SmtpExceptions en la sobrecarga de acción de ContactForm se manejan de una manera muy específica: al usuario se le presenta un ViewPage específico para los mensajes enviados con error, en este caso se llama "MessageFailed". Todas las demás excepciones son manejadas por el comportamiento predeterminado de [HandleError]. También tenga en cuenta que el registro de errores ocurre primero, seguido por el manejo de errores. Esto se indica por lo siguiente:

[LogErrors(Order = 0)] [HandleError(Order = 99)]

Actualizar:

Hay una solución alternativa a esto, con una muy buena explicación. Recomiendo leerlo para comprender mejor los problemas involucrados.

ASP.NET MVC HandleError Atributo, páginas de error personalizadas y excepciones de registro (Gracias a Scott Shepherd a continuación, quien proporcionó el enlace en una respuesta a continuación).