ASP.NET Core 中的 Request.Body 雖然是一個 Stream ,但它是一個與眾不同的 Stream —— 不允許 Request.Body.Position=0 ,這就意味着只能讀取一次,要想多次讀取,需要借助 MemoryStream ,詳見博問 asp.net core中2次讀取Request.Body的問題
using (var buffer = new MemoryStream()) { Request.Body.CopyTo(buffer); buffer.Position = 0; buffer.CopyTo(writer.BaseStream); Console.WriteLine("Request.Body:"); buffer.Position = 0; buffer.CopyTo(Console.OpenStandardOutput()); }
昨天讀了博文 Reading request body in ASP.NET Core 之后得知在 ASP.NET Core 2.0 中已經針對這個問題提供了解決方法 —— EnableRewind() ,只要啟用倒帶功能,就可以讓 Request.Body 回歸正常 Stream 。
使用非常簡單,引用命名空間 Microsoft.AspNetCore.Http.Internal ,調用方法 Request.EnableRewind() 即可,下面我們用簡單的示例代碼體驗一下
public class HomeController : Controller { public IActionResult Index() { Request.EnableRewind(); Console.WriteLine("Request.Body1:"); Request.Body.Position = 0; Request.Body.CopyTo(Console.OpenStandardOutput()); Console.WriteLine(); Console.WriteLine("Request.Body2:"); Request.Body.Position = 0; Request.Body.CopyTo(Console.OpenStandardOutput()); Console.WriteLine(); return Ok(); } }
啟動上面的 ASP.NET Core 站點,然后用 curl 命令發出請求
curl -X POST -d 'Hello World' localhost:5000
控制台就會輸出期望的結果
Request.Body1: Hello World Request.Body2: Hello World
EnableRewind 有 2 個參數 bufferThreshold 與 bufferLimit 。 bufferThreshold 設置的是 Request.Body 最大緩存字節數(默認是30K),超出這個閾值的字節會被寫入磁盤;bufferLimit 設置的是 Request.Body 允許的最大字節數(默認值是null),超出這個限制,就會拋出異常 System.IO.IOException 。
EnableRewind 的實現源代碼見 BufferingHelper.cs
更新:.NET Core 3.0 中 EnableRewind 被改名為 EnableBuffering 。
