C# ASP.NET Web API HttpContext响应在IOwinContext响应之前发送回

C# ASP.NET Web API HttpContext响应在IOwinContext响应之前发送回,c#,asp.net,iis,asp.net-web-api2,owin-middleware,C#,Asp.net,Iis,Asp.net Web Api2,Owin Middleware,我们正在IIS中托管的ASP.NET Web API 2项目中使用Owin中间件 我目前遇到一个奇怪的现象,IOwinContext.Response.Body没有被写入,事实上,即使我在唤醒Next.Invoke()之后在中间件中设置了一个断点,并且它被命中,响应已经被发送回服务器,即使我还没有继续 当我查看IOwinContext上的响应主体时,它是空的。但是,我可以从HttpContext.response.Filter获得响应。当我使用HttpContext并达到断点时,在我继续之前不会

我们正在IIS中托管的ASP.NET Web API 2项目中使用Owin中间件

我目前遇到一个奇怪的现象,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);
    }
}
公共异步无效配置(IAppBuilder应用程序)
{
尝试
{
//全局配置
var config=GlobalConfiguration.Configuration;
//配置依赖项注入
UnityConfig.RegisterComponents();
//为网络配置日志
log4net.Config.XmlConfigurator.Configure();
//把所有的请求都转到这里
应用程序使用(异步(上下文,下一步)=>
{
if(context.Request.Path.ToString()=“/”)
{
字符串text=“UP”;
context.Response.StatusCode=200;
context.Response.ReasonPhrase=文本;
wait context.Response.WriteAsync(text);
返回;
}
等待next.Invoke();
});
//在此处理OWIN层中的异常
app.UseUncaughtExceptionHandler();
//添加cors标题
使用(异步(上下文,下一步)=>{});
//一些用户界面的东西
使用(异步(上下文,下一步)=>{});
//日志请求度量
app.UseLogRequestMetrics();
//评估合作伙伴密钥
app.MapWhen(context=>Regex.IsMatch(context.Request.Uri.PathAndQuery.ToLower(),@/api),newApp=>
{
#如果!调试
newApp.Use();
#恩迪夫
newApp.Use();
newApp.Use();//在返回的响应路径上,IOwinResponse正文已为空
});
WebApiConfig.Register(配置);
app.UseWebApi(config);//这里的响应好像丢失了,但我真的不知道
config.EnsureInitialized();
//配置对象映射
AutoMapperConfig.Configure();
}
捕获(例外情况除外)
{
等待LogForNetErrorLogger.LogError(ex);
}
}
我很确定我的中间件是乱七八糟的,但是在等待Next.Invoke()之后返回到我的第一个中间件(Middleware3)之前,响应已经消失了


如有任何见解或想法,将不胜感激。另外,如果这还不够,请让我知道。

因此,正如我在上面的帖子中所说的,我认为问题在于,在IOwinResponse发出之前,HttpResponse被发回了。事实证明,我完全忽略了映射部分:

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

    newApp.Use<Middleware3>();
});
为此:

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

newApp.Use<Middleware3>();
嗯,至少修复很简单,即使我花了三个星期才找到。如果您想了解IAppBuilder.MapWhen扩展方法,下面是一些文档

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

newApp.Use<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);

    ...
}