Adding custom middleware fails when using IMiddleware

Adding a Custom Middleware with the IMiddleware Interface

This article is about how to add a custom middleware with the IMiddleware interface. We will take the .NET Core documentation example of setting the Spanish culture whenever an API call is fired.

Creating the Middleware

First, we need to create the middleware. Here is the code which runs perfectly:

public class RequestCultureMiddleware : IMiddleware
{
    public Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        CultureInfo.CurrentCulture = new CultureInfo("es-ES");
        CultureInfo.CurrentUICulture = new CultureInfo("es-ES");

        // Call the next delegate/middleware in the pipeline
        return next(context);
    }
}

public static class RequestCultureMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestCulture(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestCultureMiddleware>();
    }
}

Adding the Middleware to the Pipeline

Next, we need to add the middleware to the pipeline in the Startup class:

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.AddControllers();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        //here is our custom middleware!
        app.UseRequestCulture();

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

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

Registering the Middleware

Finally, we need to register the middleware. The IMiddleware interface is part of the Microsoft.AspNetCore.Http assembly. It looks like this:

namespace Microsoft.AspNetCore.Http
{
    //
    // Summary:
    //     Defines middleware that can be added to the application's request pipeline.
    public interface IMiddleware
    {
        //
        // Summary:
        //     Request handling method.
        //
        // Parameters:
        //   context:
        //     The Microsoft.AspNetCore.Http.HttpContext for the current request.
        //
        //   next:
        //     The delegate representing the remaining middleware in the request pipeline.
        //
        // Returns:
        //     A System.Threading.Tasks.Task that represents the execution of this middleware.
        Task InvokeAsync(HttpContext context, RequestDelegate next);
    }
}

We can register the middleware using UseMiddleware:

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

    //here is our custom middleware!
    app.UseRequestCulture();

    // ...
}

Error

But, when running the API, we get the following error at run-time:

System.InvalidOperationException: No service for type 'WebApplication1.RequestCultureMiddleware' has been registered.
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.AspNetCore.Http.MiddlewareFactory.Create(Type middlewareType)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass5_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Solution

We need to register the middleware as a service using IServiceCollection.AddSingleton:

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

    //add our custom middleware as a service
    services.AddSingleton<RequestCultureMiddleware>();
}

To solve the issue, you need to register the middleware as a service using IServiceCollection.AddSingleton in the ConfigureServices method of the Startup class.

Here’s the updated code:

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

    // add our custom middleware as a service
    services.AddSingleton<RequestCultureMiddleware>();
}

After making this change, the error should be resolved.