Last update:

Custom middleware with dependency injection in ASP.NET Core

It is likely that a lot of ASP.NET Core projects will need to use custom middleware. In this post I will describe what are the simplest ways of creating an own ASP.NET Core middleware and using the built-in dependency injection system.

EDIT (2016-10-24): This article was updated to reflect changes in recent versions of ASP.NET Core 1.0.  I’ll keep it updated when newer versions are released.

EDIT (2017-12-21): I reviewed this post to make sure everything still applies to ASP.NET Core 2.0 – and it does. There were no breaking changes in this area between 1.0 and 2.0.


So, first, what is a middleware? In OWIN world (including ASP.NET Core), similarly to other web frameworks like node.js’ express, middleware is basically a piece of code that may be used to process a request. Middleware functions are usually chained together and it’s up to them to decide whether to invoke the next one in the chain.


When a request comes into the application, the first middleware function is executed. Let’s say it contains some logging logic. It logs request properties and invokes the next middleware in the chain. The next one deal with authentication. It may check if a particular cookie is present in the request and either pass the control to the next middleware or set a 401 HTTP code and return the response. Before the response is actually returned, it is passed through all the functions that are earlier in the chain (the logger in our case).

In ASP.NET Core middleware functions are defined in the Configure method of the Startup class. This method is executed automatically by the framework when your application starts (there is also another method, ConfigureServices, but we’ll get to that). In this method the framework provides the IApplicationBuilder instance containing several useful properties and methods:

IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
This is the most important method for us at the moment. It registers a new middleware function adding it to the end of the chain.
IServiceProvider ApplicationServices { get; set; }
Inversion of control container. We’ll use this object to create instances of classes required by the middleware.
IDictionary<string, object> Properties { get; set; }
Initially this dictionary contains just the IServerInformation and IServiceProvider instances (which are the same objects returned by the properties described above). It can be used to store additional application-wide settings.
IApplicationBuilder New()
Creates a new instance of IApplicationBuilder. Currently I can’t think of a use case for it.
RequestDelegate Build()
Chains the registered middlewares and returns them as a single RequestDelegate.

The method we need to register our own middleware is Use. It accepts a single parameter – Func<RequestDelegate, RequestDelegate>, which is a function that takes a RequestDelegate and returns a RequestDelegate. But what RequestDelegate is? It’s a function that takes a HttpContext as a parameter and returns a Task instance. So, ultimately, the Use method requires a function that requires a function and returns a function… It surely looks pretty complicated and the implementation can take a few lines:

Not pretty at all. But let’s break it down anyway. The app.Use method is provided a lambda representing Func<RequestDelegate, RequestDelegate>. Its parameter, next, is the next middleware in the chain. In line 3 we’re creating and returning a new RequestDelegate. It accepts a context (an HttpContext instance), an object that we can finally be productive with. In my example, a “Hello!” string is written in response to every request, then another middleware is executed. If there is no other middleware in the chain, a framework-provided one will be executed (it just returns 404 status code).

Anyway, these 9 lines of code are certainly not something we’d like to write each time a new middleware is to be registered. Fortunately, alternatives do exist. The Microsoft.AspNetCore.Builder namespace that is home to the IApplicationBuilder contains a class with several extension methods that make our work easier. Let’s see how the above code may look:

5 lines, not bad. Here we just need to provide a function accepting both the HttpContext and the next middleware and returning a Task. No more nested lambdas, this looks a lot cleaner.

But can we do even better? Sometimes we can. If we’re going to write the last middleware in the chain (i.e. we do not intend to call next()), we can use the Run extension method. It’s like Use without the next parameter.

Both of these extension methods call the IApplicationBuilder.Use under the covers, so there’s no magic involved. I encourage you to take a look at the source code and see how it’s built (it’s open source, after all; let’s take advantage of it!).

There is yet another way of creating an own middleware, that allows you to encapsulate the logic in a class. Such a class class must have an Invoke method accepting an HttpContext as a first argument. This seems to be a great way to create reusable middleware for sharing across projects.

The class must have a constructor accepting a RequestDelegate instance. It can be used inside an Invoke method to call the next middleware in the chain.

As I stated before, the class must have a single Invoke method that returns a Task and accepts an HttpContext parameter. Why don’t we have an IMiddleware interface, then? – you may ask. The reason for this is dependency injection. As it turns out, we may add additional parameters to the Invoke method or the constructor. They will be resolved by the DI containter. I’ll describe it below in more detail. This made it impossible to create a common interface.

Registering such a class is possible via the IApplicationBuilder.UseMiddleware method (or its generic equivalent):

Dependency injection

Rarely (if at all) our code is as simple as shown on the examples above. In real world projects, middleware need to call methods from other objects. Of course we can create these dependent objects inside a middleware but thanks to built-in dependency injection system, we’re able to write more elegant code.

The first step is to register classes in the IoC container. I’ve mentioned the ConfigureServices method earlier – that’s the place for it. The ConfigureServices method is executed by the framework before Configure, so that all the dependencies are ready to be used in middleware.

Let’s have a Greeter class:

The first step is to register it in the ConfigureServices method

I used the AddTransient method which creates a new instance of the class each time it’s requested. The other options are AddSingleton, AddScoped or simple Add (which all of the former use under the covers). I won’t go into detail about these methods here as the whole DI system is described in the official docs. They all work pretty much the same as their equivalents in other DI frameworks (which, by the way, you can use in ASP.NET Core as well).

After we’ve got our dependencies registered, we finally can use them. The IApplicationBuilder instance available in Configure method has a handy RequestServices property which we can use to get our Greeter instance. Since we’ve registered the IGreeter interface, we don’t have to couple the middleware with the concrete Greeter implementation.

If the Greeter class had a parametrized constructor, its dependencies also would have to be registered within ConfigureServices.

Resolving dependencies is even easier with middleware classes. As I described in the previous section, we may add additional parameters to the middleware constructor:

Or, we can add this dependency to the Invoke method:

If types of these parameters are known to the DI system, they will be automatically resolved when the class is instantiated. It’s that simple.

Here’s the whole example:

The response from this application looks as follows:

To read more about dependency injection in middleware, see my other post: Dependency lifetime in ASP.NET Core.


  1. Good post. It really helped me understand middleware clearly.

    Alex on 27 February 2015, 20:55 +01:00 Reply
  2. Excellent post, has helped me understand the basics of middleware in ASP.NET 5 and how it’s implemented. One thing to add, it would be useful to see what the output should be of your finished example.

    Ben on 23 June 2015, 11:18 +01:00 Reply
    1. I’ve just added the description of how to use middleware classes. The final output is also present.

      Michał Dudak on 3 September 2015, 17:26 +01:00 Reply
  3. Did you keep this updated for beta6?

    eXor on 5 August 2015, 10:46 +01:00 Reply
    1. Not yet. I’m quite busy right now but I’ll try to validate it and update if necessary soon.

      Michał Dudak on 5 August 2015, 11:58 +01:00 Reply
    2. I updated the post for beta 7.

      Michał Dudak on 3 September 2015, 17:17 +01:00 Reply
  4. Really great article – thanks!

    Mark Eastwood on 16 December 2015, 15:36 +01:00 Reply
  5. Dobrze przygotowany artykuł, dzięki.

    Marzenka on 31 March 2017, 14:10 +01:00 Reply
  6. Thanks for the article.
    I am using OWIN with the method public void Configuration(IAppBuilder appBuilder) in my StartUp class.
    I have added the method ConfigureServices(IServiceCollection services) in my Startup class as well but it does not get called at Startup.
    How to have both functions called at startup?
    Thank you.

    Rems on 16 July 2017, 22:37 +01:00 Reply
    1. ConfigureServices is used in ASP.NET Core applications (it is called automatically by the framework). Based on the Configuration method signature I assume you’re using Katana, not ASP.NET Core.

      Michał Dudak on 17 July 2017, 7:58 +01:00 Reply
  7. Thank you for this tutorial. But I’m a bit stucked (using ASP.NET Core 2.0). I get “InvalidOperationException: Cannot resolve scoped service ‘…’ from root provider.” as error. I tested with two services, who are added as AddScoped. When I change one to AddTransient, then it’s working. Why is this?
    Another service needs DB, so I’m getting an error when changing to AddTransient – and I would not really like this.
    How can I resolve this error?

    Matt on 11 March 2018, 21:04 +01:00 Reply
    1. Hi Matt, take a look at my recent post: I described there exactly what you ask about.

      Michał Dudak on 11 March 2018, 21:44 +01:00 Reply
  8. I hope what I’m about to say helps someone greatly…

    IF YOU ARE PERFORMING DBCONTEXT (EF) OPERATIONS within the middleware, you may very well need to inject the repository (or DBcontext if you don’t have repositories) into the INVOKE method and NOT the constructor. If you inject into the constructor, all of your injected instances with be the same (i.e. they will all be scoped to the single middleware instance).
    Obviously this is avoidable in 2.0 with IMiddleware (factory implementation), but in 1.1 that feature is not available.

    Don’t do what I did, and sped 2hours trying to troubleshoot the context.

    Michael on 20 March 2018, 18:26 +01:00 Reply
  9. I described it more detail in my recent post:

    Michał Dudak on 20 March 2018, 20:05 +01:00 Reply
  10. Great post!
    Can we inject IApplicationBuilder in the constructor of Middleware class? I need that to resolve an interface and call a method on that to get some data.
    Thank you!

    Yawar on 15 May 2018, 22:29 +01:00 Reply
  11. Very good, this is exactly what I want, thank you very much!

    pzy on 25 May 2018, 2:56 +01:00 Reply
  12. Nice explanation indeed. However, I was looking for an example of IMiddleware implementation as well which microsoft failed explain clearly in it’s documentation here.

    5a7335h on 3 June 2018, 14:01 +01:00 Reply
  13. I’m writing a middleware that is supposed to inject some information into each implementation of IService.
    However, only one implementation reaches the Invoke method, although I have at least 2 implementations, like UsersService : IService, ProfileService : IService.

    public async Task Invoke(HttpContext context, IService theService)
    UserInfo serInfo = await GetUserInfoAsync(context).ConfigureAwait(false);

    theService.UserInfo = userInfo;

    Any ideas how to fix this?

    Danie on 3 December 2018, 13:26 +01:00 Reply
    1. If you need to get all implementations of a service, inject IEnumerable<IService> instead of just IService.

      Michał Dudak on 3 December 2018, 13:37 +01:00 Reply
  14. Well, that seems a very ugly workaround.
    To check all IService implementations, when the middleware just receives one.

    But anyway, I tried using IEnumerable but the same error occurs.
    The UserService has the data, the ProfileService doesn’t.
    So, the problem might be in the DI registration code.

    Daniel on 3 December 2018, 16:08 +01:00 Reply
    1. I thought that’s what you were aiming for, no? I understood your middleware needs to access all the implementations of IService. That’s not a workaround, it’s a pretty common practice to inject IEnumerable to receive all implementations of a service. I couldn’t find anything in the ASP.NET Core docs but Autofac allows it as well:

      Michał Dudak on 3 December 2018, 16:19 +01:00 Reply
  15. Ok, using IEnumerable instead of IService AND registering as InstancePerLifetimeScope() (with Autofac) does solve the problem.
    However, I still think there is a problem to send all the services into the middleware.
    Now there are 2 services, it’s estimated to get to around 30 services.

    Daniel on 3 December 2018, 16:36 +01:00 Reply
  16. Good one. Helped me a lot. Thank you!

    Peyman on 27 July 2019, 20:09 +01:00 Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Michał Dudak