Dependency Injection Into Views In ASP.NET Core MVC

Introduction
 
ASP.NET Core has built-in support for dependency injection. The dependency injection in ASP.NET Core is not limited to middleware, Controllers, and Models but it also supports DI into Views. This is very useful in View-specific services like localization. Using View dependency, we can bypass the Controller for fetching the data. As a good practice, all the data must pass from the Controller.
 
There are many ways to provide the data to the View, e.g. ViewBag, ViewData, and ViewModel. From ASP.NET Core, one way to supply the data is Custom service that is used via DI (dependency injection). However, it is not a best practice.
 
@inject directive
 
The @inject directive is used to inject the dependency into a View. This directive has the following syntax.
  1. @inject <type> <instance name>  
  • @inject is the directive that is used to inject the dependencies
  • <type> is service class type
  • <instance name> is the instance name of service by which we can access the service methods
There are three easy steps to achieve this.
  1. Create service
  2. Register the service in Startup class
  3. Inject the service into View
Create Service
 
Here, Service is nothing but a C# class that contains public methods.

To demonstrate the example, I have created a service class and created a method (GetCities) that returns the list of city names. This method returns List<string> ().
  1. namespace DIinView.Models  
  2. {  
  3.     using System.Collections.Generic;  
  4.     public class CityModelService  
  5.     {  
  6.         public List<string> GetCities()  
  7.         {  
  8.             return new List<string>()  
  9.             {  
  10.                 "Ahmedabad""Gandhinagar""Bhavnagar""Surat""Bhuj"  
  11.             };  
  12.         }  
  13.     }  
  14. }  
Register the service in Startup Class
 
To use the created service into the View, we need to register this service into ConfigureServices method of Startup class. There are three ways to register a service within Startup class. Each method has its own scope and based on the requirement, we can register.
 
 
 
We can register a service using AddTransient method. This method is used to map the abstract types to concrete services which are instantiated separately for every object that requires this service. The life of the instance of service is limited to that View only if we register the service using AddTransient method. In this method, Transient lifetime services are created each time when requested. It can be best to use for lightweight, stateless services.
  1. public void ConfigureServices(IServiceCollection services)  
  2. {  
  3.     services.AddMvc();  
  4.     services.AddTransient<CityModelService>();  
  5. }  
We can also register a service as Singleton that creates a single instance throughout the application. It will create the instance of service when it is called the first time and reuses this same object in all the calls.
  1. public void ConfigureServices(IServiceCollection services)  
  2. {  
  3.     services.AddMvc();  
  4.     services.AddSingleton<CityModelService>();  
  5. }  
Another approach to register a service is scoped. In this approach, service is created once per request within scope. It is equivalent to Singleton in current scope for request. It creates one instance on every HTTP request.
  1. public void ConfigureServices(IServiceCollection services)  
  2. {  
  3.     services.AddMvc  
  4.     services.AddScoped<CityModelService>();  
  5.               
  6. }  
If we do not register the service in Startup class and try to use in View, it will throw an Invalid Operation Exception: "No Service for type xxx has been registered." This error occurred as we did not register the service in a dependency injection container.
 
 
 
Inject the service in view and use its method
 
The final step is to inject the service into View and use a service method. We can inject the dependency using @inject directive.
  1. @{  
  2.     ViewData["Title"] = "City List";  
  3. }  
  4.   
  5. @inject DIinView.Models.CityModelService cityService  
  6.   
  7. <h3>My nearest City List</h3>  
  8. <ul>  
  9.     @foreach (var name in cityService.GetCities())  
  10.     {  
  11.         <li>@name</li>  
  12.     }  
  13. </ul>  
Output
 
 
 
Summary
 
ASP.NET Core MVC allows us to inject the dependency into the View. This can be useful for populating the UI elements such as dropdown list. However, the best practice says that "all the data rendered by View should come from Controller class". View injection helps us to minimize the amount of code required on Controllers.

You can view or download the source code from the following GitHub link.