In ASP.NET Core dependency injection, a scoped service is created once within a scope and reused to resolve dependencies throughout that scope. ASP.NET Core starts a new scope for each HTTP request, so components handling one request can share an instance without sharing it with the next request. section 14.4.3
Choose the registration that matches the sharing you need:
- AddSingleton<T, U>() uses one instance for subsequent dependencies. section 14.4
- AddTransient<T, U>() creates a new instance for each dependency. section 14.4
- AddScoped<T, U>() reuses an instance within one scope, such as an HTTP request. section 14.4
Check reuse with a GUID
Register `builder.Services.AddScoped<IResponseFormatter, GuidService>();` in Program.cs, then declare three `IResponseFormatter` parameters on a middleware `Invoke` method. Request `/middleware/class`: all three formatted messages show the same GUID. Reload the page: the new request gets a new GUID. With `AddTransient` instead, the three independently resolved parameters show different GUIDs even within one request. section 14.4.3
Resolve scoped services inside a scope. An endpoint helper that creates its endpoint from the application service provider during route setup can fail when it requests a scoped service: that work happens outside the request scope. Create and resolve the endpoint while handling the request instead. For work performed at application startup, create a scope with `CreateScope()` before requesting scoped services; Identity seeding needs this for `UserManager<T>` and `RoleManager<T>`. section 14.4.3 section 39.3.4
Filters can use the same lifetime. Register a filter with `AddScoped`, then obtain it as a service—for example, with `ServiceFilter`. Two uses during one request share the filter instance; reloading creates another. Entity Framework Core context scopes likewise need careful management to avoid stale data. section 30.5.2 section 36.6


