.NET 6 HttpLogging RequestBody in is always empty in log

Viewed 1121

I use HttpLogging to log requests coming to my endpoints. I would like to log the whole request. I setup the HttpLogging in Program.cs

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
});

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpLogging();

And change logging level in appsettings.Development.json

 "Microsoft.AspNetCore": "Information"

Then when I send a request from Postman or cURL I can see all the needed information but the RequestBody is ALWAYS empty (near the log end)

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Protocol: HTTP/1.1
      Method: POST
      Scheme: https
      PathBase:
      Path: /WeatherForecast
      Accept: */*
      Connection: keep-alive
      Host: localhost:7269
      User-Agent: PostmanRuntime/7.29.0
      Accept-Encoding: gzip, deflate, br
      Content-Type: application/json
      Content-Length: 60
      Postman-Token: [Redacted]
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'WebApplication1.Controllers.WeatherForecastController.Post (WebApplication1)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "Post", controller = "WeatherForecast"}. Executing controller action with signature System.Collections.Generic.IEnumerable`1[WebApplication1.WeatherForecast] Post() on controller WebApplication1.Controllers.WeatherForecastController (WebApplication1).
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
      Executing ObjectResult, writing value of type 'WebApplication1.WeatherForecast[]'.
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      Response:
      StatusCode: 200
      Content-Type: application/json; charset=utf-8
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
      Executed action WebApplication1.Controllers.WeatherForecastController.Post (WebApplication1) in 8.0904ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'WebApplication1.Controllers.WeatherForecastController.Post (WebApplication1)'
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[3]
      RequestBody:   //<----------------------------------------------- ALWAYS EMPTY
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[4]
      ResponseBody: [{"date":"2022-03-17T18:05:11.5799408+01:00","temperatureC":41,"temperatureF":105,"summary":"Bracing"}]
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 POST https://localhost:7269/WeatherForecast application/json 60 - 200 - application/json;+charset=utf-8 19.0485ms

However I know the body is there because when I try to read the body in controller and stop on breakpoint I can see the body loaded in the variable.

using var reader = new StreamReader(HttpContext.Request.Body);
var myBody = await reader.ReadToEndAsync(); // {"username": "josef","password": "MyPassword"}

There is a request cURL example generated from PostMan.

curl --location --request POST 'https://localhost:7269/WeatherForecast' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username": "josef",
    "password": "MyPassword"
}'

I dont know if there is a step I missed or something like that. I tried changing different log levels, different request types, bodies and body types. The RequestBody is always empty in the log.

Edit 1

I just found that when I keep the body reader from above in controller and read from it, it actually log the correct RequestBody in the log. Could someone explain this behaviour? I dont understand why it should log only when I manually read the body.

1 Answers

I have got this working (allbeit with Serilog over the top). I have these additions to your work in my code:

  1. Registering the logging settings:

    services.AddHttpLogging(logging =>
    {
        logging.LoggingFields = HttpLoggingFields.All;
        logging.RequestHeaders.Add(HeaderNames.Accept);
        logging.RequestHeaders.Add(HeaderNames.ContentType);
        logging.RequestHeaders.Add(HeaderNames.ContentDisposition);
        logging.RequestHeaders.Add(HeaderNames.ContentEncoding);
        logging.RequestHeaders.Add(HeaderNames.ContentLength);
    
        logging.MediaTypeOptions.AddText("application/json");
        logging.RequestBodyLogLimit = 4096;
        logging.ResponseBodyLogLimit = 4096;
    });
    
  2. Including some appsettings.json:

    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft.AspNetCore": "Information",
            "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
        }
     },

Probably just the appsettings are needed, although you definately need to code logging.MediaTypeOptions.AddText("multipart/form-data"); if you want a request form submission logged

Related