Hi @Cenk ,
I have this ASP.NET web API and I am upgrading it to Core. In my legacy application, I log requests and responses into an SQL database. I wonder if there is a way to do it in Core?
In asp.net core, you can create a custom middleware to capture both HTTP requests and responses.
Code like this:
public class RequestResponseLoggerMiddleware
{
private readonly RequestDelegate _next;
private readonly bool _isRequestResponseLoggingEnabled;
public RequestResponseLoggerMiddleware(RequestDelegate next, IConfiguration config)
{
_next = next;
_isRequestResponseLoggingEnabled = config.GetValue<bool>("EnableRequestResponseLogging", false);
}
public async Task InvokeAsync(HttpContext httpContext)
{
// Middleware is enabled only when the EnableRequestResponseLogging config value is set.
if (_isRequestResponseLoggingEnabled)
{
Console.WriteLine($"HTTP request information:\n" +
$"\tMethod: {httpContext.Request.Method}\n" +
$"\tPath: {httpContext.Request.Path}\n" +
$"\tQueryString: {httpContext.Request.QueryString}\n" +
$"\tHeaders: {FormatHeaders(httpContext.Request.Headers)}\n" +
$"\tSchema: {httpContext.Request.Scheme}\n" +
$"\tHost: {httpContext.Request.Host}\n" +
$"\tBody: {await ReadBodyFromRequest(httpContext.Request)}");
// Temporarily replace the HttpResponseStream, which is a write-only stream, with a MemoryStream to capture it's value in-flight.
var originalResponseBody = httpContext.Response.Body;
using var newResponseBody = new MemoryStream();
httpContext.Response.Body = newResponseBody;
// Call the next middleware in the pipeline
await _next(httpContext);
newResponseBody.Seek(0, SeekOrigin.Begin);
var responseBodyText = await new StreamReader(httpContext.Response.Body).ReadToEndAsync();
Console.WriteLine($"HTTP request information:\n" +
$"\tStatusCode: {httpContext.Response.StatusCode}\n" +
$"\tContentType: {httpContext.Response.ContentType}\n" +
$"\tHeaders: {FormatHeaders(httpContext.Response.Headers)}\n" +
$"\tBody: {responseBodyText}");
newResponseBody.Seek(0, SeekOrigin.Begin);
await newResponseBody.CopyToAsync(originalResponseBody);
}
else
{
await _next(httpContext);
}
}
private static string FormatHeaders(IHeaderDictionary headers) => string.Join(", ", headers.Select(kvp => $"{<!-- -->{<!-- -->{kvp.Key}: {string.Join(", ", kvp.Value)}}}"));
private static async Task<string> ReadBodyFromRequest(HttpRequest request)
{
// Ensure the request's body can be read multiple times (for the next middlewares in the pipeline).
request.EnableBuffering();
using var streamReader = new StreamReader(request.Body, leaveOpen: true);
var requestBody = await streamReader.ReadToEndAsync();
// Reset the request's body stream position for next middleware in the pipeline.
request.Body.Position = 0;
return requestBody;
}
}
Then, call the custom middleware using app.UseMiddleware<RequestResponseLoggerMiddleware>();
or create a Custom middleware extension.
More detail code, you can refer to this sample.
Besides, there also has another tutorial, you can check it: Request Response Logging Middleware ASP.NET Core
Then, to insert the request or response data into database, you can inject the DBContext in the Custom Middleware InvokeAsync method, and then insert the data into the database. Code like this:
public async Task InvokeAsync(HttpContext context, ApplicationDbContext dbContext)
{
You can refer to this article: Factory-based middleware activation in ASP.NET Core
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
Best regards,
Dillion