2026-10-16 · Q&A guide

Log ASP.NET Core 3.1 API Response Body and Latency with Middleware

Learn how to capture the full response body, execution time, and error details in an ASP.NET Core 3.1 API using a lightweight middleware and NLog.

Why Log the Response Body?

When third‑party vendors consume your API, they often need to audit the exact payload returned. Logging the response also helps debug mismatches between expected and actual data, and provides a record for compliance. However, it must be done carefully to avoid leaking sensitive information.

Middleware Basics for Logging

A middleware sits in the request pipeline and can inspect or modify the HttpContext before and after the next component executes. By wrapping the response stream, you can capture everything that is written to the client without altering the controller logic.

Replacing the Response Stream

The response body is a write‑only stream. To read it, replace it with a MemoryStream, let the pipeline write into it, then copy the buffer back to the original stream. The following snippet shows the core of that logic.

// Swap the original stream
var originalBody = context.Response.Body;
var buffer = new MemoryStream();
context.Response.Body = buffer;

await _next(context);

buffer.Seek(0, SeekOrigin.Begin);
var responseBody = await new StreamReader(buffer).ReadToEndAsync();
buffer.Seek(0, SeekOrigin.Begin);
await buffer.CopyToAsync(originalBody);
context.Response.Body = originalBody;

Measuring Latency and Logging

Wrap the next delegate call in a Stopwatch to capture elapsed time. Combine the captured body, status code, and timing into a single log entry. NLog’s layout renderer can then format the message as needed.

var sw = Stopwatch.StartNew();
await _next(context);
sw.Stop();
_logger.LogInformation("{Method} {Path} responded {StatusCode} in {Elapsed} ms. Body: {Body}",
    context.Request.Method,
    context.Request.Path,
    context.Response.StatusCode,
    sw.ElapsedMilliseconds,
    responseBody);

Security & Best Practices

Never log raw authentication tokens, passwords, or PII. Use a whitelist of safe headers and trim or redact known sensitive fields before logging. Consider adding a configuration flag to enable or disable response logging in production. For telemetry, ASP.NET Core’s built‑in Application Insights can capture request and response details automatically, but it also respects sampling and redaction settings.

Takeaway: By swapping the response stream and measuring elapsed time, you can safely log API responses while keeping sensitive data protected.

People also ask

Can I use this middleware with minimal APIs?

Yes, the same pattern applies. Register the middleware before the endpoint mapping in Program.cs.

Will this affect performance?

The overhead is minimal; the main cost is the extra MemoryStream allocation and copy, which is negligible for typical payload sizes.

Inspired by a public discussion on Stack Overflow. This article is an original explanation for learners.

← All posts