Owin Middleware可以在Invoke方法返回之前返回响应吗?

时间:2016-04-27 08:26:12

标签: asp.net-web-api owin middleware

我有以下中间件代码:

public class UoWMiddleware : OwinMiddleware
{
    readonly IUoW uow;
    public UoWMiddleware(OwinMiddleware next, IUoW uow) : base(next)
    {
        this.uow = uow;
    }

    public override async Task Invoke(IOwinContext context)
    {
        try
        {
            await Next.Invoke(context);
        }
        catch
        {
            uow.RollBack();
            throw;
        }
        finally
        {
            if (uow.Status == Base.SharedDomain.UoWStatus.Running)
            {
                var response = context.Response;
                if (response.StatusCode < 400)
                {
                    Thread.Sleep(1000);
                    uow.Commit();
                }
                else
                    uow.RollBack();
            }
        }
    }
}

有时我们会在通过fiddler调用uow.Commit()之前观察到响应返回给客户端。例如,我们给uow.Commit设置了一个断点,我们看到响应被返回给客户端,尽管我们正在等待断点。这有些出乎意料。我认为响应将在Invoke方法结束后严格返回。我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

在Owin / Katana中,当中间件在IOwinContext await Next.Invoke()对象上调用{{1}}时,响应正文(当然还有标题)会被发送到客户端}}

这意味着,如果您的下一个中间件正在编写响应正文,则客户端将在服务器端代码从{{1}}调用返回之前收到该响应正文。

Owin的设计方式,取决于Response流可能只在一个请求/响应生命周期中写入一次这一事实。

查看您的代码,我无法在此类行为中看到任何重大问题,因为您只是在将响应写入流后读取响应标头,因此不会更改它。

相反,如果您需要更改下一个中间件写入的响应,或者您需要在之后编写响应执行更多逻辑服务器端,那么您唯一的选择就是缓冲响应主体进入内存流,然后在准备好时将其复制到真实的响应流(previous post)。

我已经成功地在不同的用例(但共享相同的概念)中测试了这种方法,您可能会发现这个答案:as per this answer

参考:
https://stackoverflow.com/a/36755639/3670737