2012-08-17 109 views
9

根據我的last post我能夠使批處理工作......直到某個點。除了註冊的路由特定的處理程序我也有2個委託處理程序webapi批處理和委託處理程序

  1. 驗證用戶
  2. 登錄

批量處理程序經歷的處理程序委託認證所述用戶和登錄請求。當messagehandlerinvoker開始發送子/請求時,會拋出以下異常。

System.ArgumentException was unhandled by user code 
    HResult=-2147024809 
    Message=The 'DelegatingHandler' list is invalid because the property 'InnerHandler' of 'AuthenticationMessageHandler' is not null. 
Parameter name: handlers 
    Source=System.Net.Http.Formatting 
    ParamName=handlers 
    StackTrace: 
     at System.Net.Http.HttpClientFactory.CreatePipeline(HttpMessageHandler innerHandler, IEnumerable`1 handlers) 
     at System.Web.Http.HttpServer.Initialize() 
     at System.Web.Http.HttpServer.<EnsureInitialized>b__3() 
     at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory) 
     at System.Threading.LazyInitializer.EnsureInitialized[T](T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory) 
     at System.Web.Http.HttpServer.EnsureInitialized() 
     at System.Web.Http.HttpServer.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
     at System.Net.Http.HttpMessageInvoker.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
     at RoutingRequest.Service.Startup.BatchMessageHandler.<>c__DisplayClassd.<PrcoessRequest>b__b(Task`1 m) in C:\CEI\Clients\Footlocker.com\FL - Vendor Routing Portal\source\RoutingRequest.Service\Startup\BatchMessageHandler.cs:line 45 
     at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke() 
     at System.Threading.Tasks.Task.Execute() 
    InnerException: 

有我缺少一個配置選項,或者我需要繞過委託處理程序?

編輯 這裏是我的身份驗證處理程序。

public class AuthenticationMessageHandler 
    : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     SetCurrentUser(request); 
     return base.SendAsync(request, cancellationToken); 
    } 

    private void SetCurrentUser(HttpRequestMessage request) 
    { 
     var values = new List<string>().AsEnumerable(); 
     if (request.Headers.TryGetValues("routingrequest-username", out values) == false) return; 

     var username = values.First(); 

     var user = Membership.GetUser(username, true); 
     if (user == null) 
     { 
      var message = string.Format("membership information for '{0}' could not be found.", username); 
      throw new HttpRequestException(message); 
     } 

     var roles = Roles.GetRolesForUser(username); 

     Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(user.UserName), roles); 
    } 
} 

基於Kiran的回答分類的httpserver修復了一個問題,並引入了另一個問題。我的角色提供者正在得到一個空引用異常。現在看看。

+0

你可以發佈您的身份驗證處理程序代碼和初始化代碼? – 2012-08-17 16:50:58

回答

12

該博客後正確地識別問題,但有一個簡單的解決方案,如果您使用的是StartupOwinStartup類配置OWIN:

變化從 UseWebApi(this IAppBuilder builder, HttpConfiguration configuration); 的OWIN配置調用 UseWebApi(this IAppBuilder builder, HttpServer httpServer); 讓您的批量處理程序OWIN管道使用相同的HttpServer實例。

這樣做的根本原因是,許多的配料物品/例子(例如http://bradwilson.typepad.com/blog/2012/06/batching-handler-for-web-api.html),用於配料中除了主HttpServer被處理HTTP請求創建一個新的HttpServer;並且兩個HttpServer s都使用相同的HttpConfiguration

當每個HttpServer初始化它接收請求在第一時間,它創建通過反轉所有配置的委託處理程序(例如跟蹤處理程序,或其它代理型處理程序),以及終止所述管線處理的管道(在HttpClientFactory.CreatePipeline)使用Web API調度程序。

如果您沒有配置任何委派處理程序,那麼此問題不會引起您 - 您可以使用2 HttpServer對象使用相同的HttpConfiguration

但是,如果您有任何委託處理程序明確或隱含配置(例如由enabling Web API Tracing),則Web API不能建立第二個管道 - 的委託處理程序已鏈接在第一管道 - 這將引發異常的第一個請求到第二個HttpServer

這個例外應該更清楚地說明發生了什麼。更好的是,這個問題甚至不應該成爲可能 - 配置應該是配置,而不是單個處理程序。該配置可能是委託處理程序的工廠。但是,我離題...

儘管這一問題是有點難以弄清楚,有一個非常簡單的解決辦法:

  1. 如果您使用OWIN,傳遞相同HttpServer如您在批量處理程序使用通過UseWebApi(this IAppBuilder builder, HttpServer httpServer);
  2. 的OWIN管道如果您正在使用IIS +網絡API(無OWIN啓動類),通過GlobalConfiguration.DefaultServer到您的批處理處理程序,以避免產生新的HttpServer

下面是一個例子OWIN啓動類創建一個HttpServer並將其傳遞給批處理程序和Web API。此示例使用OData批處理程序:

[assembly: OwinStartup(typeof(My.Web.OwinStartup))] 
namespace My.Web 
{ 

    /// <summary> 
    /// OWIN webapp configuration. 
    /// </summary> 
    public sealed class OwinStartup 
    { 

     /// <summary> 
     /// Configure all the OWIN modules that participate in each request. 
     /// </summary> 
     /// <param name="app">The OWIN appBuilder</param> 
     public void Configuration(IAppBuilder app) 
     { 
      HttpConfiguration webApiConfig = new HttpConfiguration(); 
      webApiConfig.MapHttpAttributeRoutes(); 

      HttpServer webApiServer = new HttpServer(webApiConfig); 

      // Configure batch handler 
      var batchHandler = new DefaultODataBatchHandler(webApiServer); 
      webApiConfig.Routes.MapODataServiceRoute("ODataRoute", 
                "odata", 
                BuildEdmModel(), 
                new DefaultODataPathHandler(), 
                ODataRoutingConventions.CreateDefault(), 
                batchHandler); 

      app.UseWebApi(webApiServer); 
     } 

     private EdmModel BuildEdmModel() 
     { 
      // ... 
     } 
    } 

} 
+1

有趣!在startup.cs的默認'公共無效配置(IAppBuilder應用程序)'(默認配置Cors&co的OWIN)中,我將如何獲得httpServer?謝謝 – 2015-07-20 21:03:23

+1

爲我的答案增加了一個例子。 – crimbo 2015-07-22 18:22:21

+0

在'UseWebApi'後面調用'IOC'初始化,否則你可能會收到錯誤'無法重用'ApiController'實例。'ApiController'必須根據傳入的消息構造。檢查你的自定義'IHttpControllerActivator'並確保它不會製造同樣的例子「。在我的情況下,他們是'UseAutofacMiddleware'和'UseAutofacWebApi' – 2016-05-25 12:07:56

1

我有這個錯誤沒有批處理。我做了我自己的HttpClientFactory,它也需要HandlerFactory,也是我自己的。

它調用構造函數中的HandlerFactory.Create()方法和存儲,這方面取得的處理程序。

這些傳遞給每當工廠需要做出新的HttpClient方法System.Net.Http.HttpClientFactory.Create(...)

但它是那麼只有單個呼叫好,因爲處理程序本身是通過讓他們在這意味着他們不能重複使用的狀態.NET代碼突變。

我改變了我的構造函數,以便它不創建每次處理了前面,但。現在起作用了。