Asp.net

倒帶請求正文流

  • February 15, 2014

我正在重新實現一個請求記錄器作為 Owin 中間件,它記錄所有傳入請求的請求 url 和正文。我能夠讀取正文,但如果我這樣做,我的控制器中的正文參數為空。

我猜它是空的,因為流位置在末尾,所以當它試圖反序列化主體時,沒有什麼可讀取的了。我在以前版本的 Web API 中遇到了類似的問題,但能夠將 Stream 位置設置回 0。這個特定的流會引發This stream does not support seek operations異常。

在最新版本的 Web API 2.0 中,我可以Request.HttpContent.ReadAsStringAsync()在我的請求記錄器中呼叫,並且主體仍會完整地到達控制器。

閱讀後如何回退流?

要麼

如何在不使用請求正文的情況下讀取它?

public class RequestLoggerMiddleware : OwinMiddleware
{
   public RequestLoggerMiddleware(OwinMiddleware next)
       : base(next)
   {
   }

   public override Task Invoke(IOwinContext context)
   {
       return Task.Run(() => {
           string body = new StreamReader(context.Request.Body).ReadToEnd();
           // log body

           context.Request.Body.Position = 0; // cannot set stream position back to 0
           Console.WriteLine(context.Request.Body.CanSeek); // prints false
           this.Next.Invoke(context);
       });
   }
}

public class SampleController : ApiController 
{
   public void Post(ModelClass body)
   {
       // body is now null if the middleware reads it
   }
}

剛剛找到一個解決方案。用包含數據的新流替換原始流。

   public override async Task Invoke(IOwinContext context)
   {
       return Task.Run(() => {
           string body = new StreamReader(context.Request.Body).ReadToEnd();
           // log body

           byte[] requestData = Encoding.UTF8.GetBytes(body);
           context.Request.Body = new MemoryStream(requestData);
           await this.Next.Invoke(context);
       });
   }

如果您正在處理大量數據,我相信 aFileStream也可以作為替代品。

引用自:https://stackoverflow.com/questions/21805362