无法访问 ASP.NET Core 3.1 异常处理程序中的 HTTP 请求正文内容

Unable to access HTTP request body content in ASP.NET Core 3.1 exception handler

似乎 .NET Core 3.1 使得在异常后访问原始 HTTP 请求正文变得非常困难

问题的核心似乎是您无法将流倒回到开头以便可以阅读整个内容

在下面的示例中,输出是:

Content-Length: 19
Can't rewind body stream. Specified method is not supported.
Body:

如果我删除 Seek,也不例外,但是 body 当然会返回一个空字符串,因为它已经被处理过

围绕管道 API 有一些新管道涉及 Request.BodyReader,但它们遇到同样的问题。

发生异常后,我需要做的就是将完整的请求转储到包含正文内容的日志文件中。应该不会这么难吧?

   public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {            
        app.UseExceptionHandler(errorApp =>
        {
            errorApp.Run(async context =>
            {
                Console.WriteLine("Content-Length: " + context.Request.Headers["Content-Length"]);
                string tmp;
                try
                {
                    context.Request.Body.Seek(0, SeekOrigin.Begin);
                }
                catch(Exception ex)
                {
                    Console.WriteLine("Can't rewind body stream. " + ex.Message);
                }
                using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8))
                {

                    tmp = await reader.ReadToEndAsync();
                }

                Console.WriteLine("Body: " + tmp);

            });
        });

        app.UseStaticFiles();
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapDefaultControllerRoute();
        });
    }

请查看answer by Stephen Wilkinson

将以下内容添加到您的代码中:

Startup.cs

app.Use((context, next) =>
{
    context.Request.EnableBuffering(); // calls EnableRewind() `https://github.com/dotnet/aspnetcore/blob/4ef204e13b88c0734e0e94a1cc4c0ef05f40849e/src/Http/Http/src/Extensions/HttpRequestRewindExtensions.cs#L23`
    return next();
});

然后您应该能够按照上面的 倒带:

string tmp;
try
{
    context.Request.Body.Seek(0, SeekOrigin.Begin);
}
catch(Exception ex)
{
    Console.WriteLine("Can't rewind body stream. " + ex.Message);
}
using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8))
{

    tmp = await reader.ReadToEndAsync();
}