Tôi đang nói ở đây dựa trên các bit mới nhất có sẵn trên Repeater của Codeplex ASP.NET Web Stack.
Đơn hàng được kiểm soát bởi người dùng và không có thứ tự tùy ý ở đây. Hãy để tôi giải thích:
Giả sử chúng tôi có hai trình xử lý tin nhắn: MyMessageHandler
và MyMessageHandler2
. Giả sử rằng chúng ta đăng ký cho họ như sau:
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());
}
gì bạn mong đợi ở đây là cho MyMessageHandler
để chạy đầu tiên và MyMessageHandler2
như một giây, nói cách khác FIFO.
Nếu chúng ta nhìn vào một chút dưới mui xe bên trong khuôn khổ, chúng ta sẽ thấy rằng Initialize
phương pháp của HttpServer
dụ là cách gọi CreatePipeline
phương pháp System.Net.Http.HttpClientFactory
(mà trước đây được biết đến như HttpPipelineFactory.Create
phương pháp như Ali chỉ định.) CreatePipeline
phương pháp chấp nhận hai tham số: HttpMessageHandler
và IEnumerable<DelegatingHandler>
. Phương pháp HttpServer.Initialize
đang chuyển thông số System.Web.Http.Dispatcher.HttpControllerDispatcher
cho thông số HttpMessageHandler
dưới dạng HttpMessageHandler
cuối cùng bên trong chuỗi và HttpConfiguration.MessageHandlers cho tham số IEnumerable<DelegatingHandler>
.
gì xảy ra bên trong phương pháp CreatePipeline
là rất thông minh 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;
}
Như bạn thấy, thông điệp xử lý trật tự bị đảo ngược và Matryoshka doll được tạo ra nhưng phải cẩn thận ở đây: đó là đảm bảo rằng HttpControllerDispatcher
là xử lý tin nhắn cuối cùng để chạy bên trong chuỗi.
Đối với vấn đề gọi hai lần, điều đó không thực sự là khá đúng. Trình xử lý tin nhắn sẽ không được gọi hai lần, phương pháp tiếp tục bạn sẽ cung cấp sẽ là, mặt khác. Nó là vào bạn để làm cho nó xảy ra. Nếu bạn cung cấp một cuộc gọi lại (nói cách khác là tiếp tục), trình xử lý tin nhắn của bạn sẽ được gọi trên đường trở về máy khách với thông điệp phản hồi được tạo ra mà bạn có thể chơi cùng.
Ví dụ, chúng ta hãy giả định rằng hai Sau đây là các xử lý tin nhắn, chúng tôi đã đăng ký ở trên:
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;
});
}
}
Và đây là một trong những khác:
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;
});
}
}
Như chúng ta đã cung cấp liên tục, chúng tôi các trình xử lý tin nhắn sẽ được gọi lại trên đường về cho khách hàng theo thứ tự FILO. Vì vậy, phương pháp tiếp tục bên trong MyMessageHandler2
sẽ là phương thức đầu tiên được gọi trên đường trở về và phương thức bên trong MyMessageHandler
sẽ là phương thức thứ hai.
Đó là những gì tôi nghĩ. Tôi không nghĩ rằng nó hỗ trợ các khái niệm của các nhà cung cấp hoặc. Giống như giao diện IFilterprovider trong MVC. – Darren
Tôi đồng ý rằng nội dung 'Async/ContinueWith' làm cho nó có cảm giác như búp bê làm tổ. Nó chính xác hơn, theo ý kiến của tôi, để mô tả chúng theo thứ tự, như MS. Mỗi trình xử lý được gọi hai lần - một lần trên đường vào (theo thứ tự được đăng ký) và một khi thoát ra theo thứ tự ngược lại. Sơ đồ thứ ba trong bài viết sau đây làm cho nó rõ ràng .. http://www.asp.net/web-api/overview/working-with-http/http-message-handlers – EBarr