¿Cuáles son las pautas definitivas para la gestión personalizada de errores en ASP.NET MVC 3?

44

El proceso de manejo de errores personalizado en ASP.NET MVC (3 en este caso) parece estar increíblemente descuidado. He leído las diversas preguntas y respuestas aquí, en la web, páginas de ayuda para diversas herramientas (como Elmah), pero siento que he ido en un círculo completo y todavía no tengo la mejor solución. Con su ayuda, quizás podamos establecer un nuevo enfoque estándar para el manejo de errores. Me gustaría mantener las cosas simples y no sobre-diseñar esto.

Aquí están mis objetivos:

Para errores / excepciones del servidor:

  1. Mostrar información de depuración en dev
  2. Mostrar página de error amigable en producción
  3. Registrar errores y enviarlos por correo electrónico al administrador en producción
  4. Devolver 500 Código de estado HTTP

Para errores 404 no encontrados:

  1. Mostrar página de error amigable
  2. Registrar errores y enviarlos por correo electrónico al administrador en producción
  3. Devolver el código de estado HTTP 404

¿Hay alguna manera de cumplir estos objetivos con ASP.NET MVC?

RyanW
fuente
2
Me gustaría migrar esta pregunta de regreso a SO para que pueda obtener más respuestas. Estoy buscando respuestas codificadas.
Shawn Mclean
@ Shawn Eso es poco probable que suceda. La pregunta es más sobre el tema aquí que sobre SO y tiene una respuesta aceptada. Las preguntas generalmente tampoco se vuelven a migrar por razones técnicas. Si necesita ayuda para codificar un enfoque específico de manejo de errores, abra una nueva pregunta en StackOverflow. De lo contrario, las "respuestas codificadas" pueden ser un criterio demasiado amplio para ser útil o responder. Por último, pero no menos importante, la mejor manera de atraer la atención del moderador a una pregunta es marcarla. Su comentario aquí probablemente habría pasado desapercibido si no activara una marca automática al presionar el recuento de comentarios sobre 20.
Adam Lear
Solía ​​haber unos 10 comentarios aquí, ¿a dónde fueron todos?
RyanW
Encontré una solución que cumple con tus objetivos. Lo tengo como otra respuesta en SO: stackoverflow.com/questions/6508415/…
Jesse Webb
1
@AnnaLear Estoy de acuerdo con Shawn. Solo encontré esta página a través de Google. Tenga en cuenta que casi todas las respuestas a continuación contienen enlaces BACK a Stack Overflow. Para mí, eso dice mucho, ya que debería haberse dejado allí en primer lugar.
Rebecca

Respuestas:

23

Compartiré la forma en que terminé haciendo esto, eso fue parte de la pregunta original.

Primero, los problemas que encontré:

  1. Con customErrors activado (es decir, en producción), el HandleErroratributo global traga excepciones y muestra su vista de error, pero no puede iniciar sesión con una herramienta adicional como elmah, ya que elmah nunca lo ve. Supongo que podría iniciar sesión en su vista, pero es una vista que parece incorrecta. El atributo global HandleError aparece nuevo en la plantilla de proyecto MVC 3 RTM Visual Studio.

  2. customErrors con URL para puntos finales MVC devuelve 302 códigos de estado. Existe la propiedad redirectmode, pero no puede hacer coincidir las URL de mvc en customErrors y usar el modo ResponseRewrite. ( https://stackoverflow.com/questions/781861/customerrors-does-not-work-when-setting-redirectmode-responserewrite/3770265#3770265 )

  3. Evitar errores personalizados por completo y manejar todo lo personalizado en su aplicación conduce a una gran complejidad, IMO. (Me encantó esto: https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095 , pero no fue adecuado para nuestro proyecto)

Mi solución

He sacado MVC de la ecuación por completo. He quitado HandleErrorAttributeel filtro global en global.asax y centrarse exclusivamente en la configuración customErrors, desplazándola a utilizar WebForm redirecciones y el cambio a redirectmode a ResponseRewritefin de evitar los 302 códigos de respuesta HTTP.

<customErrors mode="On" defaultRedirect="/Error.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="/NotFound.aspx" />
</customErrors>

Luego, en el NotFound.aspxevento page_load, configure el Response.StatusCode404 y en Error.aspx configure el código 500.

Resultados:

Los objetivos para ambos se han logrado con los registros de Elmah, la página de error amigable y el código de estado con una línea de código en los códigos subyacentes. No lo estamos haciendo a la "manera MVC" como lo hace la solución anterior, pero estoy de acuerdo con eso si son dos líneas de código.

RyanW
fuente
5

Creo que MVC, ASP y su marco de registro / manejo de excepciones favorito pueden manejar sus objetivos bastante bien. ELMAH y Enterprise Library proporcionan un manejo y registro de excepciones fácil de usar, así que elige tu favorito ... No voy a entrar en los pros y los contras de cada uno aquí.

NOTA: no puede mostrar una página de error amigable Y devolver un HTTP 404 o 500 como sugiere su pregunta. Cuando devuelve una página de error amigable, el código HTTP devuelto a su navegador será 302. Esta es una redirección a la página de error amigable.

Páginas de error amigables

Parece que puede lograr sus objetivos con la buena configuración web.config que ha sido parte de ASP.net por algún tiempo. Usted menciona mostrar información de depuración cuando está en desarrollo y mostrar páginas amigables en producción. Puede usar la sección de errores personalizados de web.config para esto (Establecer CustomErrors = "Off" para mostrar información de depuración). Asumiré que está familiarizado con el atributo CustomErrors, si no, lea esto:

http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx

Si necesita una mayor granularidad de control sobre las vistas de error que muestra, utilice el atributo HandleError de MVC. De esta forma, puede elegir diferentes vistas de error para cada Acción / Controlador.

http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx

Registro de excepciones

Parece que quiere responder a todas sus excepciones de la misma manera ('Registrar errores y enviarlos por correo electrónico al administrador en producción'). Si este es el caso, su opción más simple es agregar código a

Application_Error (remitente del objeto, EventArgs e)

en su global.asax. Aquí es donde puede pasar a su marco de registro elegido.

Si desea más control sobre su registro / manejo de excepciones, entonces puede subclasificar HandleErrorAttribute y anular

OnException(System.Web.Mvc.ExceptionContext filterContext)

Este es otro lugar donde puede pasar a su marco de registro elegido.

https://stackoverflow.com/questions/183316/asp-net-mvc-handleerror

Esto le da más control que la técnica Application_Error mencionada anteriormente.

En general, MVC le brinda una gran granularidad de control sobre cómo manejar los errores. Si no necesita este control, puede recurrir a las formas ASP.net de hacer cosas como definir páginas de error en su web.config.

nixon
fuente
Muchas gracias por agregar tus pensamientos. Creo que el código de estado 302 es una mala elección de diseño por parte del equipo original de ASP.NET. Me ocuparé de eso en mis respuestas también, hay algunas opciones para hacerlo. Parece que algunos en el mundo MVC están abandonando completamente CustomErrors y manejándolo todo en la aplicación para una mejor reutilización y más control a medida que lo señala. Pero, tuve un éxito limitado en la implementación de esos y estaba agregando una gran cantidad de código que parecía estar mejor preparado. Más en mis respuestas a continuación.
Prefiero anular el método OnException para iniciar sesión, de esta manera sé que puedo registrar todo, incluso si se produce un error de una llamada Ajax que encuentro que no activará su Application_Error.
Alicia
@Alicia código de muestra completo?
Kiquenet