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

Viewed 1739

It seems .NET Core 3.1 makes it very difficult to access the raw HTTP request body following an exception

The core of the issue seems to be you can't rewind the stream to the beginning so the whole thing can be read

In the below sample the output is:

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

If I remove the Seek, there's no exception, but of course the body comes back as an empty string, because it's already been processed

There is some new plumbing based around the Pipeline API involving Request.BodyReader but they suffer from the same problem.

All I need to do, following an exception, is dump the full request to a log file including the body content. Surely this should not be so difficult?

   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();
        });
    }
1 Answers

Please review answer by Stephen Wilkinson

Add the following to your code:

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();
});

You should then be able to rewind as per your code above:

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();
}
Related