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.
根据使用的托管的服务进行配置或直接使用异步读取方式。