Scope and the root provider
“What is a scope in ASP.NET Core dependency injection, and what is the root provider?”
The root lives as long as the app. A scope lives for one request, and so do the scoped objects inside it.
See it
Build() makes the root provider. It lives until the app stops and keeps the .In plain words
The root provider is the 's top level: made once when the app starts, alive until it stops. A scope is a short-lived group of objects. ASP.NET Core opens one for each web request. A scoped service such as is made once inside that group, shared by everything in that request, and let go when the request ends. Two requests at the same time get two scopes and two objects. The root keeps the singletons: one object each, shared by every request.
- The root provider is the that
builder.Build()creates. It lives as long as the app and owns the singletons. - ASP.NET Core opens one scope per HTTP request, at . A scoped service is built once in it and disposed with it.
- Outside a request, such as in a background job, you open one yourself with .
- In Development, throws if a scoped service is resolved from the root.
In the lending API
Program.cs makes the root, the controller runs inside a request's scope, and a test proves both. Press Next line to walk through them.
Lending.sln · where these 3 files sit
- src/Api/
- Controllers/Servicing/
- Controllers/Servicing/
- tests/Api.IntegrationTests/
Build() makes the root provider. It lives until the app stops and keeps the .What they ask next
Interviewers check that you can explain every line. Tap a question to open it.
Why not…Why not just resolve it from
app.Services?app.Servicesis the root. A scoped service taken from the root is never disposed until the app stops, and every caller shares it, so it acts like a singleton by accident. Open a scope with and resolve fromscope.ServiceProvider.Is a scope one per user, or one per request?
One per HTTP request. The same user sending two requests gets two scopes and two objects. Nothing in DI is per user; that is session or cache work.
Is on in Production?
No. By default it is on only in Development, together with , which checks every registration at startup; the checks cost a little. Many teams turn both on everywhere:
builder.Host.UseDefaultServiceProvider(o => { o.ValidateScopes = true; o.ValidateOnBuild = true; });.Does the scope call on ?
Only on services that implement or , and only on ones the container built itself. has nothing to dispose, so it is just let go for the . In slice 3 the is scoped, and this is what gives its database connection back. See .
or ?
In async code,
await using var scope = scopes.CreateAsyncScope();. If the scope holds a service that only implements , a plain of the scope throws.
What if a singleton needs a scoped service?
That is a captive dependency: the scoped object gets trapped inside the singleton for the app's whole life. catches it in Development. The full lifetime rules are in the .
What is ?
The provider of the current request's scope. You can resolve from it, but that hides what a class needs. Constructor injection is the normal way, and it uses that same scope.
Are controllers scoped?
Controllers are not registered in the container by default. ASP.NET Core builds a new one for each request and fills its constructor from the request's scope, so in practice there is one per request.
Traps
- Don't say
Scoped means one per user or per session.SayOne per scope. In ASP.NET Core that is one per HTTP request. - Don't say
Resolving it fromSayThat is the root: in Production the object lives until the app stops. Open a scope with .app.Servicesworks on my machine. - Don't say
Scoped services are thread-safe because each request has its own.SayOnly if it is used one call at a time. Parallel tasks () inside one request share the same scoped object; see .
A worked answer from this app's research, not a quote: Copilot suggested making a singleton to fix an . The candidate rejected it, because is scoped by default and not thread-safe, so never a singleton. The real bug was a background job holding on to a scoped service; the fix was a scope from , plus a test like the one above.