Learn how to use constructor injection, property injection, method injection, and the service locator pattern in ASP.NET Core MVC 5, along with their caveats. Credit: Thinkstock Dependency injection is a first-class citizen in ASP.NET Core MVC 5. Part of the new .NET 5, ASP.NET Core MVC 5 is the latest version of Microsoft’s framework for building web apps and APIs using the model-view-controller design pattern. In this article we’ll take a deep dive into dependency injection in ASP.NET Core MVC 5 as well as learn the best practices that one should follow when working with dependency injection. To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here. Create an ASP.NET MVC 5 project in Visual Studio 2019 First off, let’s create an ASP.NET Core project in Visual Studio 2019. Following these steps will create a new ASP.NET Core MVC 5 project in Visual Studio 2019. Launch the Visual Studio IDE. Click on “Create new project.” In the “Create new project” window, select “ASP.NET Core Web App (Model-View-Controller)” from the list of templates displayed. Click Next. In the “Configure your new project” window, specify the name and location for the new project. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences. Click Next. In the “Additional Information” window shown next, select .NET 5.0 as the target framework from the drop-down list at the top. Leave the “Authentication Type” as “None” (default). Ensure that the check boxes “Enable Docker,” “Configure for HTTPS,” and “Enable Razor runtime compilation” are unchecked as we won’t be using any of those features here. Click Create. A new ASP.NET Core MVC 5 project will be created. We’ll use this project in the subsequent sections of this article. Dependency lifetimes in ASP.NET Core MVC 5 When working with ASP.NET Core MVC 5 you must register a service to be able to use it. When you register a service with the container, you can specify the service lifetime. There are three possible lifetimes: Transient: The components of the service will not be shared but will be created each time they are requested. Scoped: One instance of the components per scope (i.e., one instance per request to the application) will be created. Components are reused within the scope. Singleton: The components of the service will be created once for the lifetime of the application and will be shared by all requests. You should write your code to register dependencies using any of the above three approaches in the ConfigureServices method of the Startup class. You can learn more about making services available via dependency injection from my earlier article here. Dependency injection example in ASP.NET Core MVC 5 Let’s now create the required classes and interfaces to implement dependency injection. The Author class given below is an entity class. public class Author { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } The AuthorService class extends the IAuthorService interface and implements its methods. public class AuthorService : IAuthorService { public bool CreateAuthor(Author author) { //Write your own implementation here return true; } public List<Author> GetAllAuthors() { List<Author> authors = new List<Author>(); //Write your own implementation here return authors; } } public interface IAuthorService { bool CreateAuthor(Author author); List<Author> GetAllAuthors(); } Types of dependency injection The built-in dependency injection provider in ASP.NET Core is not as feature-rich as containers like StructureMap and Ninject, but it is quite fast and easy to configure and use. We can use the following types of dependency injection in ASP.NET Core MVC 5: Constructor injection: The injector passes the dependency via the constructor of the client class. Property injection: The injector passes the dependency via the public property of the client class. Method injection: The injector passes the dependency via a method parameter of a public method pertaining to the client class Implement constructor injection in ASP.NET Core MVC 5 The following code snippet illustrates how Constructor injection can be implemented. public class HomeController : Controller { private readonly IAuthorService _authorService; public HomeController(IAuthorService authorService) { _authorService = authorService; } //Other methods } Constructor injection best practices When using constructor injection, you should mention all required dependencies in the parameters of the constructor. You should also assign the dependency to a read-only object. Implement property injection in ASP.NET Core MVC 5 Although ASP.NET Core MVC 5 doesn’t include support for property injection using its built-in dependency injection container, it’s easy to overcome this limitation. The following code snippet shows how you can implement property injection in ASP.NET Core MVC 5. public class AuthorService : IAuthorService { public ILogger<AuthorService> Logger { get; set; } public bool CreateAuthor(Author author) { Logger = NullLogger<AuthorService>.Instance; //Write your own implementation here return true; } public List<Author> GetAllAuthors() { List<Author> authors = new List<Author>(); //Write your own implementation here return authors; } } Property injection best practices You must ensure that you use the null object pattern or validate that the dependency is null before you pass it using the property injection technique. To avoid runtime errors, you should only allow non-null objects. Furthermore, you should take advantage of property injection only for optional dependencies, i.e., for dependencies without which the service will still work. Implement method injection in ASP.NET Core MVC 5 Consider the following three interfaces: public interface IBusinessLogic { void SetDbManager(ISQLServerManager iSQLServerManager); } public interface ISQLServerManager { //Write your own implementation here } public interface IOracleManager { //Write your own implementation here } The IBusinessLogic interface represents the type that contains the declaration of members related to the business logic, which is given below. The other two interfaces represent manager classes for SQL Server and Oracle Database. Ideally, these interfaces should include the declarations of database CRUD operations. public class AuthorBusinessLogic : IBusinessLogic { ISQLServerManager _iSQLServerManager; public void SetDbManager(ISQLServerManager iSQLServerManager) { _iSQLServerManager = iSQLServerManager; } } The AuthorBusinessLogic class implements the IBusinessLogic class and contains one method, named SetDbManager. The SetDbManager method receives an instance of any of the two classes (not shown in this example for brevity) that implement the two interfaces shown earlier. It then assigns this object to the _iSQLServerManager instance. And that’s it! You can now write your own code to pass dependencies using method injection. Method injection best practices You must ensure that the dependency is not null before you pass it using the method injection technique. Implement the service locator pattern in ASP.NET Core MVC 5 The service locator design pattern is yet another way in which you can retrieve dependencies. The service locator pattern allows code to be added dynamically at run time — even without recompiling or restarting the application. So, applications can selectively add or remove items from the service locator dynamically (it uses a central registry). The example code snippet below illustrates how this pattern can be used. public class BookService { private readonly IBookRepository _bookRepository; public BookService(IServiceProvider serviceProvider) { _bookRepository = serviceProvider .GetRequiredService<IBookRepository>(); } //Other methods } Service locator pattern best practices The service locator pattern can be used when we would like to avoid dependencies between implementations of an interface and the client code. This pattern can also be used when we would like to locate services that are otherwise costly to create or manage. However, we should avoid using the service locator pattern in most cases because it makes the dependencies implicit rather than explicit. That is, we are not able to view the dependencies when creating the instance of the service. Dependency injection is a technique that facilitates loose coupling and improves code maintenance and testability. You can learn more about the core concepts related to dependency injection in my earlier article on the topic. How to do more in ASP.NET Core: How to use security headers in ASP.NET Core MVC 5 How to handle unknown actions in ASP.NET Core 5 MVC How to overload action methods in ASP.NET Core 5 MVC How to use multiple implementations of an interface in ASP.NET Core How to use IHttpClientFactory in ASP.NET Core How to use the ProblemDetails middleware in ASP.NET Core How to create route constraints in ASP.NET Core How to manage user secrets in ASP.NET Core How to build gRPC applications in ASP.NET Core How to redirect a request in ASP.NET Core How to use attribute routing in ASP.NET Core How to pass parameters to action methods in ASP.NET Core MVC How to use API Analyzers in ASP.NET Core How to use route data tokens in ASP.NET Core How to use API versioning in ASP.NET Core How to use Data Transfer Objects in ASP.NET Core 3.1 How to handle 404 errors in ASP.NET Core MVC How to use dependency injection in action filters in ASP.NET Core 3.1 How to use the options pattern in ASP.NET Core How to use endpoint routing in ASP.NET Core 3.0 MVC How to export data to Excel in ASP.NET Core 3.0 How to use LoggerMessage in ASP.NET Core 3.0 How to send emails in ASP.NET Core How to log data to SQL Server in ASP.NET Core How to schedule jobs using Quartz.NET in ASP.NET Core How to return data from ASP.NET Core Web API How to format response data in ASP.NET Core How to consume an ASP.NET Core Web API using RestSharp How to perform async operations using Dapper How to use feature flags in ASP.NET Core How to use the FromServices attribute in ASP.NET Core How to work with cookies in ASP.NET Core How to work with static files in ASP.NET Core How to use URL Rewriting Middleware in ASP.NET Core How to implement rate limiting in ASP.NET Core How to use Azure Application Insights in ASP.NET Core Using advanced NLog features in ASP.NET Core How to handle errors in ASP.NET Web API How to implement global exception handling in ASP.NET Core MVC How to handle null values in ASP.NET Core MVC Advanced versioning in ASP.NET Core Web API How to work with worker services in ASP.NET Core How to use the Data Protection API in ASP.NET Core How to use conditional middleware in ASP.NET Core How to work with session state in ASP.NET Core How to write efficient controllers in ASP.NET Core Related content feature What is Rust? Safe, fast, and easy software development Unlike most programming languages, Rust doesn't make you choose between speed, safety, and ease of use. Find out how Rust delivers better code with fewer compromises, and a few downsides to consider before learning Rust. By Serdar Yegulalp Nov 20, 2024 11 mins Rust Programming Languages Software Development how-to Kotlin for Java developers: Classes and coroutines Kotlin was designed to bring more flexibility and flow to programming in the JVM. Here's an in-depth look at how Kotlin makes working with classes and objects easier and introduces coroutines to modernize concurrency. By Matthew Tyson Nov 20, 2024 9 mins Java Kotlin Programming Languages analysis Azure AI Foundry tools for changes in AI applications Microsoft’s launch of Azure AI Foundry at Ignite 2024 signals a welcome shift from chatbots to agents and to using AI for business process automation. By Simon Bisson Nov 20, 2024 7 mins Microsoft Azure Generative AI Development Tools news Microsoft unveils imaging APIs for Windows Copilot Runtime Generative AI-backed APIs will allow developers to build image super resolution, image segmentation, object erase, and OCR capabilities into Windows applications. By Paul Krill Nov 19, 2024 2 mins Generative AI APIs Development Libraries and Frameworks Resources Videos