- Home
- .NET code examples
- Dependency injection code example for ASP.NET Core
Dependency injection code example for ASP.NET Core
We have a number of dependency injection tutorials which include explaining the different service lifetimes, injecting services into classes, keyed services, creating a new scope, unit testing and the common mistakes of dependency injection.
Download the code example
You'll need to fill out the code example form. We will send you an email where you can download the code example.
The code example will be in a zip file and will include all the dependency injection tutorials separated by a numeric folder name.
Software
This is the software that will need to be installed onto your machine.
- Visual Studio 2022. Version 17.12.0 or above. It will work with the free community version.
- .NET 9 SDK. Version 9.0.0 or above.
Tutorials
Here are the different dependency injection tutorials available:
How to use lifetimes in ASP.NET Core dependency injection?
You can read more about how to use the different lifetimes in ASP.NET Core or you can watch the video:
In Visual Studio, open up 01/RoundTheCode.DI._01.sln
from the code example zip file that you downloaded.
You can test the different ways to register a service by changing the dependencyTypeEnum
variable in Program.cs
. You can change it to:
Type
- This registers a service by providing the types as parametersGeneric
- This registers a service by providing the types using the generic class extension methodImplementationType
- Allows you to explicitly create the service instance. The types are provided as parameters.ImplementationGeneric
- Allows you to explicitly create the service instance. The types are provided using the generic class extension method
Run the application and it will load up the Scalar OpenAPI document on https://localhost:7058/scalar/v1
.
To test the differences with the singleton, scoped and transient, run https://localhost:7058/api/WebApi/service-lifetimes
.
If you want to test how the transient service lifetime works when injected into a different part of the request, run https://localhost:7058/mvc/service-lifetimes
.
How to inject services in ASP.NET Core dependency injection
You can read more about how to inject services in ASP.NET Core or you can watch the video:
In Visual Studio, open up 02/RoundTheCode.DI._02.sln
from the code example zip file that you downloaded.
Run the application and it will load up the Scalar OpenAPI document on https://localhost:7058/scalar/v1
.
Here is what you can test:
Minimal APIs
- Endpoint that injects services -
https://localhost:7058/minimal/categories
Web APIs
- Endpoint that uses services that are referenced in private readonly fields -
https://localhost:7058/api/WebApi/categories
- Injects a service through an endpoint -
https://localhost:7058/api/WebApi/computers
- Using a class in an endpoint that injects a service using primary constructors -
https://localhost:7058/api/WebApi/primary
MVC controllers and Razor views
- Razor view that injects services -
https://localhost:7058/Mvc/categories
- The
[FromService]
attribute used to inject a service through an endpoint -https://localhost:7058/Mvc/computers
Breakpoints
- The
CategoryMiddleware
class is run on every request. You can add a breakpoint to see how it behaves when injecting services
Use keyed services for multiple implementations of a service
You can read more about how to register and inject keyed services or you can watch the video:
In Visual Studio, open up 03/RoundTheCode.DI._03.sln
from the code example zip file that you downloaded.
You can test the different ways to register a keyed service by changing the dependencyTypeEnum
variable in Program.cs
. You can change it to:
Type
- This registers a keyed service by providing the types as parametersGeneric
- This registers a keyed service by providing the types using the generic class extension methodImplementationType
- Allows you to explicitly create the service instance. The types are provided as parameters.ImplementationGeneric
- Allows you to explicitly create the service instance. The types are provided using the generic class extension method
Run the application and it will load up the Scalar OpenAPI document on https://localhost:7058/scalar/v1
.
Here is what else you can test:
Minimal APIs
- Endpoint that injects keyed services -
https://localhost:7058/minimal/service-lifetimes
Web APIs
- Endpoint that uses services that are referenced in private readonly fields -
https://localhost:7058/api/WebApi/service-lifetimes
- Injects a service through an endpoint -
https://localhost:7058/api/WebApi/product-singleton-1-utc
- Add two different implementations of the same non-keyed service and injecting the service -
https://localhost:7058/api/WebApiStorage/last-category-type
- Add two different implementations of the same non-keyed service and injecting the service using an
IEnumerable
-https://localhost:7058/api/WebApiStorage/category-types
- Add two different implementations of the same service using keyed services -
https://localhost:7058/api/WebApiStorage/category-keyed-types
Primary constructors
- Using a class in a Web API controller endpoint that injects a service using primary constructors -
https://localhost:7058/api/WebApiStorage/category-primary-types
MVC controllers and Razor views
- Razor view that injects services -
https://localhost:7058/mvc/service-lifetimes
Breakpoints
- The
ProductMiddleware
class is run on every request. You can add a breakpoint to see how it behaves when injecting services
GetService or GetRequiredService in IServiceProvider?
You can read more about whether to use GetService
or GetRequiredService
when using the IServiceProvider
type or you can watch the video:
In Visual Studio, open up 04/RoundTheCode.DI._04.sln
from the code example zip file that you downloaded.
Run the application and it will load up the Scalar OpenAPI document on https://localhost:7058/scalar/v1
.
This is what you can test:
Minimal APIs
- Resolve services that have been registered -
https://localhost:7058/minimal/service-provider
- Try to resolve services that haven't been registered using
GetService
andGetKeyedService
-https://localhost:7058/minimal/service-provider-null
- Try to resolve a service that hasn't been registered using
GetRequiredService
-https://localhost:7058/minimal/service-provider-null-required-service
. This should throw anInvalidOperationException
- Try to resolve a keyed service that hasn't been registered using
GetRequiredKeyedService
-https://localhost:7058/minimal/service-provider-null-required-keyed-service
. This should throw anInvalidOperationException
You can append ?type=HttpContext
to each of these endpoints to resolve the services using HttpContext.RequestServices
.
Web APIs
- Resolve services that have been registered -
https://localhost:7058/api/WebApi/service-provider
- Try to resolve services that haven't been registered using
GetService
andGetKeyedService
-https://localhost:7058/api/WebApi/service-provider-null
- Try to resolve a service that hasn't been registered using
GetRequiredService
-https://localhost:7058/api/WebApi/service-provider-null-required-service
. This should throw anInvalidOperationException
- Try to resolve a keyed service that hasn't been registered using
GetRequiredKeyedService
-https://localhost:7058/api/WebApi/service-provider-null-required-keyed-service
. This should throw anInvalidOperationException
You can append ?type=HttpContext
to each of these endpoints to resolve the services using HttpContext.RequestServices
.
MVC controllers and Razor views
- Resolve services that have been registered -
https://localhost:7058/Mvc/service-provider
- Try to resolve services that haven't been registered using
GetService
andGetKeyedService
-https://localhost:7058/Mvc/service-provider-null
- Try to resolve a service that hasn't been registered using
GetRequiredService
-https://localhost:7058/Mvc/service-provider-null-required-service
. This should throw anInvalidOperationException
- Try to resolve a keyed service that hasn't been registered using
GetRequiredKeyedService
-https://localhost:7058/Mvc/service-provider-null-required-keyed-service
. This should throw anInvalidOperationException
You can append ?type=HttpContext
to each of these endpoints to resolve the services using HttpContext.RequestServices
.
Primary constructors
- Use
GetService
,GetRequiredService
,GetKeyedService
andGetRequiredKeyedService
by injecting theIServiceProvider
into a primary constructor class -https://localhost:7058/api/WebApiPrimary
Breakpoints
- You can put a breakpoint in
Program.cs
to test resolving services before the application runs usingapp.Services
- You can put a breakpoint in the
InvokeAsync
method inside theServiceProviderMiddleware
class to test theIServiceProvider
type in middleware. You can change theServiceProviderTypeEnum
in theGetServiceTypeInstance
method toServiceProviderTypeEnum.HttpContext
to test resolving the services fromHttpContext.RequestServices
How do you resolve scoped services in a background service?
You can read more about how to resolve scoped services in a background service, or watch the video.
In Visual Studio, open up 05/RoundTheCode.DI._05.sln
from the code example zip file that you downloaded.
There are two projects contained within the solution.
Hosted service
RoundTheCode.DI.Worker
is a background service that creates a new scope and resolves the ICategoryScopedService
, ICategoryTransientService
services and the ICategoryStorageService
keyed service with that scope.
In Visual Studio 2022, go to Project and Configure Startup Projects in the top menu. On the left-hand side, select Common Properties and Configure Startup Projects. Select the Single Startup Project: radio button, select RoundTheCode.DI.Worker
and press OK.
Run the application. It should output three timestamps to the console window every second.
Web API
RoundTheCode.DI
has a WebApiController
class which is a controller that has methods which use multithreading.
In Visual Studio 2022, go to Project and Configure Startup Projects in the top menu. On the left-hand side, select Common Properties and Configure Startup Projects. Select the Single Startup Project: radio button, select RoundTheCode.DI
and press OK.
Run the application and it will load up the Scalar OpenAPI document on https://localhost:7058/scalar/v1
. This is what you can test:
https://localhost:7058/api/WebApi/multiple-threads-unique-scope
- This returns an empty 200 response. It runs three tasks simultaneously which each task creating a new scope and outputs a task number and datestamp to the console. The empty response is returned when all three tasks are completed. It should output the task number and datestamp for each task.https://localhost:7058/api/WebApi/multiple-threads-shared-scope
- This returns an empty 200 response. It runs three tasks simultaneously but shares the same scope with each one. It outputs a task number and datestamp to the console. The empty response is returned when any of the three tasks are completed. You'll probably find that not all of the tasks will output a task number and datestamp as the scope will have already been disposed before resolving the service.
How to write xUnit tests for dependency injection services
You can read more about how to write xUnit tests for dependency injection services, or watch the video:
In Visual Studio, open up 06/RoundTheCode.DI._06.sln
from the code example zip file that you downloaded. There are two projects contained within the solution.
RoundTheCode.DI
- ASP.NET Core Web APIRoundTheCode.DI.Tests
- xUnit test project that unit test classes that are inRoundTheCode.DI
In the top menu, you can go to Test and Test Explorer. This allows you to run all four tests that are in the xUnit test project. They should all pass.
Common errors to avoid in ASP.NET Core dependency injection
You can read more about the common errors to avoid in ASP.NET Core dependency injection, or watch the video:
In Visual Studio, open up 07/RoundTheCode.DI._07.sln
from the code example zip file that you downloaded.
Run the application and it will load up the Scalar OpenAPI document on https://localhost:7058/scalar/v1
.
Here is what you can test:
Failing to register a dependency
- In
Program.cs
, set theexception
variable toExceptionEnum.NoRegisterResolution
(This is the default value) - Run
https://localhost:7058/api/webapinotadded
and you'll get the exception - Resolve it in
Program.cs
by setting theexception
variable toExceptionEnum.NoRegisterResolution
Circular dependency
- In
Program.cs
, set theexception
variable toExceptionEnum.CircularDependencyException
- Run the application and you will get the exception
Injecting a scoped service lifetime into a singleton
- In
Program.cs
, set theexception
variable toExceptionEnum.ScopedIntoSingletonException
- Run the application and you will get the exception
- Resolve it in
Program.cs
by setting theexception
variable toExceptionEnum.ScopedIntoSingletonResolution
and runhttps://localhost:7058/api/webapisingletonscope
to resolve a scoped service using a new scope
Ambiguous constructors
- In
Program.cs
, set theexception
variable toExceptionEnum.AmbiguousException
- Run the application and you will get the exception
- Resolve it in
Program.cs
by setting theexception
variable toExceptionEnum.AmbiguousResolution
. No exception will be thrown
Sharing scope and transient service lifetimes across multiple threads
- In
Program.cs
, set theexception
variable toExceptionEnum.MultipleThreads
- Run
https://localhost:7058/api/WebApiSharedScope/shared-service
and then view the console application logs to see one datestamp outputted - Run
https://localhost:7058/api/WebApiSharedScope/shared-service-fix
and then view the console application logs to see two datestamps outputted
Related pages
