Mostrar una página de error personalizado (C#)

por Scott Mitchell

¿Qué ve el usuario cuando se produce un error en runtime en una aplicación web de ASP.NET? La respuesta depende de la configuración de <customErrors> del sitio web. De forma predeterminada, los usuarios muestran una YSOD nosightly que anuncia que se ha producido un error en runtime. En este tutorial se muestra cómo personalizar esta configuración para mostrar una página de error personalizada estéticamente agradable que coincida con el aspecto de su sitio.

Introducción

En un mundo perfecto no habría errores en runtime. Los programadores escribirían código sin apenas errores y con una sólida validación de las entradas de usuario, y los recursos externos, como servidores de bases de datos y de correo electrónico, nunca se desconectarían. Por supuesto, en la realidad los errores son inevitables. Las clases de .NET Framework indican un error al producir una excepción. Por ejemplo, llamar al método Open de un objeto SqlConnection establece una conexión a la base de datos especificada por una cadena de conexión. Sin embargo, si la base de datos está inactiva o si las credenciales de la cadena de conexión no son válidas, el método Open produce un SqlException. Las excepciones se pueden controlar mediante el uso de bloques try/catch/finally. Si el código dentro de un bloque try produce una excepción, el control se transfiere al bloque catch adecuado donde el desarrollador puede intentar recuperarse del error. Si no hay ningún bloque catch coincidente o si el código que produjo la excepción no está en un bloque try, la excepción se filtra en la pila de llamadas en busca de bloques try/catch/finally.

Si la excepción llega hasta el runtime de ASP.NET sin controlarse, se lanza el evento Error de la clase HttpApplication y se muestra la página de error configurada. Por defecto, ASP.NET muestra una página de error que se conoce cariñosamente como la Yellow Screen of Death (Pantalla amarilla de la muerte) (YSOD). Hay dos versiones de YSOD: una muestra los detalles de la excepción, un seguimiento de pila y otra información útil para los desarrolladores que depuran la aplicación (véase la ilustración 1); la otra simplemente indica que se produjo un error en runtime (véase la ilustración 2).

La YSOD de detalles de la excepción es bastante útil para los desarrolladores que depuran la aplicación, pero mostrar una YSOD a los usuarios finales es poco profesional y de mal gusto. En su lugar, los usuarios finales deben ser conducidos a una página de error que mantenga la apariencia del sitio con una prosa más fácil de usar que describa la situación. La buena noticia es que crear una página de error personalizada es bastante fácil. Este tutorial comienza con un vistazo a las diferentes páginas de error de ASP.NET. A continuación, se muestra cómo configurar la aplicación web para mostrar a los usuarios una página de error personalizada ante un error.

Examen de los tres tipos de páginas de error

Cuando surge una excepción no controlada en una aplicación ASP.NET se muestra uno de los tres tipos de páginas de error:

  • La YSOD de detalles de la excepción,
  • La YSOD de error en runtime, o
  • Una página de error personalizada

La página de error con la que los desarrolladores están más familiarizados es con la YSOD de detalles de la excepción. Por defecto, esta página se muestra a los usuarios que la visitan localmente y, por lo tanto, es la página que se ve cuando se produce un error al probar el sitio en el entorno de desarrollo. Como su nombre implica, la YSOD de detalles de la excepción proporciona detalles sobre la excepción: el tipo, el mensaje y el seguimiento de la pila. Además, si el código generó la excepción en la clase de código subyacente de la página ASP.NET y si la aplicación está configurada para la depuración, la YSOD de detalles de la excepción también mostrará esta línea de código (y algunas líneas de código anteriores y debajo).

La ilustración 1 muestra la YSOD de detalles de la excepción. Anote la dirección URL en la ventana de direcciones del explorador: http://localhost:62275/Genre.aspx?ID=foo. Recuerde que la página Genre.aspx enumera las reseñas de libros de un género determinado. Requiere que un valor GenreId (un uniqueidentifier) se pase a través de la cadena de consulta; por ejemplo, la dirección URL adecuada para ver las revisiones de ficción es Genre.aspx?ID=7683ab5d-4589-4f03-a139-1c26044d0146. Si se pasa un valor que no es uniqueidentifier a través de la cadena de consulta (por ejemplo, "foo") se produce una excepción.

Nota:

Para reproducir este error en la aplicación web de demostración disponible para descarga, puede visitar Genre.aspx?ID=foo directamente o hacer clic en el vínculo "Generar un error en runtime" en Default.aspx.

Tenga en cuenta la información de la excepción presentada en la ilustración 1. El mensaje de excepción "Error de conversión al convertir de una cadena de caracteres a uniqueidentifier" está presente en la parte superior de la página. También se muestra el tipo de excepción, System.Data.SqlClient.SqlException. También el seguimiento de la pila.

Screenshot that shows the exception details YSOD that include information about the exception.

Ilustración 1: la YSOD de detalles de la excepción incluye información sobre la excepción
(Haga clic para ver la imagen a tamaño completo.)

El otro tipo de YSOD es la de error en runtime y se muestra en la ilustración 2. La YSOD de error en runtime informa al visitante de que se ha producido un error en runtime, pero no incluye información sobre la excepción. (Sin embargo, proporciona instrucciones sobre cómo hacer que los detalles del error sean visibles modificando el archivo Web.config, que forma parte de lo que hace que una YSOD parezca no profesional).

De forma predeterminada, la YSOD de error en runtime se muestra a los usuarios que visitan de forma remota (a través de http://www.yoursite.com), como se evidencia en la dirección URL de la barra de direcciones del explorador en la ilustración 2: http://httpruntime.web703.discountasp.net/Genre.aspx?ID=foo. Existen dos pantallas YSOD diferentes porque los desarrolladores están interesados en conocer los detalles del error, pero dicha información no debe mostrarse en un sitio activo, ya que puede revelar posibles vulnerabilidades de seguridad u otra información confidencial a cualquier persona que visite su sitio.

Nota:

Si usa DiscountASP.NET como host web, es posible que observe que la YSOD de error en runtime no se muestra al visitar el sitio activo. Esto se debe a que DiscountASP.NET tiene sus servidores configurados para mostrar la YSOD de detalles de la excepción de forma predeterminada. La buena noticia es que puede invalidar este comportamiento predeterminado agregando una sección <customErrors> al archivo Web.config. La sección Configurar qué página de error se muestra examina detalladamente la sección <customErrors>.

Screenshot that shows the runtime error YSOD doesn't include any error details.

Ilustración 2: la YSOD de error en runtime no incluye ningún detalle de error
(Haga clic para ver la imagen a tamaño completo.)

El tercer tipo de página de error es la página de error personalizada, que es una página web que se crea. La ventaja de una página de error personalizada es que tiene control total sobre la información que se muestra al usuario junto con la apariencia de la página; la página de error personalizada puede usar la misma página maestra y estilos que las otras páginas. En la sección "Usar una página de error personalizada" se explica cómo crear una página de error personalizada y configurarla para que se muestre en caso de una excepción no controlada. La ilustración 3 ofrece una muestra de esta página de error personalizada. Como puede ver, la apariencia de la página de error es mucho más profesional que cualquiera de las YSOD mostradas en las ilustraciones 1 y 2.

Screenshot that shows a custom error page that demonstrates a more tailored look and feel.

Ilustración 3: una página de error personalizada ofrece una apariencia más adaptada
(Haga clic para ver la imagen a tamaño completo.)

Dedique un momento a inspeccionar la barra de direcciones del explorador en la ilustración 3. Tenga en cuenta que la barra de direcciones muestra la dirección URL de la página de error personalizada (/ErrorPages/Oops.aspx). En las ilustraciones 1 y 2, las YSOD se muestran en la misma página de la que se originó el error (Genre.aspx). La página de error personalizada se pasa a la dirección URL de la página donde se produjo el error a través del parámetro querystring de aspxerrorpath.

Configuración de la página de error que se muestra

Cuál de las tres páginas de error posibles se muestra se basa en dos variables:

  • Información de configuración de la sección <customErrors> y
  • si el usuario está visitando el sitio de forma local o remota.

La sección <customErrors> de Web.config tiene dos atributos que afectan a la página de error que se muestra: defaultRedirect y mode. El atributo defaultRedirect es opcional. Si se proporciona, especifica la dirección URL de la página de error personalizada e indica que se debe mostrar la página de error personalizada en lugar de la YSOD de error en runtime. El atributo mode es necesario y acepta uno de los tres valores: On, Offo RemoteOnly. Estos valores tienen el siguiente comportamiento:

  • On: indica que la página de error personalizada o la YSOD de error en runtime se muestra a todos los visitantes, independientemente de si son locales o remotos.
  • Off: especifica que la YSOD de detalles de la excepción se muestra a todos los visitantes, independientemente de si son locales o remotos.
  • RemoteOnly: indica que la página de error personalizada o la YSOD de error en runtime se muestran a los visitantes remotos, mientras que la YSOD de detalles de la excepción se muestra a los visitantes locales.

A menos que especifique lo contrario, ASP.NET actúa como si hubiera establecido el atributo mode en RemoteOnly y no hubiera especificado un valor defaultRedirect. En otras palabras, el comportamiento predeterminado es que la YSOD de detalles de la excepción se muestre a los visitantes locales mientras que la YSOD de error en runtime se muestre a los visitantes remotos. Para invalidar este comportamiento predeterminado, agregue una sección <customErrors> a la Web.config file. de la aplicación web

Uso de una página de error personalizada

Cada aplicación web debe tener una página de error personalizada. Proporciona una alternativa más profesional a la YSOD de error en runtime, es fácil de crear y configurar la aplicación para usar la página de error personalizada solo tarda unos instantes. El primer paso consiste en crear la página de error personalizada. He agregado una nueva carpeta a la aplicación Opiniones de libros denominada ErrorPages y se ha agregado a esa nueva página de ASP.NET denominada Oops.aspx. Haga que la página use la misma página maestra que el resto de las páginas del sitio para que herede automáticamente la misma apariencia.

Screenshot that highlights the new ErrorPages folder and associated Oops dot a s p x file.

Ilustración 4: crear una página de error personalizada

A continuación, dedique unos minutos a crear el contenido de la página de error. He creado una página de error personalizada bastante sencilla con un mensaje que indica que se produjo un error inesperado y un vínculo a la página principal del sitio.

Screenshot that shows the custom error page and associated message.

Ilustración 5: diseño de la página de error personalizada
(Haga clic para ver la imagen a tamaño completo.)

Una vez completada la página de error, configure la aplicación web para que use la página de error personalizada en lugar de la YSOD de error en runtime. Esto se logra especificando la dirección URL de la página de error en el atributo defaultRedirect de la sección <customErrors>. Agregue el siguiente marcado al archivo Web.config de la aplicación:

<configuration>
    ...

    <system.web>
        <customErrors mode="RemoteOnly"
                      defaultRedirect="~/ErrorPages/Oops.aspx" />

        ...
    </system.web>
</configuration>

El marcado anterior configura la aplicación para mostrar la YSOD de detalles de la excepción a los usuarios que visitan localmente, mientras se usa la página de error personalizada Oops.aspx para aquellos usuarios que visitan de forma remota. Para ver esto en acción, implemente el sitio web en el entorno de producción y, a continuación, visite la página de Genre.aspx en el sitio activo con un valor de cadena de consulta no válido. Debería ver la página de error personalizada (véase la ilustración 3).

Para comprobar que la página de error personalizada solo se muestra a los usuarios remotos, visite la página Genre.aspx con una cadena de consulta no válida del entorno de desarrollo. Debería ver la YSOD de detalles de la excepción (véase la ilustración 1). La configuración de RemoteOnly garantiza que los usuarios que visitan el sitio en el entorno de producción vean la página de error personalizada mientras los desarrolladores trabajan localmente siguen viendo los detalles de la excepción.

Notificar a los desarrolladores y registrar los detalles del error

Los errores que se producen en el entorno de desarrollo fueron causados por el desarrollador sentado en su equipo. Se muestra la información de la excepción en la YSOD de detalles de la excepción y sabe qué pasos estaba realizando cuando se produjo el error. Pero cuando se produce un error en producción, el desarrollador no tiene conocimiento de que se produjo un error a menos que el usuario final que visita el sitio tarde el tiempo para notificar el error. E incluso si el usuario sale de su camino para alertar al equipo de desarrollo de que se produjo un error, sin conocer el tipo de excepción, el mensaje y el seguimiento de la pila, puede ser difícil diagnosticar la causa del error, mucho menos corregirlo.

Por estas razones es primordial que cualquier error en el entorno de producción se registre en algún almacén persistente (como una base de datos) y que los desarrolladores sean alertados de este error. La página de error personalizada puede parecer un buen lugar para realizar este registro y notificación. Desafortunadamente, la página de error personalizada no tiene acceso a los detalles del error y, por lo tanto, no se puede usar para registrar esta información. La buena noticia es que hay varias maneras de interceptar los detalles del error y registrarlos, y los siguientes tres tutoriales exploran este tema con más detalle.

Uso de diferentes páginas de error personalizadas para diferentes estados de error HTTP

Cuando una página de ASP.NET produce una excepción y no se controla, la excepción se filtra hasta el runtime de ASP.NET, que muestra la página de error configurada. Si una solicitud entra en el motor de ASP.NET, pero no se puede procesar por algún motivo, quizás no se encuentra el archivo solicitado o los permisos de lectura se han deshabilitado para el archivo ; el motor de ASP.NET genera un HttpException. Esta excepción, como las excepciones generadas desde ASP.NET páginas, se propagan hasta el runtime, lo que provoca que se muestre la página de error adecuada.

Lo que significa para la aplicación web en producción es que si un usuario solicita una página que no se encuentra, verá la página de error personalizada. En la ilustración 6 se muestra este ejemplo. Dado que la solicitud es para una página no existente (NoSuchPage.aspx), se produce un HttpException y se muestra la página de error personalizada (tenga en cuenta la referencia a NoSuchPage.aspx en el parámetro querystring de aspxerrorpath).

Screenshot that shows how the A S P dot NET runtime displays the configured error page.

Ilustración 6: el runtime de ASP.NET muestra la página de error configurada en respuesta a una solicitud no válida (Haga clic para ver la imagen a tamaño completo)

De forma predeterminada, todos los tipos de errores hacen que se muestre la misma página de error personalizada. Sin embargo, puede especificar una página de error personalizada diferente para un código de estado HTTP específico mediante <error> elementos secundarios dentro de la sección <customErrors>. Por ejemplo, para que se muestre una página de error diferente en caso de que no se encuentre una página, que tiene un código de estado HTTP de 404, actualice la sección <customErrors> para incluir el siguiente marcado:

<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/Oops.aspx">
    <error statusCode="404" redirect="~/ErrorPages/404.aspx" />
</customErrors>

Con este cambio en su lugar, cada vez que un usuario que visita de forma remota solicita un recurso de ASP.NET que no existe, se le redirigirá a la página de error personalizada 404.aspx en lugar de Oops.aspx. Como se muestra en la ilustración 7, la página 404.aspx puede incluir un mensaje más específico que la página de error personalizada general.

Nota:

Consulte páginas de error 404, Una vez más para obtener instrucciones sobre cómo crear páginas de error efectivas de 404.

Screenshot that shows the custom 4 O 4 error page.

Ilustración 7: la página de error personalizada 404 muestra un mensaje más dirigido que Oops.aspx
(Haga clic para ver la imagen a tamaño completo.)

Dado que sabe que la página 404.aspx solo se alcanza cuando el usuario realiza una solicitud de una página que no se encontró, puede mejorar esta página de error personalizada para incluir funcionalidad para ayudar al usuario a solucionar este tipo de error específico. Por ejemplo, podría crear una tabla de base de datos que asigne direcciones URL incorrectas conocidas a direcciones URL correctas y, a continuación, hacer que la página de error personalizada 404.aspx ejecute una consulta en esa tabla y sugerir páginas a las que el usuario esté intentando llegar.

Nota:

La página de error personalizada solo se muestra cuando se realiza una solicitud a un recurso controlado por el motor de ASP.NET. Como se ha descrito en el tutorial de Diferencias principales entre IIS y el del servidor de desarrollo de ASP.NET, el servidor web puede controlar determinadas solicitudes. De forma predeterminada, el servidor web de IIS procesa solicitudes de contenido estático como imágenes y archivos HTML sin invocar el motor de ASP.NET. En consecuencia, si el usuario solicita un archivo de imagen inexistente, recibirá el mensaje de error 404 predeterminado de IIS en lugar de la página de error configurada de ASP.NET.

Resumen

Cuando se produce una excepción no controlada en una aplicación de ASP.NET, el usuario muestra una de las tres páginas de error: la YSOD de detalles de la excepción; la YSOD de error en runtime; o una página de error personalizada. La página de error que se muestra depende de la configuración <customErrors> de la aplicación y de si el usuario está visitando local o remotamente. El comportamiento predeterminado es mostrar la YSOD de detalles de la excepción a los visitantes locales y la YSOD de error de runtime a los visitantes remotos.

Mientras que la YSOD de error en runtime oculta información de error potencialmente confidencial del usuario que visita el sitio, se interrumpe de la apariencia del sitio y hace que la aplicación tenga un aspecto erróneo. Un mejor enfoque consiste en usar una página de error personalizada, lo que implica crear y diseñar la página de error personalizada y especificar su dirección URL en el atributo defaultRedirect de la sección <customErrors>. Incluso puede tener varias páginas de error personalizadas para diferentes estados de error HTTP.

La página de errores personalizada es el primer paso de una estrategia completa de control de errores para un sitio web en producción. Alertar al desarrollador del error y registrar sus detalles también son pasos importantes. En los tres tutoriales siguientes se exploran las técnicas de notificación y registro de errores.

¡Feliz programación!

Lecturas adicionales

Para obtener más información sobre los temas tratados en este tutorial, consulte los siguientes recursos: