Ich spreche hier auf der Grundlage der neuesten Bits, die auf Codeplex ASP.NET Web Stack Repo verfügbar sind.
Die Bestellung wird vom Benutzer gesteuert und es gibt keine willkürliche Reihenfolge hier. Lassen Sie mich erklären:
Nehmen wir an, wir haben zwei Nachrichtenhandler: MyMessageHandler
und MyMessageHandler2
. Unter der Annahme, dass wir registrieren sie wie folgt:
protected void Application_Start(object sender, EventArgs e) {
RouteConfig.RegisterRoutes(GlobalConfiguration.Configuration.Routes);
GlobalConfiguration.Configuration.MessageHandlers.Add(new MyMessageHandler());
GlobalConfiguration.Configuration.MessageHandlers.Add(new MyMessageHandler2());
}
Was man hier erwarten ist, dass die MyMessageHandler
zum ersten und MyMessageHandler2
als zweiten läuft, in anderen Worten FIFO.
Wenn wir ein wenig unter der Haube im Inneren des Rahmens betrachten, werden wir sehen, dass Initialize
Methode der HttpServer
Instanz CreatePipeline
Methode von System.Net.Http.HttpClientFactory
aufruft (die als HttpPipelineFactory.Create
Methode bisher bekannt als Ali angegeben.) CreatePipeline
Methode akzeptiert zwei Parameter: HttpMessageHandler
und IEnumerable<DelegatingHandler>
. HttpServer.Initialize
Methode wird System.Web.Http.Dispatcher.HttpControllerDispatcher
für HttpMessageHandler
Parameter als letzte HttpMessageHandler
innerhalb der Kette und HttpConfiguration.MessageHandlers für IEnumerable<DelegatingHandler>
Parameter übergeben.
Was im Inneren des CreatePipeline
Methode geschieht, ist IMO sehr clever:
public static HttpMessageHandler CreatePipeline(HttpMessageHandler innerHandler, IEnumerable<DelegatingHandler> handlers)
{
if (innerHandler == null)
{
throw Error.ArgumentNull("innerHandler");
}
if (handlers == null)
{
return innerHandler;
}
// Wire handlers up in reverse order starting with the inner handler
HttpMessageHandler pipeline = innerHandler;
IEnumerable<DelegatingHandler> reversedHandlers = handlers.Reverse();
foreach (DelegatingHandler handler in reversedHandlers)
{
if (handler == null)
{
throw Error.Argument("handlers", Properties.Resources.DelegatingHandlerArrayContainsNullItem, typeof(DelegatingHandler).Name);
}
if (handler.InnerHandler != null)
{
throw Error.Argument("handlers", Properties.Resources.DelegatingHandlerArrayHasNonNullInnerHandler, typeof(DelegatingHandler).Name, "InnerHandler", handler.GetType().Name);
}
handler.InnerHandler = pipeline;
pipeline = handler;
}
return pipeline;
}
Wie Sie sehen können, die Nachrichten-Handler Reihenfolge umgekehrt wird und die Matryoshka doll erstellt, aber hier vorsichtig sein: es ist sichergestellt, dass HttpControllerDispatcher
ist die Letzter Nachrichtenhandler, der innerhalb der Kette ausgeführt wird.
Wie für das zweimal aufrufen Problem ist es eigentlich nicht ganz richtig. Der Message-Handler wird nicht zweimal aufgerufen, sondern die von Ihnen bereitgestellte Fortsetzungs-Methode. Es liegt an Ihnen, dies zu ermöglichen. Wenn Sie einen Rückruf (mit anderen Worten eine Fortsetzung) bereitstellen, werden Ihre Nachrichtenhandler auf dem Weg zurück zum Client mit der generierten Antwortnachricht aufgerufen, mit der Sie spielen können.
Zum Beispiel, nehmen wir an, dass die beiden folgenden die Nachrichtenhandler sind wir oben registriert haben:
public class MyMessageHandler : DelegatingHandler {
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) {
//inspect request here
return base.SendAsync(request, cancellationToken).ContinueWith(task => {
//inspect the generated response
var response = task.Result;
return response;
});
}
}
Und das ist die andere:
public class MyMessageHandler2 : DelegatingHandler {
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) {
//inspect request here
return base.SendAsync(request, cancellationToken).ContinueWith(task => {
//inspect the generated response
var response = task.Result;
return response;
});
}
}
Wie wir Fortsetzung zur Verfügung gestellt haben, unsere Message-Handler werden auf dem Weg zurück zum Client in FILO-Reihenfolge zurückgerufen. Also wird die Fortsetzungsmethode innerhalb der MyMessageHandler2
die erste sein, die auf dem Weg zurück aufgerufen wird und die innerhalb der MyMessageHandler
wird die zweite sein.
Das habe ich mir gedacht. Ich glaube nicht, dass es auch das Konzept der Anbieter unterstützt. Wie die IFilterprovider-Schnittstelle in MVC. – Darren
Ich stimme zu, dass das 'Async/ContinueWith'-Material das Gefühl vermittelt, Puppen zu verschachteln. Es ist meiner Meinung nach genauer, sie wie bestellt zu beschreiben, wie MS es tut. Jeder Behandler wird zweimal aufgerufen - einmal auf dem Weg in der Reihenfolge und einmal in umgekehrter Reihenfolge. Das dritte Diagramm im folgenden Artikel macht es klar .. http://www.asp.net/web-api/overview/working-with-http/http-message-handlers – EBarr