user69374
user69374

Reputation: 541

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

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

Upvotes: 3

Views: 3059

Answers (2)

Kha Bui
Kha Bui

Reputation: 1

It works for me.

StringBuilder body = new StringBuilder();
var req = context.Request;

// Allows using several time the stream in ASP.Net Core
req.EnableBuffering();

using (StreamReader reader = new StreamReader(req.Body, Encoding.UTF8, true, 1024, true))
{
    string line;
    while ((line = reader.ReadLineAsync().Result) != null)
    {
        body.Append(line);
    }
}
req.Body.Position = 0;
_logger.LogInformation($"Body: {body.ToString()}");

From link How to read request body in an asp.net core webapi controller?

Upvotes: 0

Lance
Lance

Reputation: 632

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

Upvotes: 4

Related Questions