从asp.net core 2.0中的中间件获取HttpContext中的请求体

时间:2017-12-04 00:36:40

标签: c# asp.net-core-2.0

我有一个简单的中间件,它获取请求的主体并将其存储在一个字符串中。它正在读取流,但问题是它不会调用我的控制器,在我读取流并抛出错误之后调用

  

需要非空的请求正文

。以下是我的代码。

  public async Task Invoke(HttpContext httpContext)
            {
                var timer = Stopwatch.StartNew();
                ReadBodyFromHttpContext(httpContext);
                await _next(httpContext);
                timer.Stop();
            }

   private string ReadBodyFromHttpContext(HttpContext httpContext)
        {
           return await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
        }

5 个答案:

答案 0 :(得分:5)

You need to convert HttpContext.Request.Body from a forward only memmory stream to a seekable stream.

// Enable seeking
context.Request.EnableBuffering();
// Read the stream as text
var bodyAsText = await new System.IO.StreamReader(context.Request.Body).ReadToEndAsync();
// Set the position of the stream to 0 to enable rereading
context.Request.Body.Position = 0; 

答案 1 :(得分:2)

当涉及到捕获HTTP请求和/或响应的主体时,这不是一件轻而易举的事。在ASP .NET Core中,正文是一个流 - 一旦你使用它(在这种情况下用于记录),它就消失了,导致管道的其余部分无用。

价:http://www.palador.com/2017/05/24/logging-the-body-of-http-request-and-response-in-asp-net-core/

public async Task Invoke(HttpContext httpContext)
    {
        var timer = Stopwatch.StartNew();
        string bodyAsText = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
        var injectedRequestStream = new MemoryStream();
        var bytesToWrite = Encoding.UTF8.GetBytes(bodyAsText);
        injectedRequestStream.Write(bytesToWrite, 0, bytesToWrite.Length);
        injectedRequestStream.Seek(0, SeekOrigin.Begin);
        httpContext.Request.Body = injectedRequestStream;
        await _next(httpContext);

        timer.Stop();
    }

答案 2 :(得分:2)

这里很少有关键的事情:

  • 启用缓冲
  • Streamlier中的
  • 最后一个标志 leaveOpen
  • 重置请求正文流的位置
public void UseMyMiddleware(IApplicationBuilder app)
{
    app.Use(async (context, next) =>
    {
        context.Request.EnableBuffering();

        using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, false, 1024, true))
        {
            var body = await reader.ReadToEndAsync();

            context.Request.Body.Seek(0, SeekOrigin.Begin);
        }

        await next.Invoke();
    });
}

答案 3 :(得分:0)

using (var mem = new MemoryStream())
            using (var reader = new StreamReader(mem))
            {
                Request.Body.CopyTo(mem);
                var body = reader.ReadToEnd();

//and this you can reset the position of the stream.

                mem.Seek(0, SeekOrigin.Begin);
                body = reader.ReadToEnd();
            }

在这里您可以阅读其工作原理。 https://gunnarpeipman.com/aspnet-core-request-body/

答案 4 :(得分:0)

你可以试试这个

public async Task Invoke(HttpContext context)
{
  var request = context.Request;
  request.EnableBuffering();
  var buffer = new byte[Convert.ToInt32(request.ContentLength)];
  await request.Body.ReadAsync(buffer, 0, buffer.Length);
  var requestContent = Encoding.UTF8.GetString(buffer);
  request.Body.Position = 0;  //rewinding the stream to 0
}