2017-06-16 96 views
0

我们在IIS中托管的ASP.NET Web API 2项目中使用Owin中间件。ASP.NET Web API HttpContext响应在IOwinContext响应之前发回

我目前遇到了一个奇怪的现象,即IOwinContext.Response.Body没有被写入,实际上,即使在唤醒Next.Invoke()后在中间件中设置了中断点, ,即使我还没有继续,响应已经被发送回服务器。

当我查看IOwinContext上的响应主体时,它是空的。但是,我可以从HttpContext.Response.Filter获得响应。当我使用HttpContext并击中断点时,那么响应不会被发回,直到我继续。以下是我们的Startup.cs类中使用的当前配置方法。

public async void Configuration(IAppBuilder app) 
{ 
    try 
    { 
     // Global Config 
     var config = GlobalConfiguration.Configuration; 

     // configure dependency injection 
     UnityConfig.RegisterComponents(); 

     // configure log for net 
     log4net.Config.XmlConfigurator.Configure(); 

     // turn around all requests right here 
     app.Use(async (context, next) => 
     { 
      if (context.Request.Path.ToString() == "/") 
      { 
       string text = "UP"; 
       context.Response.StatusCode = 200; 
       context.Response.ReasonPhrase = text; 
       await context.Response.WriteAsync(text); 
       return; 
      } 

      await next.Invoke(); 
     }); 

     // Handle exceptions in the OWIN layer here 
     app.UseUncaughtExceptionHandler(); 

     // add cors headers 
     app.Use(async (context, next) => { }); 

     // some UI stuff 
     app.Use(async (context, next) => { }); 

     // Log Request Metrics 
     app.UseLogRequestMetrics(); 

     // Evaluate Partner Key 
     app.MapWhen(context => Regex.IsMatch(context.Request.Uri.PathAndQuery.ToLower(), @"/api"), newApp => 
     { 
#if !DEBUG 
      newApp.Use<Middleware1>(); 
#endif 
      newApp.Use<Middleware2>(); 

      newApp.Use<Middleware3>(); // On the response path back, the IOwinResponse body is already empty 
     }); 

     WebApiConfig.Register(config); 

     app.UseWebApi(config); // It seems like I'm losing the response in here, but I don't really know 

     config.EnsureInitialized(); 

     // Configure object mapping 
     AutoMapperConfig.Configure(); 
    } 
    catch (Exception ex) 
    { 
     await LogForNetErrorLogger.LogError(ex); 
    } 
} 

我敢肯定我的中间件搞砸,但反应已经消失了它会回到我的第一个中间件(Middleware3)后等待Next.Invoke()

任何之前洞察力或思想挑衅将不胜感激。另外,如果这些信息不够,请告诉我。

回答

0

因此,正如在我上面的帖子中,我想,问题是HttpResponse在IOwinResponse之前被发回。当你使用它app.Map()分支中间件

app.MapWhen(context => Regex.IsMatch(context.Request.Uri.PathAndQuery.ToLower(), @"/api"), newApp => 
{ 
#if !DEBUG 
    newApp.Use<Middleware1>(); 
#endif 
    newApp.Use<Middleware2>(); 

    newApp.Use<Middleware3>(); 
}); 

:事实证明,我完全忽略了映射部分。所以,如果路径匹配“/ api”,它会分支。但是,它还在使用app.UseWebApi()组件,所以这就是为什么我有两个不同的响应,以及为什么我期望的响应没有写入Middleware3组件的IOwinContext。 我固定它通过去除app.MapWhen()方法,从这个改变它:

app.MapWhen(context => Regex.IsMatch(context.Request.Uri.PathAndQuery.ToLower(), @"/site"), newApp => 
{ 
#if !DEBUG 
    newApp.Use<Middleware1>(); 
#endif 
    newApp.Use<Middleware2>(); 

    newApp.Use<Middleware3>(); // On the response path back, the IOwinResponse body is already empty 
}); 

这样:

#if !DEBUG 
newApp.Use<Middleware1>(); 
#endif 
newApp.Use<Middleware2>(); 

newApp.Use<Middleware3>(); 

并把这段代码在中间件组件Middleware1Middleware2的开始,Middleware3

public override async Task Invoke(IOwinContext context) 
{ 
    if (!context.Request.Path.ToString().StartsWith("/api/")) 
    { 
     await Next.Invoke(context); 

     return; 
    } 

    // stuff I want to run if the above doesn't match 
    await Next.Invoke(context); 

    ... 
} 

那么,至少修复很简单,即使它花了我三几周才能找到它。如果你想了解IAppBuilder.Map的扩展方法,这里有一些文档https://msdn.microsoft.com/en-us/library/owin.mapwhenextensions.mapwhen(v=vs.113).aspx