https://blog.csdn.net/diamondsos/article/details/103439530
.net core3.0中啟動倒帶方式由Request.EnableRewind()變為了 request.EnableBuffering(); 但是今天在過濾器中使用此方法時出現異常。原代碼已經修改,下面以新建的項目做示例記錄一下問題。新建WebApi項目,測試過濾器代碼如下:
public class TestFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
var request = context.HttpContext.Request;
//啟動倒帶方式
request.EnableBuffering();
if (request.Method.ToLower().Equals("post"))
{
request.Body.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(request.Body, Encoding.UTF8))
{
var param = reader.ReadToEnd();
}
request.Body.Seek(0, SeekOrigin.Begin);
}
}
public override void OnActionExecuted(ActionExecutedContext context)
{
base.OnActionExecuted(context);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
啟動項目站點,發送post請求
curl -X POST "http://localhost:5000/WeatherForecast" -H "accept: text/plain" -H "Content-Type: application/json" -d "{\"name\":\"string\",\"age\":\"string\"}"
- 1
調試結果:
通過分析此時body發現stream長度為0
在請求到達過濾器時Steam已經被讀取了,此時我們在過濾器中使用EnableBuffering並沒有起作用,產生這種問題的具體原因我現在還沒搞清楚。解決這個問題有個折中方案,在站點啟動時設置以插入中間件的方式啟用EnableBuffering,以達到在全局多次讀取的目的。代碼如下:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
.....
app.Use(next => context =>
{
context.Request.EnableBuffering();
return next(context);
});
......
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
修改過濾器中代碼:
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
var request = context.HttpContext.Request;
if (request.Method.ToLower().Equals("post"))
{
request.Body.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(request.Body, Encoding.UTF8))
{
var param = reader.ReadToEnd();
}
request.Body.Seek(0, SeekOrigin.Begin);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
再次請求即可讀取到body數據,結果如下:
此外,3.0中默認禁用了AllowSynchronousIO,同步讀取body的方式需要ConfigureServices中配置允許同步讀取IO流,否則可能會拋出異常 Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
根據使用的托管的服務進行配置或直接使用異步讀取方式。