Create Custom Middleware In An ASP.NET Core Application

Introduction

One of the major features in ASP.NET Core is the new request pipeline which is available for the developer to customize according to the requirements of the application. In the request pipeline, several middleware components can be added to handle authentication, authorization, logging to files, etc. Although we have a long list of middleware’s available to us for use, there might be situations where we need to design and develop our own middleware component and add this to the request pipeline in order to execute it with every request. In today’s article, we will look at creating a simple middleware component.

Creating the custom middleware component

We will create the Middleware component using Visual Studio 2019 Community Edition. First, we will create a simple ASP.NET Core MVC application, as shown below:

Next, we will create a new folder called “Middlewares” in the main project, as shown below.

Next, we will add a new Middleware component by adding a new item.

Now, we will add the below code.

using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
namespace WebAppMiddleware.Middlewares
{
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class CustomMiddleware
    {
        private readonly RequestDelegate _next;
        public CustomMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        public async Task Invoke(HttpContext httpContext)
        {
            using var buffer = new MemoryStream();
            var request = httpContext.Request;
            var response = httpContext.Response;

            var stream = response.Body;
            response.Body = buffer;
            await _next(httpContext);
            Debug.WriteLine($"Request content type:  {httpContext.Request.Headers["Accept"]} {System.Environment.NewLine} Request path: {request.Path} {System.Environment.NewLine} Response type: {response.ContentType} {System.Environment.NewLine} Response length: {response.ContentLength ?? buffer.Length}");
            buffer.Position = 0;

            await buffer.CopyToAsync(stream);
        }
    }
    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class CustomMiddlewareExtensions
    {
        public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<CustomMiddleware>();
        }
    }
}

As we can see in the above code, we simply write some details related to the request and response objects in the Invoke method which is the place to add our custom logic. Also, note that we use the _next request delegate to pass the control to the next middleware.

Using the custom middleware component

Finally, we will plug this new Middleware component into the Request Pipeline (Configure method of the Startup class) by using the extension method defined in the CustomMiddlewareExtensions static class.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using WebAppMiddleware.Middlewares;
namespace WebAppMiddleware
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseCustomMiddleware();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });

        }
    }
}

Now, when we run the application, this new middleware component will be run with each request. Let's navigate to the privacy page and we will see the below output in the window.

Summary

In this article, we looked at how to create a simple middleware component and add it to the request pipeline in an ASP.NET Core MVC application. As we have seen, this process is quite simple and straightforward and can be used to extract particularly useful information as well as carry out desired actions while the request and response are passing through the application pipeline. For this example, we simply wrote some information related to the request and response types and sizes. However, more complex scenarios can also be implemented in the same easy-to-develop manner.


Similar Articles