Dependency
Injection is the design pattern that help us to create application
which loosely coupled. This means that object should only have those
dependency that required during complete task. The main advantages of DI
(Dependency Injection) is our application loosely coupled and has
provide greater maintainability, testability and also re-usability. It
is loosely coupled because dependency required by the class are injected
from outer world rather than created them self directly win-in code.
There are three type of DI: Construction Injection, Setter Injection, Interface based Injection. The Construction Injection type of DI accept their dependency at constructor level it means that when create object of the class, their dependency pass through the constructor of the class. It provide the strong dependency contract between objects. The Setter Injection is also known as property injection. In this type of dependency injection, dependency pass through public property instead of constructor. It allows us to pass the dependencies when they required. It does not provide strong dependency contract between objects. The interface-based dependency injection can be achieved by creating the common interface and other classes are implements this interface to inject the dependency. In this type of DI, we can use either constructor injection or setter injection.
There is a built-in support of dependency injection in ASP.net Core. This supports is not limited to middleware, but also support in Controllers, views, and model as well. There are two type of service container provided by the ASP.net core: Framework Services and Application Services. The framework services are service that are provided by the ASP.net core such as ILoggerFactory etc. The application services are the custom services created base on our requirement.
Example In the following example, I have created HelloWorld service. This service has method called "SaysHello” that simply returns "Hello " string. I have also implement this service using interface.
Now this “HelloWorld” service is available to use in the controller. We can inject this service as a dependency in constructor.
The constructor dependency injection behavior resolved the service by
either IServiceProvider or ActivatorUtilities. The ActivatorUtilities
allows to creation of the object without service registration in the DI.
The model binder, tag helper and controller service are used
ActivatorUtilities. The service required always public constructor.
ASP.net core is only support the single constructor for the controller
class which requesting the service. If we have more than one
constructor, ASP.net core MVC raised the error.
View injection can be used to populate the UI element such as
dropdown. The common dropdown such city/state dropdown can be populate
from the service. Rendering such things from the service is standard
approach in ASp.net core MVC. Alternatively, we can use viewbag and
Viewdata to populate dropdown. The directive @inject is also be used to
override the injected service. For example, we are using Html helper
service for the rendering the Html tags such as dropdown, textbox, etc.
We can replace this service with our own service using @inject
directive.
There are three type of DI: Construction Injection, Setter Injection, Interface based Injection. The Construction Injection type of DI accept their dependency at constructor level it means that when create object of the class, their dependency pass through the constructor of the class. It provide the strong dependency contract between objects. The Setter Injection is also known as property injection. In this type of dependency injection, dependency pass through public property instead of constructor. It allows us to pass the dependencies when they required. It does not provide strong dependency contract between objects. The interface-based dependency injection can be achieved by creating the common interface and other classes are implements this interface to inject the dependency. In this type of DI, we can use either constructor injection or setter injection.
There is a built-in support of dependency injection in ASP.net Core. This supports is not limited to middleware, but also support in Controllers, views, and model as well. There are two type of service container provided by the ASP.net core: Framework Services and Application Services. The framework services are service that are provided by the ASP.net core such as ILoggerFactory etc. The application services are the custom services created base on our requirement.
Dependency injection into controllers
The dependency required by the ASP.net MVC controller requested explicitly via their constructors (Constructor injection type) and this dependency are available for the controller. Some of the dependency are injected to only the controller action as a parameter. ASP.net core has built-in support for constructor-based dependency. The dependency required by the controller are simply adding a service type to the controller in the constructor. The ASP.net core will identify the service type and try to resolve the type. It would be the good design if service defined using interfaces but it is not always true.Example In the following example, I have created HelloWorld service. This service has method called "SaysHello” that simply returns "Hello " string. I have also implement this service using interface.
The next step is to add this service to the service container, so that when controller is requested for service, it is available to use. We can add the service to the service container in ConfigureServices method of startup class. There are three different life option available: Transient, Scoped, and Singleton. We will discuss this later part in the article.
- namespace DepedencyInjectionExample.Service
- {
- public interface IHelloWorldService
- {
- string SaysHello();
- }
- public class HelloWorldService : IHelloWorldService
- {
- public string SaysHello()
- {
- return "Hello ";
- }
- }
- }
If we not register the service to the ASP.net core service container, it will throw the exception as following.
- public void ConfigureServices(IServiceCollection services)
- {
- ….
- …
- services.AddTransient<IHelloWorldService, HelloWorldService>();
- …
- …
- }
Once the service has been configured correctly and injected in to the controller, it should display Hello message as expected.
- using DepedencyInjectionExample.Models;
- using Microsoft.AspNetCore.Mvc;
- using DepedencyInjectionExample.Service;
- namespace DepedencyInjectionExample.Controllers
- {
- public class HomeController : Controller
- {
- IHelloWorldService _helloWorldService;
- public HomeController(IHelloWorldService helloWorldService)
- {
- _helloWorldService = helloWorldService;
- }
- }
- }
Inject the dependency in controller action
Some time, we required dependency to the particular controller action method not to throughout controller. ASP.net core MVC allows us to inject the dependency to particular action using "FromServices" attribute. This attribute tell the ASP.net core framework that parameter should be retrieve from the service container.The property injection is not supported by the ASP.net core but we call the service instance manually and called service methods.
- using DepedencyInjectionExample.Service;
- using Microsoft.AspNetCore.Mvc;
- namespace DepedencyInjectionExample.Controllers
- {
- public class DemoController : Controller
- {
- public IActionResult Index([FromServices] IHelloWorldService helloWorldService)
- {
- ViewData["MyText"] = helloWorldService.SaysHello() + "Jignesh!";
- return View();
- }
- }
- }
Get the service instance manually
There is another way to get dependency services from the service container. In this method, service is not injected in controller constructor or in action method as parameter. Using method "GetService" of "HttpContext.RequestServices" property, we can get dependent services configured with Service container. This is also known as property injection. Following is the example.
- public IActionResult Index1()
- {
- var helloWorldService = (IHelloWorldService)this.HttpContext.RequestServices.GetService(typeof(IHelloWorldService));
- ViewData["MyText"] = helloWorldService.SaysHello() + "Jignesh Trivedi!";
- return View("index");
- }
Service Lifetime
ASP.net core allow us to specify the lifetime for registered services. The service instance gets disposed automatically based on specified life-time. So we do not care about the cleaning these dependency, it will take care by ASP.net core framework. There are three type of life-times.Singleton
ASP.net core will create and share a single instance of the service through the application life. The service can be added as singleton using AddSingleton method of IServiceCollection. ASP.net core create service instance at the time of registration and subsequence request use this service instance. Here, we do not required to implement singleton design pattern and single instance maintained by the ASP.net core itself.
- public void ConfigureServices(IServiceCollection services)
- {
- ….
- …
- services.AddSingleton<IHelloWorldService, HelloWorldService>();
- ….
- …
- }
Transient
ASP.net core will create and share an instance of the service every time to the application when we ask for it. The service can be added as Transient using AddTransient method of IServiceCollection. This life-time can be used in stateless service. It is way to add lightweight service.
- public void ConfigureServices(IServiceCollection services)
- {
- ….
- …
- services.AddTransient<IHelloWorldService, HelloWorldService>();
- ….
- …
- }
Scoped
ASP.net core will create and share an instance of the service per request to the application. It means that single instance of service available per request. It will create a new instance in new request. The service can be added as scoped using AddScoped method of IServiceCollection. We need to take care while, service registered via Scoped in middleware and inject the service in the Invoke or InvokeAsync methods. If we inject dependency via constructor, it behave like singleton object.
- public void ConfigureServices(IServiceCollection services)
- {
- ….
- …
- services.AddScoped<IHelloWorldService, HelloWorldService>();
- ….
- …
- }
Dependency injection into Views
ASP.net core can also able to inject the dependency to View. This is very useful to inject service related view such as localization. This method will bypass the controller call and fetch data directly from the service. We can inject the service dependency into the view using @inject directive. The syntax is as following to use this directive. Here we need to pass the service type that need to inject and service instance name that used to access the service method.Example In the following example, I have used same service that created in preceding section and injected in the view using @inject directive and using the service instance, we can call the service method in to the view.
- @inject <type> <instance name>
- @{
- ViewData["Title"] = "DIToView";
- }
- @inject DepedencyInjectionExample.Service.IHelloWorldService helloWorldService
- <h4>DI To View</h4>
- <h5>
- @helloWorldService.SaysHello() Reader!!!
- </h5>
Summary
Dependency injection is the design pattern that allow us to inject the dependency to the class from outer world rather than creating with in class. This will help us to create loosely coupled application so that it has provided greater maintainability, testability and also reusability. There is a built-in support of dependency injection in ASP.net Core. This supports is not limited to middleware, but also support in Controllers, views, and model as well. There are three easy step to use Dependency injection into ASP.net core MVC application.- Create the service
- Register the service into ConfigureService method of the startup class, so that it available to use
- Inject the service where you want to use
ASP.net core allow us to specify the lifetime for registered services based on our requirement to use the service. The service can either register as Singleton, Transient or Scoped.