Skip to main content

ASP.NET Core–Cannot resolve from root provider because it requires scoped service

A colleague contacted me with the following problem; when running his ASP.NET Core application it failed with the following error message:

Cannot resolve IApiLoggingService from root provider because it requires scoped service NHibernate.IInterceptor

In this post I walk you through the different steps we took to investigate the issue and explain how we solved it.

But before I dive into the problem itself I first want to give some background info on dependency injection in ASP.NET Core and service lifetimes.

Dependency injection and service lifetimes

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies.

Registration of a dependency is done in the built-in service container, IServiceProvider. Services are typically registered at the app's start-up and appended to an IServiceCollection. Once all services are added, you use BuildServiceProvider to create the service container.

    Injection of the service is done into the constructor of the class where it's used. The framework takes on the responsibility of creating an instance of the dependency and disposing of it when it's no longer needed.

    Services can be registered with one of the following lifetimes:

    • Transient: A service is created each time they’re requested from the service container
    • Scoped: A service is created once per client request(typically an HTTP request in ASP.NET Core)
    • Singleton: A service is created once per lifetime of the service container

    Diving into our problem

    If we take the knowledge above and apply it to the error message we got, we could assume that the following is happening:

    We have registered two services:

    • An IApiLoggingService with either a transient or singleton lifetime
    • An IInterceptor with a scoped lifetime

    The IApiLoggingService has a dependency on the IInterceptor.  We are resolving the IApiLoggingService from the root container(the root container is used when there is not  a scoped context (e.g. a specific HTTP request) available.

    As there is no scope available, it is not possible to create the IInterceptor service with a scoped lifetime.

    Remark: The error is caused by the built-in scope validation. If a scoped service is created in the root container, the service's lifetime is effectively promoted to singleton which is of course not what we want. Scope validation prevents this.

    Let’s dive into the application to confirm this…

    We first take a look at the service registrations:

    And indeed we have both a transient and scoped registration.

    Now we look at the ApiLoggingService implementation and we see that the IInterceptor is injected as a dependency:

    And then we check where the IApiLoggingService is injected:

    We see that it is used inside an ASP.NET Core middleware and is injected into the constructor. Convention based middleware is created and instantiated before a specific request arrives so that explains the error above.

    Does this mean that we cannot use scoped services inside ASP.NET Core middleware?

    Fortunately we can use scoped services inside our middleware. Instead of injecting our dependency through constructor injection, we could inject our service in the Invoke method through method injection when using convention based middleware:

    Another option is to switch to factory based middleware which I’ll explain in my next post.

    More information

    Dependency injection in ASP.NET Core | Microsoft Learn

    Popular posts from this blog

    DevToys–A swiss army knife for developers

    As a developer there are a lot of small tasks you need to do as part of your coding, debugging and testing activities.  DevToys is an offline windows app that tries to help you with these tasks. Instead of using different websites you get a fully offline experience offering help for a large list of tasks. Many tools are available. Here is the current list: Converters JSON <> YAML Timestamp Number Base Cron Parser Encoders / Decoders HTML URL Base64 Text & Image GZip JWT Decoder Formatters JSON SQL XML Generators Hash (MD5, SHA1, SHA256, SHA512) UUID 1 and 4 Lorem Ipsum Checksum Text Escape / Unescape Inspector & Case Converter Regex Tester Text Comparer XML Validator Markdown Preview Graphic Color B

    Help! I accidently enabled HSTS–on localhost

    I ran into an issue after accidently enabling HSTS for a website on localhost. This was not an issue for the original website that was running in IIS and had a certificate configured. But when I tried to run an Angular app a little bit later on http://localhost:4200 the browser redirected me immediately to https://localhost . Whoops! That was not what I wanted in this case. To fix it, you need to go the network settings of your browser, there are available at: chrome://net-internals/#hsts edge://net-internals/#hsts brave://net-internals/#hsts Enter ‘localhost’ in the domain textbox under the Delete domain security policies section and hit Delete . That should do the trick…

    Azure DevOps/ GitHub emoji

    I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.