ASP.NET 核心 : log all requests (reading body twice) EnableRewind not working for [FromBody] attribute

标签 asp.net asp.net-core asp.net-core-2.1

我正在关注 this post如何记录所有请求。

但是这段代码:

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] 属性的 Controller 中

[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 上有一些类似解决方案的答案,但我不明白为什么它在我的情况下不起作用。

如果我注释阅读正文的代码,它会起作用。

最佳答案

我在等 Tseng 发布答案,因为他已经在评论中指出了我的问题和解决方案。不过他没做,我会尽量根据评论和调试经验来回答。

正如 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;
}

抛出错误:

Cannot access a disposed object. Object name: '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。

关于ASP.NET 核心 : log all requests (reading body twice) EnableRewind not working for [FromBody] attribute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52931906/

相关文章:

asp.net - 使用 WCAT 负载测试解决 ValidateAntiForgeryTokenAttribute()

c# - 你调用的对象是空的? (异常错误~ASP.NET MVC)

.net - 如何在 vb - asp.net 中拆分带有多字符分隔符的字符串?

c# - 如何为 Azure 应用服务上的每个请求设置自定义 header ?

javascript - 为什么我的 $.ajax() JSON 数据会像这样发回服务器?

c# - 在类中从 appsetting.json 获取值

asp.net-core-2.1 - 如何在 asp.net Core 2.1.1 中为 IdentityUser 创建自定义字段

c# - ASP.NET Core 中具有托管服务的并行排队后台任务

docker - 如何使用Jenkinsfile在子目录中构建Dockerfile

asp.net - IIS Express applicationhost.config - 身份验证错误