Logging .NET WebAPI for debugging, monitoring, and auditing purposes
Logging requests and responses in a .NET WebAPI application can be crucial for debugging, monitoring, and auditing purposes. You can achieve this by implementing middleware in your ASP.NET WebAPI project. Here's a basic outline of how you can log requests and responses:Create a Logging Middleware: First, you need to create a middleware class to handle logging. This middleware will intercept requests and responses and log them.
Request Middleware
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Http;
- using Microsoft.Extensions.Hosting;
- namespace Lib.Common.Middleware
- {
- public class RequestMiddleware
- {
- private readonly RequestDelegate next;
- public RequestMiddleware(RequestDelegate next)
- {
- this.next = next;
- }
- public async Task Invoke(HttpContext context, IMiddlewareRepository _middlewareRepository)
- {
- string[] allowedPaths = new string[]
- {
- "/api/home",
- "/favicon.ico"
- };
- if (allowedPaths.Contains(context.Request.Path.Value.ToLower()))
- {
- await next(context);
- }
- else
- {
- var requestBodyStream = new MemoryStream();
- string apiURL = context.Request.Host + context.Request.Path;
- var originalRequestBody = context.Request.Body;
- await context.Request.Body.CopyToAsync(requestBodyStream);
- requestBodyStream.Seek(0, SeekOrigin.Begin);
- var requestBodyText = new StreamReader(requestBodyStream).ReadToEnd();
- var id = await _middlewareRepository.PostRequestLog(apiURL, requestBodyText);
- context.Items["RequestId"] = id;
- requestBodyStream.Seek(0, SeekOrigin.Begin);
- context.Request.Body = requestBodyStream;
- await next(context);
- context.Request.Body = originalRequestBody;
- }
- }
- }
- // Extension method used to add the middleware to the HTTP request pipeline.
- public static class RequestMiddlewareExtension
- {
- public static IApplicationBuilder UseLogRequestMiddleware(this IApplicationBuilder builder)
- {
- return builder.UseMiddleware<RequestMiddleware>();
- }
- }
- }
Response Middleware
- using Lib.Common.Model;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Http;
- namespace Lib.Common.Middleware
- {
- public class ResponseMiddleware
- {
- private readonly RequestDelegate _next;
- public ResponseMiddleware(RequestDelegate next)
- {
- _next = next;
- }
- public async Task Invoke(HttpContext context, IMiddlewareRepository _middlewareRepository)
- {
- string[] allowedPaths = new string[]
- {
- "/api/home",
- "/favicon.ico"
- };
- if (allowedPaths.Contains(context.Request.Path.Value.ToLower()))
- {
- await _next(context);
- }
- else
- {
- var bodyStream = context.Response.Body;
- var responseBodyStream = new MemoryStream();
- context.Response.Body = responseBodyStream;
- await _next(context);
- responseBodyStream.Seek(0, SeekOrigin.Begin);
- long requestId = Convert.ToInt64(context.Items["RequestId"]);
- string status = context.Response.StatusCode.ToString();
- var responseBody = new StreamReader(responseBodyStream).ReadToEnd();
- await _middlewareRepository.PostResponseLog(responseBody, status, requestId);
- responseBodyStream.Seek(0, SeekOrigin.Begin);
- await responseBodyStream.CopyToAsync(bodyStream);
- }
- }
- }
- // Extension method used to add the middleware to the HTTP response pipeline.
- public static class ResponseMiddlewareExtensions
- {
- public static IApplicationBuilder UseLogResponseMiddleware(this IApplicationBuilder builder)
- {
- return builder.UseMiddleware<ResponseMiddleware>();
- }
- }
- }
Middleware repository
- using Dapper;
- using Lib.Common.Enum;
- using Lib.Common.Repository.CustomExceptions;
- using Lib.Common.Repository.Dapper;
- using Microsoft.Extensions.Configuration;
- namespace Lib.Common.Middleware
- {
- public class MiddlewareRepository : IMiddlewareRepository
- {
- private readonly IConfiguration _configuration;
- private readonly IExceptionLogger _loggerRepository;
- private static readonly string exceptionSource = "Lib.Common.Middleware.MiddlewareRepository";
- private readonly IGenericDapperRepository<string> _genericDapperRepository;
- public MiddlewareRepository(IExceptionLogger loggerRepository, IConfiguration configuration,
- IGenericDapperRepository<string> genericDapperRepository)
- {
- _loggerRepository = loggerRepository;
- _configuration = configuration;
- _genericDapperRepository = genericDapperRepository;
- }
- public async Task<long> PostRequestLog(string apiURL, string requestBody, string? purpose = null, string? apiType = null)
- {
- try
- {
- requestBody = requestBody.Replace("'", @"''");
- string? procedure = _configuration["Procedure:InsertAgamApiLog"];
- var parameters = new DynamicParameters();
- parameters.Add("@p_purpose", purpose);
- parameters.Add("@p_apiType", apiType);
- parameters.Add("@p_apiURL", apiURL);
- parameters.Add("@p_bodyText", requestBody);
- string? result = await _genericDapperRepository.GetByParamsFirstOrDefaultAsync(procedure, parameters);
- return Convert.ToInt64(result);
- }
- catch (Exception ex)
- {
- _ = _loggerRepository.LogDetails(ExceptionLoggerType.DB, ex, $"{exceptionSource} => PostRequestLog()");
- throw;
- }
- }
- public async Task PostResponseLog(string responseBody, string status, long requestId)
- {
- try
- {
- responseBody = responseBody.Replace("'", @"''");
- string? procedure = _configuration["Procedure:InsertAgamApiLog"];
- procedure += $"(p_bodytext := '{responseBody}', p_requestid := {requestId}, p_status := '{status}');";
- await _genericDapperRepository.GetByParamsFirstOrDefaultAsync(procedure);
- }
- catch (Exception ex)
- {
- _ = _loggerRepository.LogDetails(ExceptionLoggerType.DB, ex, $"{exceptionSource} => PostResponseLog()");
- throw;
- }
- }
- }
- }
Register Middleware: Register the middleware in your program.cs file in the Configure method:
- using Lib.Common.CustomProvider;
- using Lib.Common.Filters;
- using Lib.Common.Middleware;
- using Lib.Common.Model;
- using WebApi.Customer.Extensions;
- var builder = WebApplication.CreateBuilder(args);
- // Add services to the container.
- var configuration = builder.Configuration;
- AppSettings appSettings = new AppSettings();
- var ConfigurationBuilder = new ConfigurationBuilder()
- //.AddJsonFile("appsettings.json" )
- .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json")
- .AddEncryptedProvider(configuration, appSettings)
- .AddEnvironmentVariables();
- builder.Services.AddSingleton(appSettings);
- builder.Services.Configure<ClientAssembly>(builder.Configuration.GetSection("ClientAssembly"));
- // Added all dependency in Custom Configuration services
- builder.Services.AddCustomConfigureService();
- // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
- builder.Services.AddEndpointsApiExplorer();
- builder.Services.AddSwaggerGen();
- builder.Services.AddControllers(options =>
- {
- options.Filters.Add(typeof(ExceptionalHandler));
- });
- builder.Services.AddCors(p => p.AddPolicy("corsapp", builder =>
- {
- builder.WithOrigins("*").AllowAnyMethod().AllowAnyHeader();
- }));
- var listenAnyIPPortNo =Convert.ToInt32( Environment.GetEnvironmentVariable("IPPortNumber"));
- builder.WebHost.ConfigureKestrel(serverOptions =>
- {
- //serverOptions.ListenAnyIP(8114);
- serverOptions.ListenAnyIP(listenAnyIPPortNo);
- serverOptions.ListenLocalhost(5001);
- });
- ConfigurationBuilder.Build();
- var app = builder.Build();
- // Configure the HTTP request pipeline.
- //if (app.Environment.IsDevelopment())
- //{
- app.UseSwagger();
- app.UseSwaggerUI();
- //}
- //Add new middleware to the pipeline
- app.UseMiddleware<RequestMiddleware>();
- app.UseMiddleware<ResponseMiddleware>();
- app.MapControllers();
- app.Run();


Post a Comment
0Comments