2016-04-27 2 views
0

У меня есть следующий код: промежуточногоМожет ли промежуточное ПО Owin возвращать ответ раньше, чем метод Invoke возвращается?

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(); 
      } 
     } 
    } 
} 

Иногда мы наблюдаем, что возвращает ответ на клиент перед вызовом uow.Commit() через стельку. Например, мы поставили точку останова на uow.Commit, и мы видим, что ответ возвращается клиенту, несмотря на то, что мы находимся в ожидании точки останова. Это несколько неожиданно. Я думаю, что ответ будет строго возвращаться после завершения метода Invoke. Я что-то упускаю?

ответ

1

В Owin/Katana тело ответа (и, конечно же, заголовки) отправляется клиенту в тот момент, когда промежуточный слой вызывает Write на Response объекте IOwinContext.

Это означает, что если ваше следующее промежуточное программное обеспечение написало тело ответа, которое ваш клиент получит, прежде чем ваш серверный код вернется с вызова на await Next.Invoke().

Именно так разработан Owin и зависит от того, что поток Response может быть написан только один раз за один жизненный цикл Request/Response.

Если вы посмотрите на свой код, я не вижу никакой серьезной проблемы в таком поведении, потому что вы просто читаете заголовки ответов после того, как ответ записывается в поток и, следовательно, не меняет его.

Если вам требуется изменить ответ, написанный вашим следующим промежуточным программным обеспечением, или вам строго нужно написать ответ после того, как вы выполните дальнейшую логическую серверную сторону, тогда ваш единственный вариант - буферизация тела ответа в поток памяти, а затем скопируйте его в поток реального ответа (as per this answer), когда вы будете готовы.

Я успешно протестировал этот подход в другом случае использования (но разделяя ту же концепцию), которые вы можете найти, глядя на этот ответ: https://stackoverflow.com/a/36755639/3670737

Ссылка:
Changing the response object from OWIN Middleware

+0

Позвольте мне кое-что прояснить. Я наблюдаю, что ответ «завершен», прежде чем мой метод owin вернется. Так вы говорите, что это по дизайну? –

+1

Да, ответ отправляется в тот же самый момент, когда промежуточное программное обеспечение вызывает «Write», и это, я полагаю, происходит внутри вашего промежуточного программного обеспечения * next * (например, Web API). Вот почему вы видите ответ HTTP в скрипде, прежде чем ваш метод вернется. –

+0

Да, видимо, вы правы. В моем случае я просто хотел подключиться к моменту отправки ответа. Поэтому обратный вызов OnSendingHeaders - это то, что я хочу. Ваше сообщение привело меня к правильному направлению. –