2012-04-20 38 views
5

Có thể kiểm soát thứ tự thực hiện của trình xử lý tin nhắn tùy chỉnh không?Trình xử lý tin nhắn API Web ASP.NET

Ví dụ, tôi có thể muốn trình xử lý ghi nhật ký thực hiện trước tiên, vì vậy tôi luôn ghi lại yêu cầu.

Ngoài việc thêm trình xử lý ghi nhật ký cuối cùng, tôi không thấy cách thực hiện điều này.

config.MessageHandlers.Add(new CustomHandlerOne()); 
config.MessageHandlers.Add(new CustomHandlerTwo()); 
config.MessageHandlers.Add(new LoggingHandler()); 

Trả lời

7

Thứ tự mà bạn đăng ký trình xử lý xác định thời điểm chúng được gọi nhưng như Aliostad chỉ ra rằng chúng hoạt động trong mô hình búp bê của Nga nên mô hình đầu tiên cũng được gọi là mẫu cuối cùng.

Bàn điều khiển đã đăng ký được gọi theo kiểu từ dưới lên trên đường dẫn đến và từ trên xuống trong phần gửi đi. Đó là, mục nhập cuối cùng được gọi là đầu tiên cho một thông điệp yêu cầu gửi đến nhưng được gọi cuối cùng cho một thông báo phản hồi gửi đi.

3

Không - AFAIK.

Đây là mô hình búp bê của Nga, với một trình xử lý bên trong cho đến khi người cuối cùng thực hiện công việc. Này được xây dựng trong lớp nội HttpPipelineFactory (bạn có thể xem mã nguồn khi nó được phát hành):

public static HttpMessageHandler Create(IEnumerable<DelegatingHandler> handlers, HttpMessageHandler innerChannel) 
    { 
     if (innerChannel == null) 
     { 
      throw Error.ArgumentNull("innerChannel"); 
     } 

     if (handlers == null) 
     { 
      return innerChannel; 
     } 

     // Wire handlers up 
     HttpMessageHandler pipeline = innerChannel; 
     foreach (DelegatingHandler handler in handlers) 
     { 
      if (handler == null) 
      { 
       throw Error.Argument("handlers", SRResources.DelegatingHandlerArrayContainsNullItem, typeof(DelegatingHandler).Name); 
      } 

      if (handler.InnerHandler != null) 
      { 
       throw Error.Argument("handlers", SRResources.DelegatingHandlerArrayHasNonNullInnerHandler, typeof(DelegatingHandler).Name, "InnerHandler", handler.GetType().Name); 
      } 

      handler.InnerHandler = pipeline; 
      pipeline = handler; 
     } 

     return pipeline; 
    } 

Vì vậy, những gì các mã lệnh thực hiện là để có được một danh sách và sau đó biến nó thành một Nga Doll.

+0

Đó 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

+0

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

3

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: MyMessageHandlerMyMessageHandler2. 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ố: HttpMessageHandlerIEnumerable<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.

Các vấn đề liên quan