.net core读取Response.Body

  • .net core读取Response.Body已关闭评论
  • 143 次浏览
  • A+
所属分类:.NET技术
摘要

报错,一般是在Request.Body处报NotSupportedException在自定义中间件中调用EnableBuffering()


读取请求体流的demo
        public static async Task<string> GetBodyForm(this HttpContext http)         {             var content = string.Empty;             var request = http.Request;              try             {                 request.Body.Position = 0;                  using var reader = new StreamReader(request.Body, Encoding.UTF8, leaveOpen: true);                 var strRequestBody = await reader.ReadToEndAsync();                 Console.WriteLine("ok");                 Console.WriteLine(strRequestBody == null ? "null" : strRequestBody);                 request.Body.Position = 0;             }             catch (Exception ex)             {                 Console.WriteLine("err");                 Console.WriteLine(ex);             }             return content;         } 

在ActionFilter中读取Request.Body

    public class ActionFilterTestA : ActionFilterAttribute     {         public override async void OnActionExecuting(ActionExecutingContext context)         {             Console.WriteLine("From Request Body---->");             Console.WriteLine(await context.HttpContext.GetBodyForm());             Console.WriteLine("From Request Body---->");         }     } 

报错,一般是在Request.Body处报NotSupportedException

解决方案

在自定义中间件中调用EnableBuffering()

    app.Use(async (context, next) =>     {         context.Request.EnableBuffering();         await next();     }); 

疑问

(移除以上正确方案代码) 为什么在ActionFilterTestA中调用context.HttpContext.Request.EnableBuffering();没有效果?(没有报错,但是内容为空字符串)

猜测

请求体流在ActionFilter之前,在自定义中间件之后被消耗。 中间件执行顺序

测试

    // 取消模型绑定     builder.Services.Configure<ApiBehaviorOptions>(options =>     {         options.SuppressInferBindingSourcesForParameters = true;     }); 

Request.Body的内容打印成功。

推论

绑定模型时会消耗掉请求体流。

其他资料

https://markb.uk/asp-net-core-read-raw-request-body-as-string.html

结语

推荐还是通过中间件调用EnableBuffering解决问题

注意事项:

  1. 避免关闭StreamReader导致关闭了Stream,可以通过leaveOpen: true解决
  2. 重置Position = 0