Uso de módulos y controladores HTTP para crear componentes de ASP.NET conectables
Scott Mitchell, 4GuysFromRolla.com
Atif Aziz, Skybow AG
Septiembre de 2004
Resumen: En este artículo, Scott Mitchell y Atif Aziz muestran cómo puede usar módulos y controladores HTTP para agregar el registro de errores a las aplicaciones de ASP.NET. (22 páginas impresas)
Descargue el archivo de ejemplo MSDNElmah.msi.
Contenido
Introducción
ELMAH: Módulos y controladores de registro de errores
Una breve introducción a los controladores y módulos HTTP
Examen de la arquitectura de ELMAH
Adición de ELMAH a una aplicación web de ASP.NET
Conclusión
Referencias
Libros relacionados
Introducción
¿Alguna vez ha trabajado en una aplicación ASP.NET y ha diseñado algunas funciones o conjuntos de características útiles que desea poder reutilizar fácilmente en otra aplicación ASP.NET? ASP.NET ofrece diferentes herramientas para la componenteción de diferentes tipos de funcionalidad. Las dos herramientas más comunes para reutilizar en ASP.NET son:
- Controles de usuario y controles de servidor compilados personalizados para elementos y funcionalidades de la interfaz de usuario.
- Bibliotecas de clases de .NET para la lógica de negocios y el código de acceso a datos.
Dos ASP.NET reutilizar herramientas que no reciben mucha atención son módulos y controladores HTTP.
Si no está familiarizado con lo que son los controladores y módulos HTTP, no se preocupe. Hablaremos más adelante sobre ellos en este artículo. Por ahora, solo tiene que entender que los módulos HTTP son clases que se pueden configurar para ejecutarse en respuesta a eventos que se activan durante la solicitud de un recurso de ASP.NET. Un controlador HTTP es una clase responsable de representar un recurso determinado o de un tipo determinado de recurso. De hecho, cada vez que agregue una página web de ASP.NET al proyecto, básicamente va a escribir un controlador HTTP. Esto se debe a que, cuando la parte HTML de una página web de ASP.NET se compila dinámicamente en tiempo de ejecución, hereda directa o indirectamente de System.Web.UI.Page
, lo que sucede que es una implementación del controlador HTTP. Esto es cierto independientemente de si se toma la estrategia insertada o de código subyacente.
Como sabe, una aplicación de ASP.NET normalmente consta de un conjunto de páginas web, que se invocan cuando se solicitan mediante el explorador de un usuario final. Como ASP.NET desarrolladores, la mayoría del código que se escribe es específico de una solicitud para una página web determinada, como el código de la clase de código subyacente de una página determinada para mostrar los resultados de la base de datos en función de alguna consulta de búsqueda. Sin embargo, hay ocasiones en que es necesario escribir código ortogonal en una sola página web, código que se aplica a todas las páginas de una aplicación. Por ejemplo, es posible que deseemos realizar un seguimiento del orden con el que cada usuario se mueve por nuestro sitio web. Para ello, tendríamos que hacer que cada página registre la hora de la solicitud y la información que identifica al usuario.
Una manera de proporcionar esta funcionalidad de registro sería agregar código que registró los datos de alemán en una base de datos en el Page_Load
controlador de eventos para cada página web del sitio. Sin embargo, este enfoque no es fácil de mantener ni reutilizar. Cada vez que agregamos una nueva página de ASP.NET en nuestro sitio, tendríamos que asegurarnos de incluir el código de registro adecuado. Si queríamos agregar una funcionalidad similar a otro sitio, tendríamos que pasar por cada página de ese sitio y agregar el código necesario. Idealmente, la funcionalidad de registro sería lógica y físicamente independiente de la funcionalidad de cada página individual y agregarla a otro sitio sería tan simple como quitar un ensamblado en el directorio del /bin
sitio.
Esta reutilización y mantenimiento es bastante posible con módulos y controladores HTTP. En este artículo, vamos a examinar un conjunto de módulos y controladores HTTP diseñados para hacer que el registro de errores sea un ejercicio muy fácil de mantener y reutilizable. El objetivo de este artículo es demostrar cómo se pueden usar los controladores y módulos HTTP como una forma muy alta de componentes, lo que permite desarrollar, empaquetar e implementar conjuntos completos de funcionalidades como una sola unidad e independiente de las aplicaciones web. Lograremos este objetivo en gran parte a través de un examen de una aplicación que se beneficia de la reutilización y la componenteización a través de controladores y módulos HTTP.
ELMAH: Módulos y controladores de registro de errores
El Error Logging Modules And Handlers (ELMAH), que examinaremos a lo largo de este artículo, fueron escritos por el coautor Atif Aziz (http://www.raboof.com/) y demuestran un medio fácil de agregar funcionalidades de registro de errores a una aplicación web de ASP.NET. ELMAH muestra cómo se pueden usar módulos y controladores HTTP para proporcionar un alto grado de componentes para el código que es ortogonal para la aplicación web (como el registro en todo la aplicación). ELMAH es una solución verdaderamente conectable, lo que significa que se puede agregar dinámicamente a una aplicación web en ejecución ASP.NET sin necesidad de volver a compilar o volver a implementar.
Independientemente de lo bien escrito y probado que sea una aplicación web determinada, las cosas seguirán rescribiendo cada momento y después. Es posible que no se produzca un error en el código, podría ser que el servidor de correo electrónico no responde o que algunos daños en los datos provocan un error criptográfico. Independientemente del motivo, cuando se produce una excepción, especialmente en un sitio activo, es importante que los detalles de la excepción se registren para ayudar a diagnosticar el problema. ELMAH proporciona un mecanismo para el registro y la notificación de errores centralizados. Cada vez que se produce una excepción en una aplicación de ASP.NET que no se detecta, se notifica a ELMAH y se controla la excepción como se indica en el archivo Web.config . Esto puede incluir registrar los detalles de la excepción en una base de datos, enviar un correo electrónico a un administrador o ambos.
ELMAH no está diseñado para responder correctamente a excepciones no controladas. Simplemente registra los detalles de las excepciones no controladas. Una vez que ELMAH se ha agregado a una aplicación web de ASP.NET, se registran todas las excepciones no controladas que se produzcan en esta aplicación. ELMAH no afecta a la experiencia del usuario final cuando se produce una excepción no controlada. Seguirán viendo la página "Error del servidor" o, si tiene errores personalizados configurados para controlar los errores HTTP 500, se les redirigirá a una página con un mensaje más fácil de usar. Pero en segundo plano, ELMAH habrá detectado que se produjo una excepción no controlada y registró los detalles.
ELMAH detecta excepciones no controladas mediante el evento Error del objeto HttpApplication. El Error
evento se genera siempre que una excepción no detectada se propaga durante el procesamiento de solicitudes, ya sea desde una biblioteca de clases de .NET o una página web de ASP.NET. Tenga en cuenta que muchas aplicaciones de ASP.NET implementan incorrectamente páginas de error personalizadas y control mediante una llamada al método Server.ClearError(). Borrar el error impedirá que el Error
evento se active (así como que se notifique al cliente) y, por tanto, ELMAH nunca tendrá la oportunidad de registrar la excepción. Para ponerlo de otra manera, al usar ClearError()
en una página de error personalizada, el usuario verá que se produjo un problema, pero no lo hará.
Nota Para obtener más información sobre cómo crear páginas de error personalizadas, lea el artículo de Eli Robillard rich Custom Error Handling with ASP.NET.
Nota Cuando se produce una excepción no controlada en un servicio web de ASP.NET, el
Error
evento no se propaga hasta módulos HTTP y, por tanto, ELMAH. En su lugar, se intercepta mediante el tiempo de ejecución de ASP.NET y se devuelve un error soap al cliente. Para tener un error registrado en un servicio web, tendría que crear una extensión SOAP que escuchara errores de SOAP.
Además de registrar detalles de excepciones no controladas, ELMAH también incluye un conjunto de controladores HTTP para ver el registro de errores. Hay una interfaz web para el registro, que puede proporcionar una lista de todos los errores no controlado, así como detalles sobre un error determinado (véase las figuras 1 y 2).
Figura 1. Visualización del registro de errores
Ilustración 2. Visualización de un error
Este registro de errores también se puede representar como RSS, lo que permite a un administrador recibir notificaciones a través de su agregador RSS favorito cuando se ha producido un error (consulte la figura 3).
Figura 3. Fuente RSS de errores
Nota RSS, que significa Realmente Simple Syndication, es un estándar con formato XML que se usa normalmente para distribuir noticias y otros tipos de contenido cambiante. Para obtener más información sobre RSS, incluido cómo distribuir contenido mediante RSS, así como cómo crear un lector RSS basado en Web, considere la posibilidad de leer Crear un agregador de noticias en línea con ASP.NET.
Por motivos de brevedad, en este artículo solo se aborda un subconjunto de las características de ELMAH, centrándose en los componentes clave. El código completo está disponible para su descarga con este artículo y le animamos a estudiarlo exhaustivamente para obtener los detalles de la implementación. También hay una configuración del área de trabajo de GotDotNet para ELMAH a http://workspaces.gotdotnet.com/elmah efectos de discusiones, informes de problemas y mantenerse al día de los cambios.
Soluciones existentes para el registro de errores centralizado
Aunque ASP.NET no proporciona funcionalidades integradas de registro y visualización de errores, el grupo de procedimientos de & patrones de Microsoft ha creado un registrador de errores de código abierto, el bloque de aplicaciones de administración de excepciones (EMAB). EmAB se diseñó para trabajar con aplicaciones .NET basadas en web y de escritorio, pero no puede ayudar a sentir que EMAB se diseñó principalmente para aplicaciones de escritorio con aplicaciones web como una idea posterior porque EMAB, de forma predeterminada, publica los detalles de excepción en el registro de eventos de Windows. Aunque el registro de eventos es un almacén de respaldo adecuado para obtener información de excepción concisa para una aplicación de escritorio, la mayoría de las aplicaciones web , especialmente las que se hospedan en un servidor compartido en una empresa de hospedaje web, se desactiven del registro de eventos porque el uso del registro de eventos requiere permisos especiales para permitir que la aplicación ASP.NET escriba en el registro de eventos. Concedido, EMAB es lo suficientemente flexible como para crear un publicador personalizado que registra información en una base de datos, pero es un paso adicional con el que usted, el desarrollador, se encarga.
Nota ELMAH se incluye con un módulo de registro de bases de datos para Microsoft SQL Server 2000, que analizaremos más adelante. Con ELMAH también puede crear registradores de excepciones personalizados, como un registrador que registra los detalles de la excepción en un archivo XML en el sistema de archivos del servidor web. De hecho, podría ampliar ELMAH para usar el bloque de aplicación de administración de excepciones, si ya tenía un publicador personalizado escrito para la EMAB que quería usar.
Cómo se usa EMAB para registrar la información de excepciones influye fuertemente en el mantenimiento y la reutilización de la aplicación web. Por ejemplo, un enfoque ingenuo para registrar información de excepciones sería colocar un try ...catch
bloque alrededor de cada bloque de código en cada página web de ASP.NET, llamando a EMAB en la catch
sección .
private void Page_Load(object sender, EventArgs e) { try { // Code that might cause an exception } catch (Exception ex) { // record exception information by calling exception logger library } }
Este enfoque es infalible, ya que acopla estrechamente el registro de excepciones a cada página web y cada ASP.NET, lo que hace que sea cualquier cosa, pero fácil de mantener o reutilizable. Un mejor enfoque sería utilizar el EMAB en el Application_Error
evento en Global.asax. Este enfoque ofrece una arquitectura más flexible, fácil de mantener y reutilizable, ya que el código de publicación de excepciones no toca ninguna página web ASP.NET y se encuentra en una ubicación centralizada. El inconveniente de este enfoque es que no se puede conectar. Para agregar esta funcionalidad de registro de errores a otra aplicación web de ASP.NET, tendría que modificar esa Global.asax
aplicación, por lo que era necesario volver a compilar y volver a implementar la aplicación.
El punto de este artículo no es introducir un reemplazo para la EMAB. En su lugar, es resaltar la componenteización que permiten los controladores HTTP y los módulos. ELMAH muestra cómo se puede tomar una tarea común, como el registro de errores centralizado y la componente para facilitar el mantenimiento y permitir un alto grado de reutilización. El propósito de ELMAH es ofrecer instrucciones para la creación de componentes de la funcionalidad aplicable.
Una breve introducción a los controladores y módulos HTTP
Antes de pasar a examinar los detalles de la arquitectura y la implementación de ELMAH, dediquemos un momento a revisar los controladores y módulos HTTP. Cada vez que llega una solicitud a un servidor web de IIS, IIS examina la extensión de la solicitud para decidir cómo continuar. Para el contenido estático, como páginas HTML, archivos CSS, imágenes, archivos JavaScript, etc., IIS controla la propia solicitud. Para el contenido dinámico, como páginas ASP, ASP.NET páginas web y servicios web ASP.NET, IIS delega la solicitud a una extensión ISAPI especificada. Una extensión ISAPI es un fragmento de código no administrado que sabe cómo representar solicitudes de un tipo determinado. Por ejemplo, la asp.dll
extensión ISAPI es responsable de representar solicitudes de páginas web ASP clásicas; la aspnet_isapi.dll
extensión ISAPI se invoca cuando una solicitud entra en un recurso de ASP.NET.
Además de las extensiones ISAPI, IIS también permite filtros ISAPI. Un filtro ISAPI es un fragmento de código no administrado que se puede ejecutar en respuesta a los eventos generados por IIS. Durante el ciclo de vida de una solicitud, IIS pasa por una serie de pasos que generan los eventos correspondientes. Por ejemplo, se genera un evento cuando la solicitud llega por primera vez a IIS, cuando la solicitud está a punto de autenticarse, cuando el contenido representado está a punto de enviarse al cliente, etc. Los filtros ISAPI se usan normalmente para proporcionar funcionalidades como reescritura de direcciones URL, compresión, autenticación especializada y autorización, registro especializado, etc.
Cuando una solicitud de un recurso de ASP.NET llega a IIS, se enruta al motor de ASP.NET, que representa el contenido del recurso solicitado. El motor de ASP.NET se comporta mucho como IIS en que genera una serie de eventos a medida que la solicitud pasa a través de la canalización HTTP de ASP.NET. Además, el motor de ASP.NET delega la representación del recurso solicitado en una clase determinada. Mientras que IIS usa extensiones y filtros ISAPI no administrados, ASP.NET usa clases administradas denominadas controladores y módulos HTTP.
Un controlador HTTP es una clase responsable de representar un tipo determinado de recurso. Por ejemplo, la clase de código subyacente de una página web de ASP.NET es un controlador HTTP, sabiendo cómo representar el marcado para la página web concreta. Ayuda a pensar en los controladores como representadores especializados que saben cómo crear el marcado para un tipo determinado de recurso.
Nota Para obtener una explicación más detallada sobre los controladores HTTP, junto con algunas aplicaciones prácticas de controladores, asegúrese de leer Servir contenido dinámico con controladores HTTP.
Un módulo HTTP es una clase que puede pulsar en los distintos eventos generados como una solicitud pasa por fases de su ciclo de vida en el servidor. Uno de estos ASP.NET evento de aplicación es el Error
evento , que se desencadena cuando se produce una excepción no controlada, que es el evento ELMAH interesado.
Nota Para obtener más información sobre los módulos HTTP, incluido un vistazo a cómo usar módulos HTTP para implementar la reescritura de direcciones URL, consulte Reescritura de direcciones URL en ASP.NET.
En la figura 4 se proporciona una representación gráfica de la canalización HTTP de ASP.NET. Tenga en cuenta que el proceso comienza con una solicitud que llega a IIS. Suponiendo que el recurso solicitado está configurado para que lo controle la extensión ISAPI de ASP.NET, IIS envía la solicitud a la extensión ISAPI no administrada aspnet_isapi.dll
. Esta extensión ISAPI pasa la solicitud al motor de ASP.NET administrado. Durante el ciclo de vida de la solicitud, se pueden ejecutar uno o varios módulos HTTP, en función de los módulos registrados y de los eventos a los que se han suscrito. Por último, el motor de ASP.NET determina el controlador HTTP responsable de representar el contenido, invocando el controlador y devolviendo el contenido generado a IIS, que lo devuelve al cliente solicitante.
Figura 4. Flujo de datos a través del registrador de errores
ELMAH proporciona un registro de errores centralizado a través de un módulo HTTP que tiene un controlador de eventos para el Error
evento. Cuando se desencadena el evento, ELMAH registra los detalles de la excepción. ELMAH también usa controladores HTTP que son principalmente responsables de generar marcado HTML y RSS para mostrar información del registro de errores.
La configuración de una aplicación web existente para usar varios controladores o módulos se realiza copiando el módulo o ensamblado del controlador en el directorio de /bin
la aplicación web y agregando algunas líneas de configuración al Web.config
archivo.
Para configurar los módulos HTTP para una aplicación web, incluya una <sección httpModules> en el Web.config
archivo que especifica el tipo del módulo que se va a agregar:
<httpModules> <add name="ModuleName" type="ModuleType" /> </httpModules>
ModuleType es una cadena que escribe el tipo del módulo, que es el nombre de clase completo (Namespace.ClassName) seguido del nombre del ensamblado. El type
atributo también puede incluir información de control de versiones y referencia cultural, junto con un token de clave pública que se requiere de ensamblados con nombre seguro. En el fragmento de código siguiente se muestra la configuración real <httpModules>
que deberá usar para incluir el módulo de registro de errores de ELMAH en la aplicación de ASP.NET:
<httpModules> <add name="ErrorLog" type="GotDotNet.Elmah.ErrorLogModule, GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, PublicKeyToken=978d5e1bd64b33e5" /> </httpModules>
Un controlador HTTP se puede usar en una aplicación web agregando una <sección httpHandlers> al Web.config
archivo. Dado que un controlador HTTP representa el contenido de un tipo determinado de recurso, además de un type
atributo, el <httpHandlers>
elemento contiene un path
atributo , que indica qué rutas de acceso o extensiones de archivo se deben asignar a este controlador HTTP. También hay un verb
atributo que permite limitar el uso del controlador a tipos específicos de solicitudes HTTP, como en una solicitud GET o POST. En el ejemplo siguiente se crea un controlador HTTP que se invoca para todas las solicitudes a los archivos con una .ashx
extensión.
<httpHandlers> <add verb="*" path="*.ashx" type="HandlerType" /> </ httpHandlers >
El type
atributo del controlador HTTP se expresa con las mismas opciones de sintaxis que con los módulos HTTP. Esta configuración de también se puede colocar en Web.config
el archivo machine.config , lo que tiene el efecto de habilitar los controladores y módulos para todas las aplicaciones web del servidor. En el fragmento de código siguiente se muestra el <httpHandlers>
elemento del Web.config
archivo en la demostración incluida en la descarga de este artículo. Tenga en cuenta que indica que la ErrorLogPageFactory
clase debe representar las solicitudes entrantes a /elmah/default.aspx
.
<httpHandlers> <add verb="POST,GET,HEAD" path="elmah/default.aspx" type="GotDotNet.Elmah.ErrorLogPageFactory, GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, PublicKeyToken=978d5e1bd64b33e5" /> </httpHandlers>
Como puede ver, agregar módulos y controladores HTTP a una aplicación web de ASP.NET es muy sencillo, se puede hacer en cuestión de segundos y no requiere ninguna recompilación ni reimplementación de la aplicación de ASP.NET. Este es el motivo por el que los módulos y controladores HTTP son una excelente herramienta para reutilizarse y permitirse un medio para componentes de la aplicación en piezas de acoplamiento flexible y altamente fáciles de mantener.
Examinar la arquitectura de ELMAH
La arquitectura de ELMAH consta de tres subsistemas:
- Un subsistema de registro de errores
- Un subsistema de módulo HTTP
- Un subsistema de controlador HTTP
El subsistema de registro de errores es responsable de dos tareas: registrar errores en el registro y recuperar información de error del registro. El subsistema del módulo HTTP es responsable de registrar un error cuando se produce una excepción no controlada en la aplicación ASP.NET. El subsistema del controlador HTTP proporciona un medio para que el registro de errores se represente en el marcado, que constituye una interfaz basada en Web en el registro de errores, así como una fuente RSS.
Como se muestra en la figura 5, los subsistemas de módulo HTTP y controlador utilizan el subsistema de registro de errores. El subsistema del módulo HTTP envía información de excepción al subsistema de registro de errores, mientras que el subsistema del controlador HTTP lee y representa la información de error.
Figura 5. Dónde se ajusta el sistema de registro de errores
Para comprender mejor la arquitectura de ELMAH, examinemos cada uno de estos tres subsistemas con más detalle.
Subsistema de registro de errores
El subsistema de registro de errores es responsable de registrar errores en el registro, así como ofrecer funcionalidades para recuperar detalles sobre un error determinado o un subconjunto de los errores. Esta funcionalidad está disponible mediante una serie de clases:
- ErrorLog: Esta clase abstracta proporciona los métodos contractuales para leer y escribir en el registro.
- Error: Esta clase contiene propiedades que describen los detalles de un error determinado.
- ErrorLogEntry: Esta clase representa una instancia determinada
Error
para un determinadoErrorLog
. BásicamenteErrorLogEntry
agrupa unaError
instancia con laErrorLog
instancia de la que se originó.
Echemos un vistazo a estas tres clases y cómo funcionan con los módulos HTTP y los subsistemas de controlador HTTP para proporcionar una utilidad completa y centralizada de registro de excepciones.
Examinar la clase ErrorLog
Dependiendo de una estrategia o configuración de proyecto determinada, es posible que desee emplear otro almacén de respaldo para el registro de errores. Por ejemplo, en un servidor de producción, es posible que desee registrar excepciones en Microsoft SQL Server, pero en un servidor de desarrollo podría estar satisfecho simplemente almacenando los errores en un conjunto de archivos XML o en una base de datos de Microsoft Access. Para ofrecer la capacidad de usar diferentes almacenes de respaldo, el subsistema de registro de errores proporciona una clase base abstracta, ErrorLog
, que define los métodos base que todos los registradores de errores elMAH deben implementar. Estos métodos son:
- Log(Error): Registra un error en el almacén de respaldo. La
Error
clase representa información sobre una excepción no controlada; en breve analizaremos estaError
clase con más detalle. Al registrar la información de error, elLog()
método también debe asignar un identificador único al error. - GetError(id): Devuelve información sobre un error determinado en el registro.
- GetErrors(...): Devuelve un subconjunto de errores del registro. El subsistema del controlador HTTP usa este método para mostrar el registro de errores de forma paginada, en lugar de mostrar todos los errores a la vez.
ELMAH se incluye con dos ErrorLog
implementaciones:
- SqlErrorLog: Registra errores en una base de datos de Microsoft SQL Server 2000 mediante el
System.Data.SqlClient
proveedor.SqlErrorLog
Requiere SQL Server 2000 porque aprovecha algunas de sus características XML, pero se trata de un detalle de implementación que se puede cambiar. - MemoryErrorLog: Registra errores en la memoria de la aplicación (RAM). En otras palabras, se enlaza al AppDomain de forma que cada aplicación recibe su propio registro privado. No es necesario decir que este registro no sobrevive a los reinicios o la duración de la aplicación, por lo que es especialmente bueno para realizar pruebas y solucionar problemas temporales cuando se pueden producir errores en otras implementaciones.
Puede usar cualquiera de estos registradores de excepciones simplemente agregando un par de líneas de texto al archivo de la aplicación web de Web.config
ASP.NET. Si necesita almacenar detalles de error en algún lugar que no sea SQL Server o memoria de la aplicación, puede crear su propio registrador personalizado. Para implementar un registrador de errores para ELMAH, cree una clase que extienda ErrorLog
y proporcione la implementación de , GetError()
y GetErrors()
en el Log()
almacén deseado.
Tenga en cuenta que tanto el módulo HTTP como los subsistemas de controlador de ELMAH interactúan directamente con la clase especificada ErrorLog
, ya sea SqlErrorLog
, MemoryErrorLog
o su propia clase de registro personalizada. El módulo HTTP registra la información de excepción mediante la creación de una Error
instancia y el paso al ErrorLog
método del Log()
método . Los controladores HTTP leen detalles sobre uno o varios errores a través de los ErrorLog
métodos y GetErrors()
, que devuelven una instancia específica ErrorLogEntry
o un conjunto de ErrorLogEntry
GetError()
instancias.
Un vistazo a la clase de error
El Log()
método de ErrorLog
espera un parámetro de entrada de tipo Error
. Se usa una clase personalizada Error
en lugar de la Exception
clase proporcionada en .NET Framework porque la Exception
clase es más adecuada para comunicar información de excepciones en la pila de código y durante la vigencia de una aplicación. Sin embargo, Exception
los objetos no son ideales para almacenar en un registro de excepciones debido a problemas de almacenamiento, escritura y portabilidad. Sí, se podría usar la serialización binaria para almacenar una Exception
instancia, pero esto requeriría que el Exception
objeto se deserializara en un equipo con el mismo conjunto de tipos y ensamblados disponibles. Se trata de una limitación inaceptable (especialmente desde el punto de vista de la administración y las operaciones), ya que un registro y su contenido deben ser portátiles y no solo se pueden ver en un equipo con un entorno de ejecución o una configuración concretos. Además, una Exception
instancia a menudo carece de información de periferia específica de una aplicación web, como los valores de la colección ServerVariables de la solicitud web actual, algo que puede ser incalculable para el diagnóstico. Por lo tanto, en resumen, la Error
clase actúa como suplente para todos los tipos de excepción, manteniendo la información de una excepción generada en una aplicación web.
La lista completa de Error
propiedades se muestra en la tabla 1.
Propiedad | Descripción |
---|---|
Excepción | Instancia Exception representada por este error. Se trata de una propiedad en tiempo de ejecución que nunca se conserva junto con una instancia de la clase . |
ApplicationName | Nombre de la aplicación en la que se produjo este error. |
HostName | Nombre de la máquina host donde se produjo este error. Un buen valor predeterminado es Environment.MachineName . |
Tipo | Tipo, clase o categoría del error. Normalmente, este sería el nombre de tipo completo (sans the assembly qualification) de la excepción. |
Source | Origen del error, normalmente igual que la Message propiedad de un Exception objeto . |
Message | Texto breve que describe el error, normalmente igual que la Message propiedad de un Exception objeto. |
Detalle | Texto detallado del error, como el seguimiento completo de la pila. |
Usuario | El usuario inició sesión en la aplicación en el momento del error, como el devuelto por Thread.CurrentPrincipal.Identity.Name. |
Time | Hora y fecha en las que se ha producido el error. Esto siempre está en la hora local. |
StatusCode | El código de estado que se devuelve en el encabezado de respuesta como resultado del error. Por ejemplo, esto es 404 para una excepción FileNotFoundException. Desafortunadamente, este valor no siempre se puede determinar de forma confiable desde dentro de ASP.NET. En algunos casos, este StatusCode valor se puede notificar como cero. |
WebHostHtmlMessage | Mensaje HTML predeterminado que el host web (ASP.NET) habría generado en ausencia de páginas de error personalizadas. |
ServerVariables | NameValueCollection de variables de servidor web, como las contenidas en HttpRequest.ServerVariables. |
QueryString | Una NameValueCollection de variables de cadena de consulta HTTP, como las contenidas en HttpRequest.QueryString. |
Form | de NameValueCollection variables de formulario, como las contenidas en HttpRequest.Form. |
Cookies | Una NameValueCollection de las cookies enviadas por el cliente, como las contenidas en HttpRequest.Cookies. |
La WebHostHtmlMessage
propiedad necesita alguna explicación. Si la aplicación web de ASP.NET encuentra una excepción no controlada y no tiene la aplicación configurada para usar páginas de error personalizadas, verá una pantalla similar a la que se muestra en la figura 6. Se trata de una pantalla que cada desarrollador ASP.NET ha visto demasiadas veces.
Figura 6. Página De error estándar
Cuando se produce una excepción, se obtiene acceso al marcado HTML real de la pantalla correspondiente y se guarda en la WebHostHtmlMessage
propiedad de la Error
clase . Cuando se visita la página que muestra información detallada sobre una excepción determinada, si la instancia correspondiente Error
tiene un valor en su WebHostHtmlMessage
propiedad, el visitante se presenta un vínculo a una página que mostrará la pantalla de información de excepción real (como se muestra en la figura 6). Lo ordenado aquí es que no solo se registra la excepción, sino que también puede visitar la página de error original generada por ASP.NET al examinar el registro más adelante. Y todo esto mientras tiene errores personalizados habilitados.
La Error
clase también tiene métodos para serializar y deserializar su estado hacia y desde un formato XML. Consulte FromXml
y ToXml
en el código adjunto para obtener más información.
La clase ErrorLogEntry: Asociando un error con un errorLog
La clase final del subsistema de registro de errores es la ErrorLogEntry
clase , que asocia una Error
instancia a una ErrorLog
instancia de . Cuando el subsistema del controlador HTTP llama al GetError()
método para recuperar información sobre una excepción determinada, el GetError()
método recupera la información del almacén de respaldo específico y rellena esta información en una ErrorLogEntry
instancia de . La ErrorLogEntry
clase contiene tres propiedades:
- Id: Identificador único de los detalles de la excepción.
- Registro: Referencia a la
ErrorLog
instancia de que representa la memoria auxiliar. - Error: Instancia rellenada de la
Error
clase con los detalles del error específico.
Mientras que el GetError()
método devuelve una sola ErrorLogEntry
instancia, GetErrors()
devuelve una lista de ErrorLogEntry
instancias. GetErrors()
está especialmente diseñado para permitir que los errores se paginan a través de n registros a la vez.
En la figura 7 se muestra una vista actualizada de la arquitectura de ELMAH, que muestra más detalles en el subsistema de registro de errores.
Ilustración 7. Arquitectura actualizada
Subsistema del módulo HTTP
ELMAH consta de dos módulos HTTP: ErrorLogModule
y ErrorMailModule
. ErrorLogModule
es un módulo HTTP que crea un controlador de eventos para el evento de Error
la aplicación. En caso de una excepción no controlada, el módulo HTTP obtiene el registrador de errores adecuado tal como se especifica en la configuración de la aplicación y llama al Log()
método en él, pasando una Error
instancia rellenada con la información de la excepción y HttpContext para la solicitud actual. El código fuente siguiente muestra el código alemán de la ErrorLogModule
clase :
public class ErrorLogModule : IHttpModule { public virtual void Init(HttpApplication application) { application.Error += new EventHandler(OnError); } protected virtual ErrorLog ErrorLog { get { return ErrorLog.Default; } } protected virtual void OnError(object sender, EventArgs args) { HttpApplication application = (HttpApplication) sender; LogException(application.Server.GetLastError(), application.Context); } protected virtual void LogException(Exception e, HttpContext context) { try { this.ErrorLog.Log(new Error(e, context)); } catch (Exception localException) { Trace.WriteLine(localException); } } }
La ErrorLogModule
ejecución de se inicia en el Init()
método , donde indica al ASP.NET tiempo de ejecución que se debe invocar al OnError()
método siempre que se genere el Error
evento. El OnError()
método hace referencia al HttpApplication
objeto y llama al LogException()
método , pasando los detalles de la última excepción, así como la HttpContext
instancia específica de la solicitud determinada. LogException()
simplemente llama al método de la Log()
clase adecuadaErrorLog
, pasando una nueva Error
instancia. (El Error
constructor de la instancia toma una Exception
instancia y HttpContext
rellena las propiedades en consecuencia; consulte el código fuente disponible en la descarga para obtener más información).
ErrorLogModule
contiene una propiedad de solo ErrorLog
lectura y devuelve la ErrorLog
instancia devuelta por ErrorLog.Default
. Default
es una propiedad estática de tipo ErrorLog
en la ErrorLog
clase . Consulta la configuración de la aplicación web para determinar qué clase se va a usar para el registro de excepciones: SqlErrorLog
, MemoryErrorLog
o una clase de registro de excepciones personalizada.
Nota En la sección Agregar ELMAH a una aplicación web de ASP.NET examinaremos cómo configurar una aplicación web para usar un registrador de excepciones específico. Es tan sencillo como agregar un par de líneas a los
Web.config
archivos omachine.config
.
El otro módulo HTTP del subsistema del módulo HTTP es la ErrorMailModule
clase , que envía un correo electrónico a un administrador en caso de una excepción. No analizaremos esta parte de ELMAH, aunque puede examinar cómo usar este módulo en los ejemplos de código disponibles en la descarga de este artículo.
Subsistema de controlador HTTP
Recuerde que el propósito de los controladores HTTP es representar el contenido de un tipo determinado de recurso. Cuando una solicitud entra en la canalización HTTP de ASP.NET, el motor de ASP.NET examina la ruta de acceso solicitada y determina qué controlador HTTP se debe usar para controlar el recurso solicitado. En concreto, una aplicación de ASP.NET se puede configurar para tener una ruta de acceso determinada administrada por un controlador HTTP o un generador de controladores HTTP. Un generador de controladores HTTP es una clase que no es responsable directa de representar el contenido, sino que es responsable de seleccionar y devolver una instancia del controlador HTTP. Esta instancia de controlador HTTP devuelta es la que se encarga de representar el recurso solicitado.
El subsistema del controlador HTTP de ELMAH consta de una serie de clases de controlador HTTP diseñadas para generar marcado para mostrar los errores registrados, junto con una única clase de generador de controladores HTTP. La clase de generador de controladores HTTP, ErrorLogPageFactory
, examina la PathInfo
parte de la dirección URL solicitada para determinar qué controlador HTTP debe generar la salida.
Nota La
PathInfo
parte de una dirección URL es cualquier contenido adicional que siga el nombre de archivo y está disponible a través de laRequest
propiedad PathInfo del objeto. Por ejemplo, en la dirección URLhttp://www.example.com/someDir/somePage.aspx/somePath
, somePath es laPathInfo
parte de la dirección URL. Para obtener más información sobre la terminología usada para las distintas partes de una dirección URL y las propiedades de objeto correspondientesRequest
, consulte la entrada de blog de Rick StrahlMaking Sense of ASP.NET Paths.
El siguiente fragmento de código muestra el código más interesante de la ErrorLogPageFactory
clase de generador de controladores HTTP.
public class ErrorLogPageFactory : IHttpHandlerFactory { public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { string resource = context.Request.PathInfo.Length == 0 ? string.Empty : context.Request.PathInfo.Substring(1); switch (resource.ToLower(CultureInfo.InvariantCulture)) { case "detail" : return new ErrorDetailPage(); case "html" : return new ErrorHtmlPage(); case "rss" : return new ErrorRssHandler(); default : return new ErrorLogPage(); } } }
Como puede ver, el método de la ErrorLogPageFactory
clase devuelve una instancia de GetHandler()
controlador HTTP basada en la PathInfo
de la solicitud. PathInfo
Si es rss
, se devuelve una instancia del ErrorRssHandler
controlador HTTP, que representa el registro como una fuente RSS. PathInfo
Si es detail
, se devuelve una ErrorDetailPage
instancia del controlador HTTP, que muestra información sobre una excepción determinada.
En la configuración de ASP.NET aplicación web, debe especificar una ruta de acceso que se asigne al ErrorLogPageFactory
generador de controladores HTTP, como ErrorLog.aspx
. Para ver una fuente RSS del registro de excepciones, puede visitar: http://www.example.com/ErrorLog.aspx/rss
.
Las distintas clases de controlador HTTP de ELMAH,ErrorDetailPage
, ErrorHtmlPage
, ErrorRssHandler
ErrorLogPage
, etc., representan un marcado diferente. El ErrorRssHandler
controlador HTTP, por ejemplo, recorre en bucle los 15 errores más recientes y emite el marcado XML adecuado para mostrar esta información en un formato RSS. Todos los demás controladores HTTP se derivan, directa o indirectamente, de la System.Web.UI.Page
clase (que es la clase de la que se derivan todas las clases de código subyacente de ASP.NET). Estos controladores HTTP relacionados con páginas reemplazan los métodos Render() y OnLoad() de la Page
clase para crear una interfaz HTML que muestre una lista paginable de las excepciones registradas. Consulte las figuras 1, 2 y 3 para ver las capturas de pantalla de estas páginas.
Nota Mientras la
Error
clase guarda lasServerVariables
colecciones ,QueryString
,Form
yCookie
, solo se muestra laServerVariables
colección en los detalles de una excepción. Esto se debe a que losQueryString
parámetros y las cookies son visibles a través deQUERY_STRING
losServerVariable
parámetros yHTTP_COOKIE
, respectivamente. LaForm
colección se omite porque esto podría incluir potencialmente decenas de kilobytes de información de estado de vista que normalmente sirve poco para el diagnóstico. Por supuesto, puede modificar fácilmente los detalles del controlador HTTP para incluir esta información, si así lo elige.
Ahora que hemos examinado los tres subsistemas de ELMAH, echemos un vistazo a cómo agregar ELMAH a una aplicación web de ASP.NET existente. Preste especial atención a lo fácil que es agregar ELMAH a cualquier sitio, una ventaja de la componenteización que ofrecen los controladores HTTP y los módulos.
Adición de ELMAH a una aplicación web de ASP.NET
Agregar ELMAH a una aplicación web de ASP.NET es bastante sencillo y consta de dos pasos:
- Agregar el ensamblado ELMAH a la aplicación web.
- Configuración de la aplicación web para usar los módulos HTTP y los controladores HTTP de ELMAH.
ELMAH se puede aplicar a una aplicación web determinada en un servidor web copiando el ensamblado en el directorio de /bin
la aplicación web y configurando los valores de ELMAH a través del Web.config
archivo. Además, puede configurar ELMAH para que se aplique a todas las aplicaciones web de un servidor web agregando el ensamblado a la caché global de ensamblados (GAC) del servidor web y agregando las mismas opciones de configuración en machine.config
lugar de Web.config
.
En el Web.config
archivo (o machine.config
), deberá agregar la siguiente configuración:
- Elemento <sectionGroup> del <elemento configSections> que define un nuevo nombre de sección,
<gotdotnet.elmah>
, con una sección dentro de llamada<errorLog>
, que tiene información sobre cómo registrar información de excepciones. - Una
<gotdotnet.elmah>
sección, con una sección interna denominada<errorLog>
, que contiene una referencia de tipo al registrador de excepciones que desea que use ELMAH, junto con cualquier configuración específica de ese registrador de excepciones. - Una entrada de la
<httpHandlers>
sección que indica la ruta de acceso que, cuando se visita a través de un explorador, representará varias vistas en el registro de errores. - Entrada de la
<httpModules>
sección que agregaErrorLogModule
al ASP.NET canalización HTTP.
El siguiente fragmento de código del archivo incluido en la Web.config
descarga de este artículo muestra cómo se pueden especificar estas cuatro opciones:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <!-- Allows for a new section group to the Web.config --> <sectionGroup name="gotdotnet.elmah"> <!-- Indicates that inside the section group there will be an errorLog section --> <section name="errorLog" type="System.Configuration.SingleTagSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </sectionGroup> </configSections> <!-- This section group contains the type of the exception logger to use (SqlErrorLog, MemoryErrorLog, or a custom logger). It also contain properties pertinent to the exception logger (connectionString, for the SqlErrorLog). --> <gotdotnet.elmah> <errorLog type="GotDotNet.Elmah.SqlErrorLog, GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, PublicKeyToken=978d5e1bd64b33e5" connectionString="...connection string..." /> </gotdotnet.elmah> <system.web> <!-- Register that a request to aspnetham/errorlog.aspx should be serviced by the ErrorLogPageFactory HTTP Handler factory --> <httpHandlers> <add verb="POST,GET,HEAD" path="elmah/default.aspx" type="GotDotNet.Elmah.ErrorLogPageFactory, Skybow.Samples.AspNetHam, Version=1.0.5527.0, Culture=neutral, PublicKeyToken=978d5e1bd64b33e5" /> </httpHandlers> <!-- Adds the ErrorLogModule HTTP Module to the HTTP pipeline. --> <httpModules> <add name="ErrorLog" type="GotDotNet.Elmah.ErrorLogModule, GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, PublicKeyToken=978d5e1bd64b33e5" /> </httpModules> ... </system.web> </configuration>
El <sectionGroup>
elemento del <configSections>
elemento escribe que habrá un grupo de secciones adicional en el archivo de configuración denominado <gotdotnet.elmah>
. Además, indica que dentro de esta sección personalizada habrá una <errorLog>
sección. Dentro del elemento real <gotdotnet.elmah>
hay un <errorLog>
elemento que especifica qué implementación del registro de errores se debe usar. Recuerde que ELMAH se distribuye con dos implementaciones integradas, es decir SqlErrorLog
, y MemoryErrorLog
. Puede especificar cuál de estos dos usar, o puede especificar para usar un registrador de excepciones personalizado que puede haber creado en el <errorLog>
elemento . El <errorLog>
elemento también contiene la configuración específica de una implementación del registro de errores. Por ejemplo, cuando se usa el <errorLog>
elemento para indicar que SqlErrorLog
se debe usar , se debe incluir una connectionString
propiedad que le indique cómo conectarse a la base de datos. El script SQL para crear la tabla adecuada y los procedimientos almacenados asociados se incluye en la descarga.
Nota Si desea que un administrador se envíe por correo electrónico en caso de una excepción no controlada, deberá agregar otro
<section>
elemento en<sectionGroup>
que defina un nuevo elemento denominado<errorMail>
. Además, en el elemento real<gotdotnet.elmah>
, tendría que agregar un<errorMail>
elemento . Consulte elWeb.config
archivo en la descarga para obtener un ejemplo de esta sintaxis.
La <httpHandlers>
sección especifica que ErrorLogPageFactory
se debe usar (un generador de controladores HTTP) para recuperar el controlador HTTP que representa el contenido para ver el registro de errores. El valor del path
atributo indica la dirección URL relativa a la raíz virtual de la aplicación para obtenerla en la presentación del registro de errores. Puede cambiar esto a lo que quiera, pero asegúrese de que es una dirección URL con una extensión controlada por el motor de ASP.NET. Es decir, si cambia la ruta de acceso a algo parecido errors.log
a , deberá configurar IIS para asignar solicitudes a errors.log
la extensión ISAPI de ASP.NET (aspnet_isapi.dll
). Si desea asegurarse de que solo los administradores puedan ver el registro, use ASP. Funcionalidades de autorización de direcciones URL de NET para restringir el acceso a un usuario específico o a un conjunto de usuarios o roles. Por otro lado, si desea deshabilitar completamente el acceso basado en Web al registro, simplemente no configure la <httpHandlers>
sección.
En la sección se <httpModules>
agrega el ErrorLogModule
módulo HTTP a la canalización HTTP de ASP.NET. Asegúrese de incluir esta <httpModules>
configuración; de lo contrario, ELMAH no escuchará el Error
evento y, por lo tanto, no registrará ninguna excepción no controlada.
Como puede ver, agregar ELMAH a una aplicación web de ASP.NET existente es bastante sencillo. La implementación y reutilización simples de ELMAH se debe al hecho de que está componentedo mediante módulos y controladores HTTP.
Conclusión
Esperamos que este artículo haya podido echar algo de luz sobre cómo los controladores y módulos HTTP son excelentes herramientas para la funcionalidad de componentes ortogonal a una aplicación web de ASP.NET. Las tareas comunes, como el registro centralizado, el registro en toda la aplicación o las solicitudes de supervisión en toda la aplicación, se pueden componentes a través de controladores y módulos. Al encapsular esta funcionalidad en un conjunto de componentes, obtendrá ventajas de reutilización, mantenimiento e implementación sin necesidad de ninguna migración, integración o recompilación de código y aplicaciones existentes.
Para demostrar la componenteización posible con módulos y controladores HTTP, hemos examinado ELMAH, una aplicación de registro y correo centralizados de errores. ELMAH usa un módulo HTTP para escuchar los eventos de toda Error
la aplicación, que se desencadenan como resultado de una propagación de excepciones no controladas. Después de aprender de una excepción no controlada, ELMAH registra la excepción en una base de datos de SQL Server, en la memoria o, quizás, en algún otro almacén de respaldo. ELMAH también puede enviar por correo electrónico el contenido de la excepción a uno o varios destinatarios, como desarrolladores y personal de operaciones.
Además de un módulo HTTP, ELMAH contiene un conjunto de controladores HTTP y un generador de controladores HTTP para facilitar la visualización del registro de errores a través de un medio basado en Web. Esto incluye no solo una página web tradicional, sino también una fuente RSS. ELMAH mantiene un componente discreto al tener la funcionalidad de visualización encapsulada en un controlador HTTP, en lugar de requerir que la aplicación web incluya una página web de ASP.NET que muestre dicha información. Mediante el uso de controladores HTTP, la implementación de ELMAH es un proceso sencillo y no requiere una recompilación de la aplicación web o la carga de una página web de ASP.NET en el servidor de producción.
ELMAH es solo un ejemplo de la potencia de la componenteización que proporcionan los controladores HTTP y los módulos. Quizás haya otros procesos en toda la aplicación que haya implementado que puedan beneficiarse de la creación de componentes con controladores y módulos.
¡Feliz programación!
Agradecimientos
Antes de enviar este artículo al editor de MSDN, tuvimos una serie de voluntarios que ayudan a revisar el artículo y proporcionar comentarios sobre el contenido, la gramática y la dirección del artículo. Entre los colaboradores principales del proceso de revisión de este artículo se incluyen Milán Negovan, Carl Lambrecht, Dominique Kuster, Roman Mathis, Raffael Zaghet, Muhammad Abubakar y Patrick Schuler.
Referencias
- Control de errores personalizado enriquecido con ASP.NET
- Creación de páginas personalizadas de informes de errores en ASP.NET mediante Visual C# .NET
- tiempo de ejecución http de ASP.NET
- Módulos HTTP
- Modelo de conexión de ASP .NET y escritura de objetos de respuesta/controlador HTTP personalizados
Libros relacionados
- Inicio de los controles web de datos de ASP.NET
- ASP. NET: sugerencias, tutoriales y código
- ASP.NET desatado
- Programación de Microsoft ASP.NET
Atif Aziz tiene casi 13 años de experiencia en desarrollo de soluciones en la plataforma Microsoft. Es consultor principal de Skybow AG, donde su principal enfoque es ayudar a los clientes a comprender y crear soluciones en la plataforma de desarrollo de .NET. Atif contribuye regularmente a la comunidad de desarrolladores de Microsoft dando charlas en conferencias de Microsoft y que no son de Microsoft y escribiendo artículos para publicaciones técnicas. Es un orador ineta y presidente del grupo de usuarios de .NET suizo más grande (dotMUGS). Puede llegar a o atif.aziz@skybow.com a través de su sitio web en http://www.raboof.com.
Scott Mitchell, autor de cinco libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Puede acceder a él en mitchell@4guysfromrolla.com o a través de su blog, que se puede encontrar en http://ScottOnWriting.NET.