Building Custom Middleware Components for Logging, Error Handling, and Request/Response Modification

ASP.NET Core to handle cross-cutting concerns like logging, error handling, and request/response modification.

Step 1. Create a new ASP.NET Core Web API project using Visual Studio or the .NET CLI.

Step 2. Define your custom middleware class. In this example, we'll create a middleware that logs incoming requests and outgoing responses.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;

Author: Sardar Mudassar Ali Khan
public class RequestResponseLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestResponseLoggingMiddleware> _logger;

    public RequestResponseLoggingMiddleware(RequestDelegate next, 
    ILogger<RequestResponseLoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        LogRequest(context);

        var originalBodyStream = context.Response.Body;
        using (var responseBody = new MemoryStream())
        {
            context.Response.Body = responseBody;

            await _next(context);

            LogResponse(context);

            await responseBody.CopyToAsync(originalBodyStream);
        }
    }

    private void LogRequest(HttpContext context)
    {
        var request = context.Request;

        var requestLog = new StringBuilder();
        requestLog.AppendLine("Incoming Request:");
        requestLog.AppendLine($"HTTP {request.Method} {request.Path}");
        requestLog.AppendLine($"Host: {request.Host}");
        requestLog.AppendLine($"Content-Type: {request.ContentType}");
        requestLog.AppendLine($"Content-Length: {request.ContentLength}");

        _logger.LogInformation(requestLog.ToString());
    }

    private void LogResponse(HttpContext context)
    {
        var response = context.Response;

        var responseLog = new StringBuilder();
        responseLog.AppendLine("Outgoing Response:");
        responseLog.AppendLine($"HTTP {response.StatusCode}");
        responseLog.AppendLine($"Content-Type: {response.ContentType}");
        responseLog.AppendLine($"Content-Length: {response.ContentLength}");

        _logger.LogInformation(responseLog.ToString());
    }
}

Step 3. Register your custom middleware in the Startup.cs file.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

Author: Sardar Mudassar Ali Khan
public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory 
    loggerFactory)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMiddleware<RequestResponseLoggingMiddleware>();

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

Step 4. Run the application and test it using a tool like Postman or a web browser. You should see the logs in the output window of your development environment or logging provider.

Conclusion

Custom middleware in ASP.NET Core is a powerful tool for handling cross-cutting concerns in your application. By creating custom middleware, you can intercept and modify both incoming requests and outgoing responses, enabling you to implement features such as logging, error handling, request/response modification, and much more.

Custom middleware that logs incoming requests and outgoing responses. However, the possibilities are vast, and you can tailor the middleware to suit your specific application needs.

Some Important Points 

  1. Custom middleware is a way to encapsulate cross-cutting concerns in ASP.NET Core applications.
  2. Middleware components are executed in the order they are registered in the Startup.cs file.
  3. You can create custom middleware by implementing the Invoke method in a class and using the RequestDelegate parameter to call the next middleware in the pipeline.
  4. Middleware can access and modify both the incoming HttpContext and the outgoing HttpResponse.
  5. The provided example demonstrated a middleware for logging incoming requests and outgoing responses using the ILogger<T> instance.
  6. Custom middleware allows you to implement various functionalities, such as authentication, authorization, caching, compression, and more.
  7. Ensure that you handle errors properly and avoid logging sensitive information in production environments.

As you delve into ASP.NET Core development, exploring and mastering custom middleware will give you more control over your application's behavior and help you create robust, efficient, and maintainable web APIs. Always refer to the official documentation and best practices when working with custom middleware and other advanced features in ASP.NET Core. Happy coding!


Similar Articles