HttpClient-Nachrichtenhandler in ASP.NET-Web-API
Ein Nachrichtenhandler ist eine Klasse, die eine HTTP-Anforderung empfängt und eine HTTP-Antwort zurückgibt.
In der Regel werden eine Reihe von Nachrichtenhandlern miteinander verkettet. Der erste Handler empfängt eine HTTP-Anforderung, führt eine Verarbeitung durch und übergibt die Anforderung an den nächsten Handler. Irgendwann wird die Antwort erstellt und führt die Kette zurück. Dieses Muster wird als delegierender Handler bezeichnet.
Auf der Clientseite verwendet die HttpClient-Klasse einen Nachrichtenhandler, um Anforderungen zu verarbeiten. Der Standardhandler ist HttpClientHandler, der die Anforderung über das Netzwerk sendet und die Antwort vom Server abruft. Sie können benutzerdefinierte Nachrichtenhandler in die Clientpipeline einfügen:
Hinweis
ASP.NET-Web-API verwendet auch Nachrichtenhandler auf der Serverseite. Weitere Informationen finden Sie unter HTTP-Nachrichtenhandler.
Benutzerdefinierte Nachrichtenhandler
Um einen benutzerdefinierten Nachrichtenhandler zu schreiben, leiten Sie von System.Net.Http.DelegatingHandler ab, und überschreiben Sie die SendAsync-Methode . Hier die Signatur der Methode:
Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken);
Die -Methode nimmt eine HttpRequestMessage als Eingabe an und gibt asynchron eine HttpResponseMessage zurück. Eine typische Implementierung führt folgendes aus:
- Verarbeiten Sie die Anforderungsnachricht.
- Rufen Sie
base.SendAsync
auf, um die Anforderung an den inneren Handler zu senden. - Der innere Handler gibt eine Antwortnachricht zurück. (Dieser Schritt ist asynchron.)
- Verarbeiten Sie die Antwort, und geben Sie sie an den Aufrufer zurück.
Das folgende Beispiel zeigt einen Nachrichtenhandler, der der ausgehenden Anforderung einen benutzerdefinierten Header hinzufügt:
class MessageHandler1 : DelegatingHandler
{
private int _count = 0;
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
System.Threading.Interlocked.Increment(ref _count);
request.Headers.Add("X-Custom-Header", _count.ToString());
return base.SendAsync(request, cancellationToken);
}
}
Der Aufruf von base.SendAsync
ist asynchron. Wenn der Handler nach diesem Aufruf eine Arbeit ausführt, verwenden Sie die await Schlüsselwort (keyword), um die Ausführung nach Abschluss der Methode fortzusetzen. Das folgende Beispiel zeigt einen Handler, der Fehlercodes protokolliert. Die Protokollierung selbst ist nicht sehr interessant, aber das Beispiel zeigt, wie die Antwort innerhalb des Handlers abgerufen werden kann.
class LoggingHandler : DelegatingHandler
{
StreamWriter _writer;
public LoggingHandler(Stream stream)
{
_writer = new StreamWriter(stream);
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (!response.IsSuccessStatusCode)
{
_writer.WriteLine("{0}\t{1}\t{2}", request.RequestUri,
(int)response.StatusCode, response.Headers.Date);
}
return response;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_writer.Dispose();
}
base.Dispose(disposing);
}
}
Hinzufügen von Nachrichtenhandlern zur Clientpipeline
Verwenden Sie die HttpClientFactory.Create-Methode, um benutzerdefinierte Handler zu HttpClient hinzuzufügen:
HttpClient client = HttpClientFactory.Create(new Handler1(), new Handler2(), new Handler3());
Nachrichtenhandler werden in der Reihenfolge aufgerufen, in der Sie sie an die Create-Methode übergeben. Da Handler geschachtelt sind, wird die Antwortnachricht in die andere Richtung verschoben. Das heißt, der letzte Handler ist der erste, der die Antwortnachricht erhält.