首页 > 解决方案 > ASP.NET Core:记录所有请求(两次读取正文) EnableRewind 不适用于 [FromBody] 属性

问题描述

我正在关注这篇文章如何记录所有请求。

但是这段代码:

public async Task Invoke(HttpContext context)
{
    await this.LogRequest(context.Request);

    await this._next(context);
}

private async Task LogRequest(HttpRequest request)
{
    var body = request.Body;
    request.EnableRewind();

    var buffer = new byte[Convert.ToInt32(request.ContentLength)];
    await request.Body.ReadAsync(buffer, 0, buffer.Length);
    request.Body.Seek(0, SeekOrigin.Begin);
    var bodyAsText = Encoding.UTF8.GetString(buffer);
    request.Body = body;
}

不起作用,因为我得到

"A non-empty request body is required."

[ApiController]在具有属性的控制器中

[HttpPut("MyMethod")]
public async Task<ActionResult<MyModel>> MyMethod([FromBody]MyArgs model)
{
    //...
}

我正在尝试做各种组合

    string bodyAsText = null;
    if (request.ContentLength > 0)
    {
        var body = request.Body;
        request.EnableRewind();

        using (var streamReader = new StreamReader(request.Body, Encoding.UTF8))
        {
            bodyAsText = await streamReader.ReadToEndAsync();
            request.Body.Seek(0, SeekOrigin.Begin);
        }
        request.Body = body;
    }

但没有任何效果。我在这里想念什么?在SO上有一些类似解决方案的答案,但我不明白为什么它在我的情况下不起作用。

如果我评论阅读正文的代码,它可以工作。

标签: asp.netasp.net-coreasp.net-core-2.1

解决方案


我正在等待 Tseng 发布答案,因为他已经在评论中指出了我的问题和解决方案。但由于他没有这样做,我会根据评论和调试经验尝试回答。

正如曾提到EnableRewind过的那样var body = request.Body;

这段代码:

if (request.ContentLength > 0)
{
    request.EnableRewind();
    var body = request.Body;

    using (var streamReader = new StreamReader(request.Body, Encoding.UTF8))
    {
         bodyAsText = await streamReader.ReadToEndAsync();
         request.Body.Seek(0, SeekOrigin.Begin);
    }
    request.Body = body;
}

抛出错误:

无法访问已处置的对象。对象名称:'FileBufferingReadStream'。

排队await this._next(context);

工作代码是:

if (request.ContentLength > 0)
{
    request.EnableRewind();
    var body = request.Body;

    var buffer = new byte[Convert.ToInt32(request.ContentLength)];
    await request.Body.ReadAsync(buffer, 0, buffer.Length);
    request.Body.Seek(0, SeekOrigin.Begin);
    bodyAsText = Encoding.UTF8.GetString(buffer);
    request.Body = body;
}

谢谢@Tseng。


推荐阅读