So protokollieren Sie Anforderungs- und Antwortmetadaten in der ASP.NET-Web-API

Wie die Authentifizierung, das Caching und die Ausnahmeverwaltung ist die Protokollierung ein Querschnittsthema - eine Funktion, die sich auf die gesamte Anwendung auswirkt -, das zentralisiert werden sollte. Wir protokollieren häufig Anwendungsdaten, die die Folge von Methodenaufrufen oder -ereignissen, Benutzeraktionen oder sogar Fehlern enthalten können, die bei der Ausführung der Anwendung auftreten können. Es gibt viele Protokollierungsframeworks, die Sie nutzen können. In diesem Artikel konzentrieren wir uns jedoch darauf, wie Anforderungen und Antworten in der ASP.NET-Web-API protokolliert werden können.

Das Protokollieren von Anforderungen und Antworten in der Web-API ist hilfreich beim Debuggen, Verfolgen und Überprüfen der eingehenden und ausgehenden Serviceaufrufe. Durch die Protokollierung aller Anfragen und Antworten an einem Ort wird das Erkennen von Problemen bei Anfragen und Antworten zum Kinderspiel. In diesem Beitrag erstellen wir einen benutzerdefinierten Nachrichtenhandler zum Überwachen und Protokollieren von Anforderungen und Antworten in der Web-API. Der Nachrichtenhandler wird verwendet, um Anrufe abzufangen und alle Anforderungen und Antworten zentral an einem Ort zu protokollieren.

Strategien, um Querschnittsthemen in die Web-API einzubringen

Es gibt mehrere Möglichkeiten, die Protokollierung und andere Querschnittsthemen in die Web-API einzufügen. Eine Möglichkeit besteht darin, eine benutzerdefinierte ApiController-Klasse oder eine Basisklasse für alle unsere Controller zu erstellen und dann die ExecuteAsync-Methode zu überschreiben. Eine andere Möglichkeit ist die Verwendung eines benutzerdefinierten Aktionsfilters. Beide Strategien haben jedoch ihre Grenzen. Im ersteren Fall müssten wir sicherstellen, dass alle unsere Controller die benutzerdefinierte Basis-Controller-Klasse erweitern. In letzterem Fall müssten wir sicherstellen, dass der Filter auf alle von uns verwendeten Controller angewendet wird.

Die beste Strategie ist meiner Meinung nach, einen Nachrichtenhandler zu verwenden, da Sie ihn nur einmal schreiben und dann an einer Stelle registrieren. Da der benutzerdefinierte Nachrichtenhandler viel früher in der Pipeline aufgerufen wird, dh noch vor dem HttpControllerDispatcher, eignet er sich auch gut zum Einfügen von Querschnittsthemen. Nachrichtenhandler sind übrigens Klassen, die die abstrakte HttpMessageHandler-Klasse erben. Daher werden wir einen Nachrichtenhandler nutzen, um unseren benutzerdefinierten Logger in diesen Beitrag einzufügen.

Wenn Sie den in diesem Beitrag dargestellten Quellcode erstellen und ausführen möchten, sollte Visual Studio auf Ihrem System ausgeführt werden. Außerdem sollte NLog installiert sein. Wenn Sie wissen möchten, wie NLog installiert, konfiguriert und verwendet wird, lesen Sie meinen Artikel über NLog hier.  

Erstellen unseres Kundenloggers für die Web-API

Erstellen Sie ein neues Web-API-Projekt in Visual Studio und speichern Sie es unter Ihrem gewünschten Namen. Wir werden hier einen benutzerdefinierten Delegierungshandler verwenden, um die Aufrufe der Web-API abzufangen. Lassen Sie uns zunächst eine benutzerdefinierte POCO-Klasse erstellen, in der alle Informationen aus unseren Anfragen und Antworten gespeichert werden.

öffentliche Klasse LogMetadata

    {

        öffentliche Zeichenfolge RequestContentType {get; einstellen; }}

        öffentlicher String RequestUri {get; einstellen; }}

        öffentliche Zeichenfolge RequestMethod {get; einstellen; }}

        public DateTime? RequestTimestamp {get; einstellen; }}

        öffentliche Zeichenfolge ResponseContentType {get; einstellen; }}

        public HttpStatusCode ResponseStatusCode {get; einstellen; }}

        public DateTime? ResponseTimestamp {get; einstellen; }}

    }}

Jetzt implementieren wir eine benutzerdefinierte Klasse namens LogHandler. Dies ist im Wesentlichen ein Nachrichtenhandler, der die DelegatingHandler-Klasse erweitert.

öffentliche Klasse CustomLogHandler: DelegatingHandler

    {

        geschützte Überschreibung asynchron Aufgabe SendAsync (HttpRequestMessage-Anforderung, CancellationToken CancellationToken)

        {

           return base.SendAsync (Anfrage, CancellationToken);

        }}

    }}

Das folgende Codefragment zeigt, wie Sie Anforderungsmetadaten erstellen können. Diese Methode wird von der SendAsync-Methode unseres benutzerdefinierten Nachrichtenhandlers aufgerufen und gibt eine Instanz der LogMetadata-Klasse zurück.

private LogMetadata BuildRequestMetadata (HttpRequestMessage-Anforderung)

    {

        LogMetadata log = neue LogMetadata

        {

            RequestMethod = request.Method.Method,

            RequestTimestamp = DateTime.Now,

            RequestUri = request.RequestUri.ToString ()

        };

        Rückgabeprotokoll;

    }}

Als Nächstes müssen wir die Protokollmetadateninstanz mit Informationen aus dem Antwortobjekt aktualisieren. So kann dies erreicht werden.

private LogMetadata BuildResponseMetadata (LogMetadata logMetadata, HttpResponseMessage-Antwort)

    {

        logMetadata.ResponseStatusCode = response.StatusCode;

        logMetadata.ResponseTimestamp = DateTime.Now;

        logMetadata.ResponseContentType = response.Content.Headers.ContentType.MediaType;

        return logMetadata;

    }}

Hier finden Sie den vollständigen Quellcode des benutzerdefinierten Nachrichtenhandlers als Referenz.

öffentliche Klasse CustomLogHandler: DelegatingHandler

    {

        geschützte Überschreibung asynchron Aufgabe SendAsync (HttpRequestMessage-Anforderung, CancellationToken CancellationToken)

        {

            var logMetadata = BuildRequestMetadata (Anfrage);

            var response = warte auf base.SendAsync (request, cancellationToken);

            logMetadata = BuildResponseMetadata (logMetadata, Antwort);

            warte auf SendToLog (logMetadata);

            Antwort zurückgeben;

        }}

        private LogMetadata BuildRequestMetadata (HttpRequestMessage-Anforderung)

        {

            LogMetadata log = neue LogMetadata

            {

                RequestMethod = request.Method.Method,

                RequestTimestamp = DateTime.Now,

                RequestUri = request.RequestUri.ToString ()

            };

            Rückgabeprotokoll;

        }}

        private LogMetadata BuildResponseMetadata (LogMetadata logMetadata, HttpResponseMessage-Antwort)

        {

            logMetadata.ResponseStatusCode = response.StatusCode;

            logMetadata.ResponseTimestamp = DateTime.Now;

            logMetadata.ResponseContentType = response.Content.Headers.ContentType.MediaType;

            return logMetadata;

        }}

        private asynchrone Aufgabe SendToLog (LogMetadata logMetadata)

        {

            // TODO: Schreiben Sie hier Code, um die logMetadata-Instanz in einem vorkonfigurierten Protokollspeicher zu speichern ...

            return true;

        }}

    }}

Beachten Sie, dass Sie den erforderlichen Code schreiben müssen, um die in der SendToLog-Methode angezeigte logMetadata-Instanz in einem vorkonfigurierten Protokollziel, dh einer Datei oder einer Datenbank, zu speichern. Ich bevorzuge die Verwendung von NLog, um diese Metadaten zu protokollieren. Sie können sich auch hier auf meinen Artikel über NLog beziehen, um zu sehen, wie dies getan werden kann.

Registrieren des Nachrichtenhandlers

Um den benutzerdefinierten Nachrichtenhandler zu registrieren, können Sie das Application_Start-Ereignis in der Datei Global.asax.cs oder die Register-Methode der WebApiConfig-Klasse nutzen. Das folgende Codeausschnitt zeigt, wie Sie den Handler mithilfe der Register-Methode der WebApiConfig-Klasse registrieren können.

öffentliches statisches ungültiges Register (HttpConfiguration config)

    {

      // Schreibe hier deinen üblichen Code ...

      config.MessageHandlers.Add (neuer CustomLogHandler ());

    }}

In diesem Artikel haben wir untersucht, wie wir Anforderungen und Antworten in der Web-API mithilfe eines benutzerdefinierten Nachrichtenhandlers protokollieren können. Nachrichtenhandler sind eine hervorragende Möglichkeit, um Querschnittsthemen in die Web-API-Pipeline einzufügen. Obwohl wir andere Möglichkeiten haben, die Protokollierung in die Web-API einzufügen, z. B. eine benutzerdefinierte ApiController-Klasse oder einen benutzerdefinierten Aktionsfilter, ist die Verwendung eines benutzerdefinierten Nachrichtenhandlers ein einfacherer Ansatz. Sie können diese Implementierung jederzeit an Ihre Anforderungen anpassen, z. B. um weitere benutzerdefinierte Metadaten hinzuzufügen.

So machen Sie mehr in ASP.NET und ASP.NET Core:

  • Verwendung des In-Memory-Caching in ASP.NET Core
  • Behandlung von Fehlern in der ASP.NET-Web-API
  • Übergeben mehrerer Parameter an Web-API-Controller-Methoden
  • So protokollieren Sie Anforderungs- und Antwortmetadaten in der ASP.NET-Web-API
  • So arbeiten Sie mit HttpModules in ASP.NET
  • Erweiterte Versionierung in der ASP.NET Core-Web-API
  • Verwendung der Abhängigkeitsinjektion in ASP.NET Core
  • So arbeiten Sie mit Sitzungen in ASP.NET
  • So arbeiten Sie mit HTTPHandlern in ASP.NET
  • Verwendung von IHostedService in ASP.NET Core
  • So verwenden Sie einen WCF-SOAP-Dienst in ASP.NET Core
  • So verbessern Sie die Leistung von ASP.NET Core-Anwendungen
  • So verwenden Sie eine ASP.NET Core-Web-API mit RestSharp
  • So arbeiten Sie mit der Protokollierung in ASP.NET Core
  • Verwendung von MediatR in ASP.NET Core
  • So arbeiten Sie mit dem Sitzungsstatus in ASP.NET Core
  • Verwendung von Nancy in ASP.NET Core
  • Grundlegendes zur Parameterbindung in der ASP.NET-Web-API
  • So laden Sie Dateien in ASP.NET Core MVC hoch
  • Implementieren der globalen Ausnahmebehandlung in der ASP.NET Core-Web-API
  • Implementieren von Integritätsprüfungen in ASP.NET Core
  • Best Practices für das Caching in ASP.NET
  • Verwendung von Apache Kafka Messaging in .NET
  • So aktivieren Sie CORS in Ihrer Web-API
  • Wann wird WebClient vs. HttpClient vs. HttpWebRequest verwendet?
  • So arbeiten Sie mit Redis Cache in .NET
  • Verwendung von Task.WaitAll vs. Task.WhenAll in .NET