Verwenden von HTTP-Modulen und -Handlern zum Erstellen von ASP.NET-Plug-In-Komponenten
TOC
Inhaltsverzeichnis reduzieren
Inhaltsverzeichnis erweitern

Verwenden von HTTP-Modulen und -Handlern zum Erstellen von ASP.NET-Plug-In-Komponenten

Veröffentlicht: 17. Jan 2005
Von Scott Mitchell und Atif Aziz

In diesem Artikel erläutern Scott Mitchell und Atif Aziz, wie Sie ASP.NET-Anwendungen mithilfe von HTTP-Modulen und -Handlern um eine Fehlerprotokollierung erweitern. Dieser Artikel enthält auch Links zu englischsprachigen Seiten. (22 gedruckte Seiten)

Downloaden Sie die Beispieldatei "MSDNElmah.msi" (in Englisch).

* * *

Auf dieser Seite

Einführung Einführung
ELMAH: Fehlerprotokollierungsmodule und -handler ELMAH: Fehlerprotokollierungsmodule und -handler
Vorhandene Lösungen für eine zentrale Fehlerprotokollierung Vorhandene Lösungen für eine zentrale Fehlerprotokollierung
Ein kurzer Überblick über HTTP-Handler und -Module Ein kurzer Überblick über HTTP-Handler und -Module
Untersuchen der ELMAH-Architektur Untersuchen der ELMAH-Architektur
Hinzufügen von ELMAH zu einer ASP.NET-Webanwendung Hinzufügen von ELMAH zu einer ASP.NET-Webanwendung
Schlussbemerkung Schlussbemerkung
Referenzen Referenzen
Verwandte Literatur Verwandte Literatur

Einführung

Haben Sie jemals für eine ASP.NET-Anwendung verschiedene Funktionen oder Leistungsmerkmale entworfen, die auch in anderen ASP.NET-Anwendungen ohne weiteres verfügbar sein sollten? ASP.NET bietet verschiedene Tools, mit denen Sie verschiedene Arten von Funktionen als Komponenten bereitstellen können. Die zwei am häufigsten eingesetzten Tools für die Wiederverwendung von Funktionen in ASP.NET sind:

  • Benutzersteuerelemente und benutzerdefinierte, kompilierte Serversteuerelemente für Benutzeroberflächenelemente und -funktionen.

  • .NET-Klassenbibliotheken für Geschäftslogik- und Datenzugriffscode.

Zwei ASP.NET-Wiederverwendungstools, die oftmals nicht beachtet werden, sind HTTP-Module und -Handler.

Wenn Sie noch nicht mit HTTP-Handlern und -Modulen vertraut sind, so spielt dies keine Rolle. Weiter unten in diesem Artikel werden diese Themen noch genauer erläutert. Vorläufig müssen Sie lediglich wissen, dass es sich bei HTTP-Modulen um Klassen handelt, die so konfiguriert werden können, dass sie auf Ereignisse reagieren, die während der Anforderung einer ASP.NET-Ressource ausgelöst werden. Ein HTTP-Handler ist eine Klasse, die für die Darstellung einer bestimmten Ressource oder eines bestimmten Ressourcentyps zuständig ist. Tatsächlich erzeugen Sie im Grunde genommen jedes Mal einen HTTP-Handler, wenn Sie eine ASP.NET-Webseite zu einem Projekt hinzufügen. Denn der während der Laufzeit dynamisch kompilierte HTML-Teil einer ASP.NET-Webseite wird direkt oder indirekt von System.Web.UI.Page abgeleitet, und hierbei handelt es sich um eine HTTP-Handlerimplementierung. Dies gilt unabhängig davon, ob Sie mit Inline- oder CodeBehind-Anweisungen arbeiten.

Wie Sie wissen, besteht eine ASP.NET-Anwendung in der Regel aus einer Reihe von Webseiten, die aufgerufen werden, wenn sie vom Browser eines Endbenutzers angefordert werden. Der Code, den ASP.NET-Entwickler schreiben, bezieht sich meist auf eine Anforderung einer bestimmten Webseite. Dies gilt z. B. für Code in einer CodeBehind-Klasse einer bestimmten Seite, mit dem Datenbankergebnisse angezeigt werden, die auf einer Suchabfrage beruhen. In bestimmten Fällen müssen Entwickler jedoch Code schreiben, der nicht nur für eine einzelne Webseite, sondern für alle Seiten einer Anwendung gilt. Beispielsweise soll erfasst werden, in welcher Reihenfolge die einzelnen Benutzer die Seiten der Website aufrufen. Dazu müssen bei jeder Seite der Zeitpunkt der Anforderung und Informationen über den Benutzer protokolliert werden.

Eine solche Protokollfunktion könnte mit Code bereitgestellt werden, mit dessen Hilfe die betreffenden Daten für jede Webseite der Website in einer Datenbank im Page_Load-Ereignishandler aufgezeichnet werden. Dieses Verfahren ist jedoch kaum wartbar oder wiederverwendbar. Sobald eine neue ASP.NET-Seite zur Website hinzugefügt wird, müsste sichergestellt werden, dass sie den entsprechenden Protokollierungscode enthält. Wenn eine andere Website die gleiche Funktion erhalten soll, muss der entsprechende Code zu jeder Seite der Website hinzugefügt werden. Im Idealfall sollte die Protokollfunktion von der Funktion der einzelnen Seiten sowohl logisch als auch physisch getrennt sein, und die Integration der Funktion in eine andere Website sollte so einfach sein wie das Ablegen einer Assembly im Verzeichnis /bin der Website.

Eine solche Wiederverwendung und Wartbarkeit ist bei HTTP-Modulen und -Handlern ohne weiteres möglich. In diesem Artikel wird eine Reihe von HTTP-Modulen und -Handlern vorgestellt, die so konzipiert wurden, dass die Fehlerprotokollierung problemlos gewartet und wiederverwendet werden kann. Ziel dieses Artikels ist es, zu zeigen, wie sich HTTP-Handler und -Module zur Bildung von Komponenten auf übergeordneter Ebene einsetzen lassen. Dabei werden vollständige Gruppen von Funktionen entwickelt, gebündelt und unabhängig von Webanwendungen als Einheit weitergegeben. Dies wird überwiegend anhand einer Anwendung erläutert, die von der Wiederverwendung und Komponentenbildung mittels HTTP-Handlern und -Modulen profitiert.

ELMAH: Fehlerprotokollierungsmodule und -handler

Die Fehlerprotokollierungsmodule und -handler (Error Logging Modules And Handlers, ELMAH), die in diesem Artikel vorgestellt werden, wurden vom Koautor Atif Aziz (http://www.raboof.com/ (in Englisch)) geschrieben und zeigen, wie sich eine ASP.NET-Webanwendung auf einfache Weise um Fehlerprotokollierungsfunktionen erweitern lässt. ELMAH ist ein Beispiel dafür, wie mithilfe von HTTP-Modulen und -Handlern Code, der in einer Webanwendung an verschiedensten Stellen eingesetzt werden kann (beispielsweise zur anwendungsweiten Protokollierung), in Komponenten umgewandelt werden kann. ELMAH ist eine echte Plug-In-Lösung, die dynamisch zu einer ASP.NET-Webanwendung hinzugefügt werden kann, ohne dass diese neu kompiliert oder bereitgestellt werden muss.

Eine Webanwendung kann noch so gut geschrieben und getestet sein, gelegentlich wird doch einiges schief gehen. Dabei muss noch nicht einmal Ihr Code fehlerhaft sein, es ist auch möglich, dass der E-Mail-Server nicht antwortet oder ein kryptischer Fehler durch beschädigte Daten hervorgerufen wird. Sobald eine Ausnahme auftritt, müssen unabhängig von deren Grund, insbesondere bei einer aktiven Website, Einzelheiten zu der Ausnahme erfasst werden, damit das Problem diagnostiziert werden kann. ELMAH enthält einen Mechanismus für die zentrale Fehlerprotokollierung und -benachrichtigung. Sobald in einer ASP.NET-Anwendung eine Ausnahme auftritt, die nicht abgefangen wird, erhält ELMAH eine Benachrichtigung, und die Ausnahme wird entsprechend den Anweisungen in der Datei Web.config behandelt. Dabei werden etwa Einzelheiten über die Ausnahme in einer Datenbank aufgezeichnet und/oder eine E-Mail an einen Administrator gesendet.

ELMAH ist nicht dafür vorgesehen, nicht behandelte Ausnahmen zu beseitigen, sondern zeichnet lediglich die Details zu nicht behandelten Ausnahmen auf. Sobald ELMAH zu einer ASP.NET-Webanwendung hinzugefügt wurde, werden alle in dieser Anwendung ausgelösten, nicht behandelten Ausnahmen protokolliert. Endbenutzer bemerken nicht, wenn eine nicht behandelte Ausnahme auftritt. Sie sehen die Seite "Serverfehler" bzw. werden zu einer Seite mit einer benutzerfreundlicheren Meldung umgeleitet, wenn Sie für HTTP-500-Fehler eine benutzerdefinierte Vorgehensweise konfiguriert haben. Im Hintergrund jedoch wird von ELMAH das Auftreten einer nicht behandelten Ausnahme erkannt, und die Details werden protokolliert.

ELMAH entdeckt nicht behandelte Ausnahmen mithilfe des Ereignisses Error des Objekts HttpApplication. Das Ereignis Error wird ausgelöst, sobald während der Verarbeitung einer Anforderung von einer .NET-Klassenbibliothek oder einer ASP.NET-Webseite eine nicht abgefangene Ausnahme auftritt. Bedenken Sie, dass in vielen ASP.NET-Anwendungen benutzerdefinierte Fehlerseiten und Fehlerbehandlung falsch implementiert sind, da häufig die Methode Server.ClearError() aufgerufen wird. Wird der Fehler gelöscht, wird die Auslösung des Ereignisses Error (sowie die Meldung an den Client) verhindert, so dass ELMAH nie die Möglichkeit erhält, die Ausnahme zu protokollieren. Das bedeutet, wenn ClearError() auf einer benutzerdefinierten Fehlerseite verwendet wird, sehen zwar die Benutzer, dass ein Problem aufgetreten ist, Sie jedoch nicht.

Hinweis   Weitere Informationen über das Erstellen benutzerdefinierter Fehlerseiten finden Sie im Artikel Rich Custom Error Handling with ASP.NET (in Englisch) von Eli Robillard.

Hinweis   Wenn in einem ASP.NET-Webdienst eine nicht behandelte Ausnahme auftritt, wird das Ereignis Error nicht an HTTP-Module und damit auch nicht an ELMAH weitergeleitet. Es wird vielmehr von der ASP.NET-Laufzeit abgefangen, und an den Client wird ein SOAP-Fehler zurückgegeben. Damit ein Fehler in einem Webdienst protokolliert wird, müssten Sie eine SOAP-Erweiterung (in Englisch) erstellen, die SOAP-Fehler empfangen kann.

ELMAH zeichnet nicht nur die Details nicht behandelter Ausnahmen auf, sondern verfügt auch über eine Reihe von HTTP-Handlern zum Anzeigen des Fehlerprotokolls. Es gibt eine Webschnittstelle zum Protokoll, das eine Liste aller nicht behandelten Fehler sowie Details zu einem bestimmten Fehler enthalten kann (siehe Abbildungen 1 und 2).

Anzeigen des Fehlerprotokolls
Abbildung 1: Anzeigen des Fehlerprotokolls

Anzeigen eines Fehlers
Abbildung 2: Anzeigen eines Fehlers

Dieses Fehlerprotokoll kann auch als RSS dargestellt werden, so dass Administratoren über ihr bevorzugtes RSS-Tool Benachrichtigungen erhalten, wenn ein Fehler aufgetreten ist (siehe Abbildung 3).

RSS-Fehlerfeed
Abbildung 3: RSS-Fehlerfeed

Hinweis   RSS steht für Really Simple Syndication, einen Standard im XML-Format, der üblicherweise zur Veröffentlichung von Nachrichten und anderen Arten veränderlicher Inhalte verwendet wird. Wenn Sie mehr über RSS, die Veröffentlichung von Inhalten mithilfe von RSS sowie über die Erstellung eines webbasierten RSS-Lesetools erfahren möchten, lesen Sie den Artikel Creating an Online News Aggregator with ASP.NET (in Englisch).

Der Kürze halber werden in diesem Artikel nicht alle Funktionen von ELMAH, sondern nur die wichtigsten Komponenten erläutert. Der vollständige Code steht mit diesem Artikel zum Download zur Verfügung, und Sie sind aufgefordert, ihn gründlich zu studieren, damit Sie die Details der Implementierung erfassen. Es gibt auch einen GotDotNet-Workspace-Setup für ELMAH unter http://workspaces.gotdotnet.com/elmah (in Englisch). Dort können Sie diskutieren, über Probleme berichten und sich über die neuesten Änderungen informieren.

Vorhandene Lösungen für eine zentrale Fehlerprotokollierung

ASP.NET verfügt zwar über keine integrierten Fehlerprotokollierungs- und Anzeigefähigkeiten, von der Patterns & Practices Group (in Englisch) von Microsoft wurde jedoch ein Opensource-Fehlerprotokollierer erstellt, der Exception Management Application Block (in Englisch) (EMAB). Der EMAB wurde sowohl für Desktop- als auch webbasierte .NET-Anwendungen entwickelt. Es drängt sich jedoch der Eindruck auf, dass der EMAB hauptsächlich für Desktopanwendungen konzipiert wurde und Webanwendungen erst nachträglich berücksichtigt wurden, denn der EMAB zeigt Details über Ausnahmen standardmäßig im Windows-Ereignisprotokoll an. Bei Desktopanwendungen eignet sich das Ereignisprotokoll durchaus als Sicherungsspeicher für knappe Informationen über Ausnahmen. Bei den meisten Webanwendungen allerdings - insbesondere bei solchen, die auf einem gemeinsam genutzten Server eines Webhostunternehmens verwaltet werden - wird die Verwendung des Ereignisprotokolls vermieden, da spezielle Berechtigungen eingerichtet werden müssen, damit die ASP.NET-Anwendung in das Ereignisprotokoll schreiben kann. Der EMAB ist natürlich so flexibel, dass Sie einen benutzerdefinierten Publisher erstellen können, der Informationen in einer Datenbank aufzeichnet. Für Sie als Entwickler bedeutet dies jedoch zusätzliche Arbeit.

Hinweis   ELMAH wird mit einem Datenbankprotokollierungsmodul für Microsoft SQL Server 2000 geliefert, das weiter unten behandelt wird. Mit ELMAH können Sie auch benutzerdefinierte Ausnahmeprotokollierer erstellen, beispielsweise einen Protokollierer, der Details über Ausnahmen in einer XML-Datei im Dateisystem des Webservers aufzeichnet. Wenn Sie für den EMAB bereits einen benutzerdefinierten Publisher geschrieben haben, den Sie verwenden möchten, könnten Sie ELMAH in der Tat erweitern, so dass der EMAB verwendet wird.

Wartbarkeit und Wiederverwendbarkeit der Webanwendung sind in starkem Maße davon abhängig, wie mit dem EMAB Ausnahmeinformationen aufgezeichnet werden. In einem sehr schlichten Ansatz zum Erfassen von Ausnahmeinformationen etwa würde jeder Codeblock einer ASP.NET-Webseite in einen try ...catch-Block eingefügt, wobei der EMAB im Abschnitt catch aufgerufen wird.

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
  }
}

Dieser Ansatz ist verwegen, da die Ausnahmeprotokollierung eng an jede einzelne ASP.NET-Webseite gebunden ist, so dass sie nicht mehr wartbar oder wiederverwendbar ist. Besser wäre es, den EMAB im Ereignis Application_Error in Global.asax (in Englisch) zu verwenden. Dieser Ansatz ermöglicht eine weniger eng gekoppelte, wartbare und wiederverwendbare Architektur, da der Code für die Ausnahmeveröffentlichung in keiner ASP.NET-Webseite enthalten ist, sondern sich stattdessen an einem zentralen Ort befindet. Der Nachteil dieses Ansatzes besteht darin, dass er nicht für ein Plug-In-Verfahren geeignet ist. Um diese Fehlerprotokollierfunktion zu einer anderen ASP.NET-Webanwendung hinzuzufügen, müssten Sie Änderungen in Global.asax der betreffenden Anwendung vornehmen, damit die Anwendung erneut kompiliert und weitergegeben werden kann.

In diesem Artikel geht es nicht darum, einen Ersatz für den EMAB einzuführen. Vielmehr soll die durch HTTP-Handler und -Module ermöglichte Komponentenbildung hervorgehoben werden. ELMAH ist ein Beispiel dafür, wie sich eine häufig stellende Aufgabe wie die zentrale Fehlerprotokollierung zu einer Komponente umbilden lässt, welche die Wartbarkeit vereinfacht und ein hohes Maß an Wiederverwendbarkeit bietet. Der Zweck von ELMAH besteht darin, eine Anleitung zur Erstellung von Komponenten für anwendbare Funktionen zu geben.

Ein kurzer Überblick über HTTP-Handler und -Module

Bevor die Besonderheiten der ELMAH-Architektur und -Implementierung untersucht werden, sollen HTTP-Handler und -Module nochmals kurz dargestellt werden. Wenn ein IIS-Webserver eine Anforderung empfängt, untersucht IIS die Erweiterung der Anforderung, damit die weitere Vorgehensweise festgelegt werden kann. Bei statischen Inhalten wie HTML-Seiten, CSS-Dateien, Bildern, JavaScript-Dateien usw. wird die Anforderung vonm IIS selbst verarbeitet. Bei dynamischen Inhalten wie ASP-Seiten, ASP.NET-Webseiten und ASP.NET-Webdiensten delegiert IIS die Anforderung an eine festgelegte ISAPI-Erweiterung. Eine ISAPI-Erweiterung ist nicht verwalteter Code, der angibt, wie Anforderungen eines bestimmten Typs dargestellt werden sollen. Die ISAPI-Erweiterung asp.dll ist z. B. für die Darstellung von Anforderungen für klassische ASP-Webseiten zuständig. Die ISAPI-Erweiterung aspnet_isapi.dll wird aufgerufen, wenn eine Anforderung einer ASP.NET-Ressource empfangen wird.

Neben ISAPI-Erweiterungen lässt IIS auch ISAPI-Filter zu. Ein ISAPI-Filter ist nicht verwalteter Code, der als Antwort auf Ereignisse ausgeführt wird, die von IIS ausgelöst wurden. Während des Lebenszyklus einer Anforderung durchläuft IIS eine Reihe von Schritten, durch die entsprechende Ereignisse ausgelöst werden. Ein Ereignis wird z. B. ausgelöst, wenn die Anforderung erstmalig vom IIS empfangen wird, wenn die Anforderung authentifiziert werden soll, wenn der dargestellte Inhalt wieder an den Client gesendet werden soll usw. ISAPI-Filter werden in der Regel für Funktionen wie das Umschreiben von URLs, Komprimierung, spezielle Authentifizierung und Autorisierung, spezielle Protokollierung usw. verwendet.

Wenn die Anforderung einer ASP.NET-Ressource IIS erreicht, wird sie an das ASP.NET-Modul weitergeleitet. Von diesem Modul wird der Inhalt für die angeforderte Ressource dargestellt. Das ASP.NET-Modul reagiert auf sehr ähnliche Weise wie IIS, indem es eine Reihe von Ereignissen auslöst, während die Anforderung durch die ASP.NET-HTTP-Pipeline geleitet wird. Außerdem delegiert das ASP.NET-Modul die Darstellung der angeforderten Ressource an eine bestimmte Klasse. Während IIS nicht verwaltete ISAPI-Erweiterungen und -Filter verwendet, werden von ASP.NET verwaltete Klassen verwendet, die als HTTP-Handler und -Module bezeichnet werden.

Ein HTTP-Handler ist eine Klasse, die für die Darstellung eines bestimmten Ressourcentyps zuständig ist. Die CodeBehind-Klasse für eine ASP.NET-Webseite ist z. B. ein HTTP-Handler, dem bekannt ist, wie das Markup für die betreffende Webseite darzustellen ist. Es ist hilfreich, sich Handler als spezialisierte Darstellungsmodule vorzustellen, die für die Erstellung des Markups für einen bestimmten Ressourcentyp zuständig sind.

Hinweis   Ausführlichere Erläuterungen zu HTTP-Handlern und Beispiele für praktische Anwendungen von Handlern finden Sie im Artikel Serving Dynamic Content with HTTP Handlers (in Englisch).

Ein HTTP-Modul ist eine Klasse, die die verschiedenen Ereignisse nutzen kann, die ausgelöst werden, während die Anforderung auf dem Server die verschiedenen Stadien ihres Lebenszyklus durchläuft. Eines dieser ASP.NET-Anwendungsereignisse ist das Ereignis Error, das beim Auftreten einer nicht behandelten Ausnahme ausgelöst wird. Ein solches Ereignis ist für ELMAH relevant.

Hinweis   Weitere Informationen über HTTP-Module sowie über deren Verwendung zum Umschreiben von URLs finden Sie unter URL Rewriting in ASP.NET (in Englisch).

Abbildung 4 enthält eine grafische Darstellung der ASP.NET-HTTP-Pipeline. Beachten Sie, dass der Prozess mit dem Eintreffen einer Anforderung bei IIS beginnt. Angenommen, die angeforderte Ressource ist so konfiguriert, dass sie von der ASP.NET-ISAPI-Erweiterung verarbeitet wird, so sendet IIS die Anforderung an die nicht verwaltete ISAPI-Erweiterung aspnet_isapi.dll. Diese ISAPI-Erweiterung übergibt die Anforderung an das verwaltete ASP.NET-Modul. Während des Lebenszyklus der Anforderung werden unter Umständen mehrere HTTP-Module ausgeführt. Dies ist davon abhängig, welche Module registriert wurden und welche Ereignisse von ihnen abonniert wurden. Das ASP.NET-Modul bestimmt schließlich den HTTP-Handler, der für die Darstellung des Inhalts zuständig ist, ruft den Handler auf und gibt den erzeugten Inhalt an IIS zurück, von wo er wiederum an den anfordernden Client zurückgegeben wird.

Datenfluss durch den Fehlerprotokollierer
Abbildung 4: Datenfluss durch den Fehlerprotokollierer

ELMAH ermöglicht die zentrale Fehlerprotokollierung durch ein HTTP-Modul, das über einen Ereignishandler für das Ereignis Error verfügt. Wenn das Ereignis ausgelöst wird, protokolliert ELMAH die Ausnahmedetails. ELMAH verwendet außerdem HTTP-Handler, die hauptsächlich für die Erzeugung von HTML- und RSS-Markup zur Darstellung der Informationen des Fehlerprotokolls zuständig sind.

Wenn eine vorhandene Webanwendung für die Verwendung verschiedener Handler oder Module konfiguriert werden soll, wird die Modul- oder Handlerassembly in das Verzeichnis /bin der Webanwendung kopiert, und in die Datei Web.config werden einige Konfigurationszeilen eingefügt.

Zur Konfiguration der HTTP-Module für eine Webanwendung fügen Sie einen <httpModules>-Abschnitt in die Datei Web.config ein, mit dem der Typ des hinzuzufügenden Moduls angegeben wird:

<httpModules>
   <add name="ModuleName" type="ModuleType" />
</httpModules>

ModuleType ist eine Zeichenfolge, die den Typ des Moduls angibt. Dabei handelt es sich um den vollqualifizierten Klassennamen (Namespace.ClassName) gefolgt vom Assemblynamen. Das Attribut type kann zusätzlich Versions- und Kulturinformationen enthalten sowie einen Token für einen öffentlichen Schlüssel, der von Assemblies mit Strong Names verlangt wird. Das folgende Codefragment zeigt die eigentliche <httpModules>-Einstellung, die Sie verwenden müssen, wenn Sie das ELMAH-Fehlerprotokollierungsmodul in die ASP.NET-Anwendung einfügen möchten:

<httpModules>
  <add name="ErrorLog" type="GotDotNet.Elmah.ErrorLogModule, 
    GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, 
    PublicKeyToken=978d5e1bd64b33e5" />
</httpModules>

In einer Webanwendung kann ein HTTP-Handler verwendet werden, wenn der Abschnitt <httpHandlers> zur Datei Web.config hinzugefügt wird. Da ein HTTP-Handler Inhalte für einen bestimmten Ressourcentyp darstellt, enthält das Element <httpHandlers> neben dem Attribut type auch das Attribut path, das angibt, welche Dateipfade oder Erweiterungen diesem HTTP-Handler zugeordnet werden sollen. Außerdem können Sie mit dem Attribut verb die Verwendung des Handlers auf bestimmte Arten von HTTP-Anforderungen einschränken, beispielsweise auf GET- oder POST-Anforderungen. Mit dem folgenden Beispielcode wird ein HTTP-Handler erstellt, der bei allen Anforderungen von Dateien mit der Erweiterung .ashx aufgerufen wird.

<httpHandlers>
   <add verb="*" path="*.ashx" type="HandlerType" />
</ httpHandlers >

Das Attribut type für den HTTP-Handler wird mit den gleichen Syntaxoptionen wie bei HTTP-Modulen ausgedrückt. Diese Einstellungen in der Datei Web.config können auch in die Datei machine.config eingefügt werden. Dadurch werden die Handler und Module für alle Webanwendungen auf dem Server aktiviert. Das folgende Codefragment zeigt das Element <httpHandlers> in der Datei Web.config. Diese Datei ist in der Demonstration enthalten, die zum Download für diesen Artikel gehört. Das Element gibt an, dass eingehende Anforderungen für /elmah/default.aspx von der Klasse ErrorLogPageFactory dargestellt werden sollen.

<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>

Wie Sie sehen, können HTTP-Module und -Handler ohne weiteres in wenigen Sekunden zu einer ASP.NET-Webanwendung hinzugefügt werden, ohne dass die ASP.NET-Anwendung erneut kompiliert oder weitergegeben werden muss. Aus diesem Grund eignen sich HTTP-Module und -Handler sehr gut für die Wiederverwendung sowie dafür, Anwendungen in lose gekoppelte, problemlos verwaltbare Komponenten zu zerlegen.

Untersuchen der ELMAH-Architektur

Die ELMAH-Architektur besteht aus drei Subsystemen:

  • Einem Fehlerprotokollierungs-Subsystem

  • Einem HTTP-Modulsubsystem

  • Einem HTTP-Handlersubsystem

Das Fehlerprotokollierungs-Subsystem ist für zwei Aufgaben zuständig: Aufzeichnen von Fehlern im Protokoll und Abrufen von Fehlerinformationen aus dem Protokoll. Das HTTP-Modulsubsystem hat die Aufgabe, einen Fehler zu protokollieren, wenn in der ASP.NET-Anwendung eine nicht behandelte Ausnahme auftritt. Das HTTP-Handlersubsystem ermöglicht die Darstellung des Fehlerprotokolls als Markup und bildet eine webbasierte Schnittstelle zum Fehlerprotokoll sowie einen RSS-Feed.

Wie Abbildung 5 zeigt, wird das Fehlerprotokollierungs-Subsystem sowohl vom HTTP-Modul- als auch vom HTTP-Handlersubsystem verwendet. Das HTTP-Modulsubsystem sendet Ausnahmeinformationen an das Fehlerprotokollierungs-Subsystem, während das HTTP-Handlersubsystem die Fehlerinformationen liest und darstellt.

Integration des Fehlerprotokollierungssystems
Abbildung 5: Integration des Fehlerprotokollierungssystems

Zum besseren Verständnis der ELMAH-Architektur sollen diese drei Subsysteme nun ausführlicher untersucht werden.

Fehlerprotokollierungs-Subsystem

Das Fehlerprotokollierungs-Subsystem hat die Aufgabe, Fehler im Protokoll aufzuzeichnen und Funktionen zum Abrufen von Details über einen bestimmten Fehler oder eine Teilmenge der Fehler bereitzustellen. Diese Funktionen werden durch verschiedene Klassen zur Verfügung gestellt:

  • ErrorLog: Diese abstrakte Klasse enthält die Methoden zum Lesen und Schreiben des Protokolls.

  • Error: Diese Klasse enthält Eigenschaften, die die Details eines bestimmten Fehlers beschreiben.

  • ErrorLogEntry: Diese Klasse stellt eine bestimmte Error-Instanz für ein bestimmtes ErrorLog dar. Die Klasse ErrorLogEntry ordnet eine Error-Instanz im Wesentlichen der ErrorLog-Instanz zu, aus der sie stammt.

Diese drei Klassen und deren Zusammenarbeit mit den HTTP-Modulen und HTTP-Handlersubsystemen sollen im Folgenden untersucht werden, so dass ein umfassendes zentrales Dienstprogramm zur Protokollierung von Ausnahmen entsteht.

Untersuchen der Klasse "ErrorLog"

Je nach Projektkonfiguration oder -strategie empfiehlt es sich eventuell, das Fehlerprotokoll in unterschiedlichen Sicherungsspeichern abzulegen. Auf einem Produktionsserver ist es unter Umständen sinnvoll, Ausnahmen mit Microsoft SQL Server zu protokollieren, während es auf einem Entwicklungsserver möglicherweise schon ausreicht, die Fehler in einer Reihe von XML-Dateien oder in einer Microsoft Access-Datenbank zu speichern. Damit verschiedene Sicherungsspeicher verwendet werden können, verfügt das Fehlerprotokollierungs-Subsystem über eine abstrakte Basisklasse ErrorLog, in der die Basismethoden definiert sind, die von allen ELMAH-Fehlerprotokollierern implementiert werden müssen. Zu diesen Methoden gehören:

  • Log(Error): Protokolliert einen Fehler im Sicherungsspeicher. Die Klasse Error stellt Informationen über nicht behandelte Ausnahmen dar. Diese Klasse wird weiter unten ausführlicher erläutert. Beim Protokollieren der Fehlerinformationen muss dem Fehler durch die Methode Log() außerdem ein eindeutiger Bezeichner zugeordnet werden.

  • GetError(id): Gibt Informationen über einen bestimmten, im Protokoll enthaltenen Fehler zurück.

  • GetErrors(...): Gibt eine Teilmenge der im Protokoll enthaltenen Fehler zurück. Diese Methode wird vom HTTP-Handlersubsystem verwendet, um die Fehler seitenweise darzustellen, anstatt alle Fehler auf einmal anzuzeigen.

ELMAH wird mit zwei ErrorLog-Implementierungen geliefert:

  • SqlErrorLog: Zeichnet Fehler unter Verwendung des Providers System.Data.SqlClient in einer Microsoft SQL Server 2000-Datenbank auf. SqlErrorLog erfordert SQL Server 2000, da einige XML-Funktionen von SQL Server 2000 verwendet werden. Dieses Implementierungsdetail kann jedoch geändert werden.

  • MemoryErrorLog: Zeichnet Fehler im Speicher der Anwendung (RAM) auf. Das heißt die Implementierung ist an die Anwendungsdomäne gebunden, da für jede Anwendung ein eigenes Protokoll geführt wird. Dieses Protokoll ist natürlich nach einem Neustart der Anwendungen oder nach Ablauf der Lebensdauer der Anwendungen nicht mehr vorhanden. Die Implementierung eignet sich daher hauptsächlich für Test- und Problembehandlungszwecke, wenn andere Implementierungen nicht eingesetzt werden können.

Sie können beide Ausnahmeprotokollierer verwenden. Dazu müssen Sie in die Datei Web.config der ASP.NET-Webanwendung lediglich einige Textzeilen einfügen. Wenn Sie Fehlerdetails weder in SQL Server noch im Anwendungsspeicher ablegen möchten, können Sie einen benutzerdefinierten Protokollierer erstellen. Erstellen Sie zur Implementierung eines Fehlerprotokollierers für ELMAH eine Klasse, die ErrorLog erweitert, und stellen Sie die Implementierung der Methoden Log(), GetError() und GetErrors() für den gewünschten Speicher bereit.

Sowohl das HTTP-Modulsubsystem als auch das HTTP-Handlersubsystem in ELMAH interagieren direkt mit der angegebenen ErrorLog-Klasse. Dabei kann es sich um die Klassen SqlErrorLog, MemoryErrorLog oder um eine benutzerdefinierte Protokollklasse handeln. Das HTTP-Modul protokolliert Informationen über Ausnahmen, indem es eine Error-Instanz erstellt und diese an die Methode Log() der Methode ErrorLog übergibt. Die HTTP-Handler lesen Details über einen oder mehrere Fehler mithilfe der Methoden GetError() und GetErrors() von ErrorLog. Diese Methoden geben entweder eine bestimmte ErrorLogEntry-Instanz oder eine Gruppe von ErrorLogEntry-Instanzen zurück.

Informationen über die Klasse "Error"

Die Methode Log() von ErrorLog erwartet einen Eingabeparameter des Typs Error. Anstelle der im .NET Framework enthaltenen Klasse Exception wird die benutzerdefinierte Klasse Error verwendet, da sich die Klasse Exception eher dazu eignet, Informationen über Ausnahmen über den Codestapel und während der Lebensdauer einer Anwendung zu übermitteln. Die Exception-Objekte lassen sich jedoch aufgrund von Speicher-, Typ- und Portabilitätsproblemen nicht gut in einem Ausnahmeprotokoll speichern. Zum Speichern einer Exception-Instanz könnte zwar die binäre Serialisierung verwendet werden, dazu müsste das Exception-Objekt jedoch auf einem System deserialisiert werden können, auf dem die gleichen Typen und Assemblies zur Verfügung stehen. Insbesondere im Hinblick auf die Verwaltung und den Betriebsablauf ist diese Einschränkung jedoch nicht akzeptabel, da ein Protokoll und dessen Inhalte portierbar und nicht nur auf einem System mit einer speziellen Laufzeitumgebung oder Konfiguration darstellbar sein sollten. Außerdem fehlen einer Exception-Instanz häufig Peripherieinformationen, die sich auf eine bestimmte Webanwendung beziehen, etwa die Werte der ServerVariables-Collection der aktuellen Webanforderung, die für die Diagnose äußerst wertvoll sein können. Kurz gesagt, die Klasse Error fungiert als Ersatz für alle Ausnahmetypen und speichert Informationen über eine Ausnahme, die in einer Webanwendung ausgelöst wurde.

Tabelle 1 enthält die vollständige Liste der Error-Eigenschaften.

Eigenschaft

Beschreibung

Exception

Die Exception-Instanz des betreffenden Fehlers. Hierbei handelt es sich lediglich um eine Laufzeiteigenschaft, die niemals zusammen mit einer Instanz der Klasse bestehen bleibt.

ApplicationName

Der Name der Anwendung, in welcher der Fehler aufgetreten ist.

HostName

Der Name des Hostcomputers, auf dem der Fehler aufgetreten ist. Ein guter Standardwert ist Environment.MachineName.

Type

Der Typ, die Klasse oder die Kategorie des Fehlers. In der Regel ist dies der vollständige Typname (ohne Assemblyqualifizierung) der Ausnahme.

Source

Die Quelle des Fehlers, in der Regel identisch mit der Message-Eigenschaft eines Exception-Objekts.

Message

Eine kurze Beschreibung des Fehlers, in der Regel identisch mit der Message-Eigenschaft eines Exception-Objekts.

Detail

Ausführlicher Text des Fehlers, beispielsweise die vollständige Stapelüberwachung.

User

Der Benutzer, der zum Zeitpunkt des Fehlers bei der Anwendung angemeldet war und der durch Thread.CurrentPrincipal.Identity.Name zurückgegeben wird.

Time

Datum und Uhrzeit des Fehlers. Hierbei handelt es sich immer um die lokale Uhrzeit.

StatusCode

Der aufgrund des Fehlers im Antwortheader zurückgegebene Statuscode. Bei einer FileNotFoundException ist dies z. B. der Wert 404. Leider kann dieser Wert in ASP.NET nicht immer zuverlässig ermittelt werden. In einigen Fällen wird als StatusCode-Wert eventuell Null zurückgegeben.

WebHostHtmlMessage

Die standardmäßige HTML-Meldung, die der Webhost (ASP.NET) erzeugt, wenn keine benutzerdefinierten Fehlerseiten vorhanden sind.

ServerVariables

Eine NameValueCollection von Webservervariablen, beispielsweise Variablen, die in HttpRequest.ServerVariables enthalten sind.

QueryString

Eine NameValueCollection von HTTP-Abfragezeichenfolgenvariablen, beispielsweise Variablen, die in HttpRequest.QueryString enthalten sind.

Form

Eine NameValueCollection von Formularvariablen, beispielsweise Variablen, die in HttpRequest.Form enthalten sind.

Cookies

Eine NameValueCollection von Cookies, die vom Client gesendet wurden, beispielsweise Cookies, die in HttpRequest.Cookies enthalten sind.

Die Eigenschaft WebHostHtmlMessage muss noch näher erläutert werden. Wenn in der ASP-NET-Webanwendung eine nicht behandelte Ausnahme auftritt und Sie die Anwendung nicht für die Verwendung von benutzerdefinierten Fehlerseiten (in Englisch) konfiguriert haben, wird ein Fenster ähnlich dem in Abbildung 6 dargestellten angezeigt. Ein solches Fenster hat jeder ASP.NET-Entwickler bereits viel zu oft gesehen.

Standardfehlerseite
Abbildung 6: Standardfehlerseite

Wenn eine Ausnahme ausgelöst wird, erfolgt ein Zugriff auf den tatsächlichen HTML-Code für das entsprechende Fenster (in Englisch), und dieser Code wird in der Eigenschaft WebHostHtmlMessage der Klasse Error gespeichert. Wenn Sie die Seite aufrufen, auf der detaillierte Informationen über eine bestimmte Ausnahme angezeigt werden, und die Eigenschaft WebHostHtmlMessage der entsprechenden Error-Instanz einen Wert enthält, wird dem Benutzer ein Link zu einer Seite angezeigt, auf der das Fenster mit Informationen über die Ausnahme dargestellt wird (z. B. das in Abbildung 6 dargestellte Fenster). Sinnvollerweise wird hier also nicht nur die Ausnahme protokolliert, vielmehr können Sie bei einer späteren Überprüfung des Protokolls sogar die originale Fehlerseite aufrufen, die von ASP.NET erzeugt wurde. All dies ist möglich, obwohl benutzerdefinierte Fehler aktiviert sind!

Die Klasse Error verfügt auch über Methoden zum Serialisieren und Deserialisieren ihres Status in bzw. aus einem XML-Format. Einzelheiten hierzu finden Sie unter FromXml und ToXml im zugehörigen Code.

ErrorLogEntry: Verknüpfen einer "Error"-Instanz mit einer "ErrorLog"-Instanz

Die letzte Klasse im Fehlerprotokollierungs-Subsystem ist die Klasse ErrorLogEntry, die eine Error-Instanz mit einer ErrorLog-Instanz verknüpft. Wenn das HTTP-Handlersubsystem die Methode GetError() aufruft, um Informationen über eine bestimmte Ausnahme abzurufen, werden diese Informationen von der Methode GetError() aus dem jeweiligen Sicherungsspeicher abgerufen und in eine ErrorLogEntry-Instanz eingefügt. Die Klasse ErrorLogEntry enthält drei Eigenschaften:

  • Id: Die eindeutige ID der Ausnahmedetails.

  • Log: Ein Verweis auf die ErrorLog-Instanz, die den Sicherungsspeicher darstellt.

  • Error: Eine gefüllte Instanz der Klasse Error, welche die Details zum jeweiligen Fehler enthält.

Während die Methode GetError() eine einzelne ErrorLogEntry-Instanz zurückgibt, gibt die Methode GetErrors() eine Liste von ErrorLogEntry-Instanzen zurück. GetErrors() wurde speziell dafür entwickelt, Fehler in Form von n Datensätzen seitenweise darzustellen.

Abbildung 7 zeigt eine aktualisierte Ansicht der ELMAH-Architektur mit einer detaillierteren Darstellung des Fehlerprotokollierungs-Subsystems.

Aktualisierte Architektur
Abbildung 7: Aktualisierte Architektur

HTTP-Modulsubsystem

ELMAH besteht aus zwei HTTP-Modulen: ErrorLogModule und ErrorMailModule. ErrorLogModule ist ein HTTP-Modul, das einen Ereignishandler für das Ereignis Error der Anwendung erzeugt. Bei Auftreten einer nicht behandelten Ausnahme aktiviert das HTTP-Modul den Fehlerprotokollierer, der in der Anwendungskonfiguration festgelegt ist, und ruft für diesen die Log()-Methode auf. Dabei wird eine Error-Instanz übergeben, welche die Informationen über die Ausnahme sowie den HttpContext für die aktuelle Anforderung enthält. Der folgende Quellcode zeigt den betreffenden Code der Klasse ErrorLogModule:

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);
        }
    }
}

Die Ausführung von ErrorLogModule beginnt in der Methode Init(). Dort wird der ASP.NET-Laufzeitanwendung mitgeteilt, dass die Methode OnError() aufgerufen werden soll, sobald das Ereignis Error ausgelöst wird. Die Methode OnError() verweist auf das Objekt HttpApplication und ruft die Methode LogException() auf. Dabei werden die Details über die letzte Ausnahme sowie die HttpContext-Instanz der entsprechenden Anforderung übergeben. Mit LogException() wird lediglich die Log()-Methode der entsprechenden ErrorLog-Klasse aufgerufen, wobei eine neue Error-Instanz übergeben wird. (Der Konstruktor der Error-Instanz verwendet eine Exception- sowie eine HttpContext-Instanz und füllt die Eigenschaften entsprechend. Weitere Informationen hierzu finden Sie im Quellcode, der im Download enthalten ist.)

Das ErrorLogModule enthält eine schreibgeschützte ErrorLog-Eigenschaft und gibt die ErrorLog-Instanz zurück, die von ErrorLog.Default zurückgegeben wurde. Default ist eine statische Eigenschaft des Typs ErrorLog in der Klasse ErrorLog. Damit wird die Konfiguration der Webanwendung abgefragt, um die für die Ausnahmeprotokollierung zu verwendende Klasse zu ermitteln: SqlErrorLog, MemoryErrorLog oder eine benutzerdefinierte Klasse für die Ausnahmeprotokollierung.

Hinweis Im Abschnitt "Hinzufügen von ELMAH zu einer ASP.NET-Webanwendung" wird erläutert, wie eine Webanwendung zur Verwendung eines bestimmten Ausnahmeprotokollierers konfiguriert wird. Dabei müssen lediglich einige Zeilen in die Dateien Web.config oder machine.config eingefügt werden.

Das andere HTTP-Modul im HTTP-Modulsubsystem ist die Klasse ErrorMailModule, die bei Auftreten einer Ausnahme eine E-Mail-Nachricht an einen Administrator sendet. Dieses ELMAH-Element wird hier nicht erläutert. Sie können jedoch anhand der Codebeispiele, die im Download zu diesem Artikel enthalten sind, mehr über die Verwendung dieses Moduls erfahren.

HTTP-Handlersubsystem

Wie oben bereits erwähnt, besteht der Zweck von HTTP-Handlern darin, Inhalte für einen bestimmten Ressourcentyp darzustellen. Wenn eine Anforderung in die ASP.NET-HTTP-Pipeline gelangt, prüft das ASP.NET-Modul den angeforderten Pfad und stellt fest, mit welchem HTTP-Handler die angeforderte Ressource verarbeitet werden soll. Eine ASP.NET-Anwendung kann vor allem so konfiguriert sein, dass ein bestimmter Pfad entweder von einem HTTP-Handler oder von einer HTTP-Handlerfactory-Klasse verarbeitet wird. Eine Klasse vom Typ HTTP-Handlerfactory ist eine Klasse, die nicht direkt für die Darstellung der Inhalte zuständig ist, sondern für die Auswahl und Rückgabe einer HTTP-Handlerinstanz. Diese zurückgegebene HTTP-Handlerinstanz erhält anschließend die Aufgabe, die angeforderte Ressource darzustellen.

Das HTTP-Handlersubsystem von ELMAH umfasst eine Reihe von HTTP-Handlerklassen, die Code zur Anzeige der protokollierten Fehler erzeugen sollen, sowie eine einzelne HTTP-Handlerfactory-Klasse. Die HTTP-Handlerfactory-Klasse ErrorLogPageFactory prüft den Abschnitt PathInfo des angeforderten URL, um festzustellen, mit welchem HTTP-Handler die Ausgabe erzeugt werden soll.

Hinweis Der Abschnitt PathInfo einer URL umfasst den zusätzlichen Inhalt, der auf den Dateinamen folgt. Er steht in der Eigenschaft PathInfo des Objekts Request zur Verfügung. In der URL http://www.example.com/someDir/somePage.aspx/somePath beispielsweise ist somePath der PathInfo-Abschnitt der URL. Weitere Informationen über die Terminologie für die verschiedenen Bestandteile einer URL sowie über die entsprechenden Eigenschaften des Objekts Request finden Sie im Weblog Making Sense of ASP.NET Paths (in Englisch) von Rick Strahl (in Englisch).

Das folgende Codefragment zeigt den interessanteren Code der HTTP-Handlerfactory-Klasse ErrorLogPageFactory.

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();
        }
    }
}

Sie sehen, dass die Methode GetHandler() der Klasse ErrorLogPageFactory eine HTTP-Handlerinstanz zurückgibt, die auf dem PathInfo-Teil der Anforderung beruht. Hat PathInfo den Wert rss, wird eine Instanz des HTTP-Handlers ErrorRssHandler zurückgegeben, der das Protokoll als RSS-Feed darstellt. Hat PathInfo den Wert detail, wird die HTTP-Handlerinstanz ErrorDetailPage zurückgegeben, die Informationen über eine bestimmte Ausnahme anzeigt.

In den Einstellungen der ASP.NET-Webanwendung müssen Sie einen Pfad angeben, welcher der HTTP-Handlerfactory-Klasse ErrorLogPageFactory zugeordnet wird, beispielsweise ErrorLog.aspx. Um ein RSS-Feed des Ausnahmeprotokolls anzuzeigen, könnten Sie die folgende Webseite aufrufen: http://www.example.com/ErrorLog.aspx/rss.

Die verschiedenen HTTP-Handlerklassen von ELMAH, ErrorDetailPage, ErrorHtmlPage, ErrorRssHandler, ErrorLogPage usw. erstellen unterschiedlichen Markupcode. Der HTTP-Handler ErrorRssHandler durchläuft beispielsweise in einer Schleife die letzen 15 Fehler und gibt den entsprechenden XML-Code aus, um diese Informationen in einem RSS-Format darzustellen. Die übrigen HTTP-Handler sind sämtlich direkt oder indirekt von der Klasse System.Web.UI.Page abgeleitet (aus dieser Klasse sind alle ASP.NET-CodeBehind-Klassen abgeleitet). Diese seitenbezogenen HTTP-Handler überschreiben die Methoden Render() und OnLoad() der Klasse Page und erzeugen eine HTML-Oberfläche, in der eine navigierbare Liste der protokollierten Ausnahmen angezeigt wird. Die Abbildungen 1, 2 und 3 zeigen jeweils einen Screenshot dieser Seiten.

Hinweis   Obwohl die Klasse Error die Auflistungen ServerVariables, QueryString, Form und Cookie speichert, wird bei den ausführlichen Informationen zu einer Ausnahme nur die Auflistung ServerVariables angezeigt. Der Grund hierfür ist, dass die QueryString-Parameter und -Cookies mit den Parametern QUERY_STRING bzw. HTTP_COOKIE der Auflistung ServerVariable angezeigt werden können. Die Auflistung Form wird übergangen, da diese unter Umständen viele Kilobyte Ansichtsstatusinformationen enthält, die bei der Diagnose in der Regel wenig hilfreich sind. Sie können die Details des HTTP-Handlers natürlich gegebenenfalls ändern, so dass diese Informationen einbezogen werden.

Nach der Untersuchung der drei Subsysteme von ELMAH soll nun dargestellt werden, wie ELMAH zu einer vorhandenen ASP.NET-Webanwendung hinzugefügt wird. Achten Sie besonders darauf, wie einfach es ist, ELMAH zu einer beliebigen Site hinzuzufügen, ein Vorteil der Bildung von Komponenten durch die HTTP-Handler und -Module.

Hinzufügen von ELMAH zu einer ASP.NET-Webanwendung

ELMAH zu einer ASP.NET-Webanwendung hinzuzufügen, ist ein sehr einfacher Vorgang, der aus zwei Schritten besteht:

  • Hinzufügen der ELMAH-Assembly zur Webanwendung.

  • Konfigurieren der Webanwendung für die Verwendung der HTTP-Module und -Handler von ELMAH.

Um ELMAH für eine Webanwendung auf einem Webserver zur Verfügung zu stellen, wird die Assembly in das Verzeichnis /bin der Webanwendung kopiert, und die ELMAH-Einstellungen werden durch die Datei Web.config konfiguriert. Darüber hinaus haben Sie die Möglichkeit, ELMAH für alle Webanwendungen auf einem Webserver zur Verfügung zu stellen. Dazu fügen Sie die Assembly zum Globalen Assemblycache (GAC) des Webservers hinzu und konfigurieren die gleichen Einstellungen nicht in der Datei Web.config, sondern in der Datei machine.config.

In der Datei Web.config (bzw. machine.config) müssen Sie die folgenden Einstellungen hinzufügen:

  • Ein <sectionGroup>-Element im Element <configSections>. Damit wird der neue Abschnittsname <gotdotnet.elmah> definiert, der wiederum den Abschnitt <errorLog> mit Anweisungen zum Protokollieren der Ausnahmeinformationen enthält.

  • Einen Abschnitt <gotdotnet.elmah> mit einem darin enthaltenen Abschnitt <errorLog>, der einen Typverweis auf den von ELMAH zu verwendenden Ausnahmeprotokollierer enthält, sowie die Einstellungen für den entsprechenden Ausnahmeprotokollierer.

  • Einen Eintrag im Abschnitt <httpHandlers>, der den Pfad angibt, über den bei Aufruf in einem Browser verschiedene Ansichten des Fehlerprotokolls dargestellt werden.

  • Einen Eintrag im Abschnitt <httpModules>, mit dem ErrorLogModule zur ASP.NET-HTTP-Pipeline hinzugefügt wird.

Das folgende Fragment aus der im Download zu diesem Artikel enthaltenen Datei Web.config zeigt, wie diese vier Einstellungen festgelegt werden können:

<?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>

Das Element <sectionGroup> im Element <configSections> gibt an, dass die Konfigurationsdatei <gotdotnet.elmah> eine zusätzliche Abschnittsgruppe enthält. Außerdem wird damit angegeben, dass dieser benutzerdefinierte Abschnitt seinerseits den Abschnitt <errorLog> enthält. Innerhalb des eigentlichen Elements <gotdotnet.elmah> befindet sich das Element <errorLog>, mit dem festgelegt wird, welche Fehlerprotokollimplementierung zu verwenden ist. Wie oben erwähnt, wird ELMAH mit zwei integrierten Implementierungen, SqlErrorLog und MemoryErrorLog, geliefert. Im Element <errorLog> können Sie die zu verwendende Implementierung oder einen benutzerdefinierten Ausnahmeprotokollierer festlegen, den Sie selbst erstellt haben. Das Element <errorLog> enthält außerdem die Einstellungen für eine bestimmte Fehlerprotokollimplementierung. Wenn Sie im Element <errorLog> z. B. angeben, dass SqlErrorLog verwendet werden soll, müssen Sie eine connectionString-Eigenschaft einfügen, aus der hervorgeht, wie die Verbindung mit der Datenbank hergestellt wird. Das SQL-Skript zur Erstellung der entsprechenden Tabelle und der zugehörigen gespeicherten Prozeduren ist im Download enthalten.

Hinweis   Wenn bei Auftreten einer nicht behandelten Ausnahme ein Administrator per E-Mail benachrichtigt werden soll, müssen Sie ein weiteres <section>-Element in <sectionGroup> hinzufügen, mit dem ein neues Element namens <errorMail> definiert wird. Zusätzlich müssen Sie im Element <gotdotnet.elmah> ein <errorMail>-Element hinzufügen. In der im Download enthaltenen Datei Web.config finden Sie ein Beispiel für diese Anweisungen.

Im Abschnitt <httpHandlers> wird angegeben, dass ErrorLogPageFactory (eine HTTP-Handlerfactory) verwendet werden soll, um den HTTP-Handler abzurufen, der den Inhalt zur Anzeige des Fehlerprotokolls aufbereitet. Der Wert des Attributs path gibt den URL relativ zum virtuellen Stammverzeichnis der Anwendung an, der zur Anzeige des Fehlerprotokolls dient. Sie können hier einen beliebigen Wert eingeben. Achten Sie jedoch darauf, dass die Erweiterung der URL vom ASP.NET-Modul verarbeitet werden kann. Wenn Sie als Pfad beispielsweise errors.log angeben, müssen Sie IIS so konfigurieren, dass Anforderungen für errors.log der ASP.NET-ISAPI-Erweiterung (aspnet_isapi.dll) zugeordnet werden. Wenn Sie sicherstellen möchten, dass das Protokoll nur von Administratoren angezeigt werden kann, verwenden Sie die URL-Autorisierungsfunktionen von ASP.NET, um den Zugriff auf einen bestimmten Benutzer oder eine Gruppe von Benutzern bzw. Rollen einzuschränken. Soll dagegen der Zugriff auf das Protokoll über das Web vollständig deaktiviert werden, wird der Abschnitt <httpHandlers> einfach gar nicht konfiguriert.

Durch den Abschnitt <httpModules> wird das HTTP-Modul ErrorLogModule zur ASP.NET-HTTP-Pipeline hinzugefügt. Sie müssen diese <httpModules>-Einstellung unbedingt angeben, andernfalls empfängt ELMAH kein Error-Ereignis und protokolliert somit auch keine nicht behandelten Ausnahmen.

Sie sehen, dass sich ELMAH problemlos in eine vorhandene ASP.NET-Webanwendung integrieren lässt. Die einfache Weitergabe und Wiederverwendbarkeit von ELMAH beruht auf der Komponentenbildung mithilfe von HTTP-Modulen und -Handlern.

Schlussbemerkung

Dieser Artikel hat hoffentlich deutlich dargestellt, wie hervorragend sich HTTP-Handler und -Module dazu eignen, aus Funktionen eigenständige Komponenten zu erstellen, die in einer ASP.NET-Webanwendung überall eingesetzt werden können. Allgemeine Aufgaben wie die zentrale, anwendungsweite Protokollierung oder die Überwachung von Anforderungen in der gesamten Anwendung können mithilfe von Handlern und Modulen als Komponenten zur Verfügung gestellt werden. Durch die Integration dieser Funktionen in verschiedene Komponenten können diese problemlos wiederverwendet, gewartet und weitergegeben werden. Dabei müssen sie weder in vorhandenen Code bzw. vorhandene Anwendungen migriert oder integriert werden, noch müssen vorhandener Code bzw. Anwendungen neu kompiliert werden.

Zur Demonstration der mit HTTP-Modulen und -Handlern möglichen Komponentenbildung wurde ELMAH untersucht, eine zentrale Fehlerprotokollierungs- und E-Mail-Anwendung. Über ein HTTP-Modul empfängt ELMAH anwendungsweite Error-Ereignisse, die bei Auftreten nicht behandelter Ausnahmen ausgelöst werden. Sobald ELMAH eine nicht behandelte Ausnahme empfängt, wird diese in einer SQL Server-Datenbank, im Arbeitsspeicher oder eventuell auch in einem anderen Sicherungsspeicher abgelegt. ELMAH kann den Inhalt der Ausnahme zudem per E-Mail an Empfänger wie Entwickler und für den Betriebsablauf zuständige Mitarbeiter weiterleiten.

Neben einem HTTP-Modul enthält ELMAH eine Reihe von HTTP-Handlern und eine HTTP-Handlerfactory, so dass das Fehlerprotokoll in einem webbasierten Medium dargestellt werden kann. Hierzu gehört nicht nur eine herkömmliche Webseite, sondern auch ein RSS-Feed. ELMAH enthält eine separate Komponente, in der die Darstellungsfunktion in einem HTTP-Handler integriert ist. Die Webanwendung benötigt daher keine ASP.NET-Webseite, auf der die entsprechenden Informationen dargestellt werden. Dank der Verwendung von HTTP-Handlern lässt sich ELMAH problemlos bereitstellen. Es ist weder eine Neukompilierung der Webanwendung, noch ein Upload einer ASP.NET-Webseite auf den Produktionsserver erforderlich.

ELMAH ist nur ein Beispiel für die Leistungsfähigkeit der Komponentenbildung mithilfe von HTTP-Handlern und -Modulen. Möglicherweise gibt es weitere anwendungsweite Verfahren, die Sie implementiert haben und die von der Komponentenbildung durch Handler und Module profitieren können.

Viel Spaß beim Programmieren!

Danksagung

Bevor dieser Artikel dem MSDN-Editor vorgelegt wurde, haben ihn eine Reihe von freiwilligen Mitarbeitern Korrektur gelesen und Feedback zum Inhalt, zur Grammatik und zur Ausrichtung gegeben. Zu den Hauptlektoren dieses Artikels gehören Milan Negovan, Carl Lambrecht, Dominique Kuster, Roman Mathis, Raffael Zaghet, Muhammad Abubakar und Patrick Schuler.

Referenzen

Verwandte Literatur

Atif Aziz verfügt über nahezu 13 Jahre Erfahrung in der Entwicklung von Lösungen auf der Microsoft-Plattform. Er ist Chefberater bei der Skybow AG. Sein Haupttätigkeitsfeld besteht darin, Kunden zu helfen, Lösungen auf Grundlage der .NET-Entwicklungsplattform zu verstehen und zu erstellen. Atif Aziz ist regelmäßig für die Gemeinschaft der Microsoft-Entwickler tätig, nimmt an Microsoft-Konferenzen und Konferenzen ohne Microsoft-Beteiligung teil und schreibt Artikel für technische Publikationen. Er ist INETA-Referent und Vorsitzender der größten Swiss .NET User Group (dotMUGS) (in Englisch). Sie erreichen ihn unter atif.aziz@skybow.com (in Englisch) oder über seine Website unter http://www.raboof.com/ (in Englisch).

Scott Mitchell, Autor von fünf ASP/ASP.NET-Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 für Microsoft Web Technologies. Scott Mitchell ist als freischaffender Berater, Kursleiter und Redakteur tätig. Sie erreichen ihn unter mitchell@4guysfromrolla.com (in Englisch) oder über sein Weblog unter http://scottonwriting.net/ (in Englisch).


Anzeigen:
© 2016 Microsoft