我有以下中间件代码:
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方法结束后严格返回。我错过了什么吗?
答案 0 :(得分:1)
在Owin / Katana中,当中间件在IOwinContext
await Next.Invoke()
对象上调用{{1}}时,响应正文(当然还有标题)会被发送到客户端}}
这意味着,如果您的下一个中间件正在编写响应正文,则客户端将在服务器端代码从{{1}}调用返回之前收到该响应正文。
Owin的设计方式,取决于Response流可能只在一个请求/响应生命周期中写入一次这一事实。
查看您的代码,我无法在此类行为中看到任何重大问题,因为您只是在将响应写入流后读取响应标头,因此不会更改它。
相反,如果您需要更改下一个中间件写入的响应,或者您需要在之后编写响应执行更多逻辑服务器端,那么您唯一的选择就是缓冲响应主体进入内存流,然后在准备好时将其复制到真实的响应流(previous post)。
我已经成功地在不同的用例(但共享相同的概念)中测试了这种方法,您可能会发现这个答案:as per this answer