sto parlando qui in base alle punte più recenti che sono disponibili su Codeplex ASP.NET Web Stack pronti contro termine.
L'ordine è controllato dall'utente e non vi è alcun ordine arbitrario qui. Lasciatemi spiegare:
Diciamo che abbiamo due gestori di messaggi: MyMessageHandler
e MyMessageHandler2
. Partendo dal presupposto che noi li registriamo come di seguito:
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());
}
Cosa vi aspettate qui è per la MyMessageHandler
a correre prima e MyMessageHandler2
come secondo, in altre parole FIFO.
Se guardiamo un po 'sotto il cofano all'interno del quadro, vedremo che Initialize
metodo dell'istanza HttpServer
invoca CreatePipeline
metodo System.Net.Http.HttpClientFactory
(che in precedenza era conosciuto come HttpPipelineFactory.Create
Metodo Ali indicato.) CreatePipeline
metodo accetta due parametri: HttpMessageHandler
e IEnumerable<DelegatingHandler>
. Il metodo HttpServer.Initialize
sta passando System.Web.Http.Dispatcher.HttpControllerDispatcher
per il parametro HttpMessageHandler
come ultimo HttpMessageHandler
all'interno della catena e HttpConfiguration.MessageHandlers per il parametro IEnumerable<DelegatingHandler>
.
Cosa accade all'interno del metodo CreatePipeline
è molto intelligente IMO:
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;
}
Come si può vedere, l'ordine gestore di messaggi è invertito e il Matryoshka doll è creato ma attenzione qui: è garantito che HttpControllerDispatcher
è la l'ultimo gestore di messaggi da eseguire all'interno della catena.
Per quanto riguarda il doppio problema di chiamata, in realtà non è del tutto vero. Il gestore di messaggi non verrà chiamato due volte, il metodo di continuazione che fornirai sarà, d'altra parte. Spetta a te farlo accadere. Se fornisci un callback (in altre parole continuazione), i gestori dei messaggi verranno richiamati al cliente con il messaggio di risposta generato con cui puoi giocare.
Per esempio, supponiamo che il seguente due sono i gestori di messaggi che abbiamo registrato in precedenza:
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;
});
}
}
E questa è l'altra:
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;
});
}
}
Come abbiamo fornito la continuazione, la nostra i gestori dei messaggi saranno richiamati sulla via del ritorno al cliente in ordine FILO. Quindi, il metodo di continuazione all'interno di MyMessageHandler2
sarà il primo a essere richiamato al ritorno e quello all'interno di MyMessageHandler
sarà il secondo.
Questo è quello che pensavo. Non penso nemmeno che supporti il concetto di provider. Come l'interfaccia IFilterprovider in MVC. – Darren
Sono d'accordo che il materiale 'Async/ContinueWith' lo fa sentire come un nido di bambole. È più accurato, secondo me, descriverli come ordinati, come fa MS. Ogni gestore viene chiamato due volte - una volta in entrata (nell'ordine registrato) e una volta in uscita in ordine inverso. Il terzo diagramma nel seguente articolo chiarisce ... http://www.asp.net/web-api/overview/working-with-http/http-message-handlers – EBarr