Mastering ASP.NET Core 2.1 : Instructor-led online course by Bipin Joshi in November 2018. Read more...
Live instructor-led online courses in ASP.NET Core and Design Patterns. Registration is open for November 2018 batch. More details are available here.

Various ways of accessing DI services

ASP.NET Core provides an inbuilt Dependency Injection framework that you can utilize to register and access services. One of my earlier article explains various lifetime options that you can use while registering a service. Once a service is registered with the DI container you can get an instance of the service using what is known as constructor injection. Although constructor injection is the most common way of accessing the registered services, there are a few more options that can be used to accomplish the task. To that end this article discusses these alternatives with a simple example.

As an example we will create a simple class named NotificationHelper that is based on INotificationHelper interface. They are shown below :

public interface INotificationHelper
{
    void Notify();
}

public class NotificationHelper:INotificationHelper
{
    public void Notify()
    {
        //do something here
    }
}

The code shown above is quite straightforward. The actual implementation of INotificationHelper is not important for the subject of this article. So, we will keep the things quite simple.

Now, the NotificationHelper is registered with the DI container using AddScoped() method. This code will go inside the ConfigureServices() method of the Startup and is shown below :

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddScoped<INotificationHelper,NotificationHelper>();

}

Once our INotificationHelper is registered with the DI framework we can access it in our controllers using the approaches discussed below.

Constructor injection

Constructor injection is possibly the most common way of accessing the DI services inside a controller. As the name suggests, constructor injection approach injects a service instance in the constructor of the controller. You can then store the object in a member variable so that the service can be accessed in any of the actions of the controller.

The following code shows INotificationHelper being injected into the constructor of HomeController :

public class HomeController : Controller
{
    private INotificationHelper helper = null;

    public HomeController(INotificationHelper helper)
    {
        this.helper = helper;
    }
}

As you can see the constructor takes a parameter of type INotificationHelper. At runtime the DI framework will create the required instance and supply it to the constructor. Inside, you hold a reference to the INotificationHelper injected object into a private member variable - helper.

Now you can use the helper object in any action as illustrated below :

public IActionResult Index()
{
    helper.Notify();

    return View();
}

Action injection

Constructor injection works great when a service is required in many of the actions. At times you need a particular service only in one or two actions. In such cases rather than injecting the service in the controller you can inject it into those actions under consideration. The action injection is facilitated by [FromServices] attribute. The following code will make the use of [FromServices] clear.

public IActionResult Index([FromServices]INotificationHelper helper)
{
    helper.Notify();

    return View();
}

The above code shows the modified Index() action. This time the Index() action takes INotificationHelper parameter. More importantly this parameter is decorated with [FromServices] attribute. Now DI framework will inject the service instance directly into the Index() action at the time of invoking it.

Injecting IServiceProvider

Imagine a case where you need to inject many DI services into a controller. Obviously your controller needs to have those many parameters. Moreover in some cases you may not know in advance as to which DI service you are going to need at runtime. In such cases you can inject IServiceProvider into the controller. IServiceProvider allows you to access any of the registered DI services at runtime. The following code will make it clear.

public class HomeController : Controller
{
    private IServiceProvider provider = null;

    public HomeController(IServiceProvider provider)
    {
        this.provider = provider;
    }
}

In this case the constructor takes a parameter of IServiceProvider and stores the injected instance into a member variable - provider. You can now use the provider object in any of the actions. This is shown below :

public IActionResult Index()
{
    INotificationHelper helper = (INotificationHelper)
provider.GetService(typeof(INotificationHelper));

    helper.Notify();

    return View();
}

As you can see, the code calls the GetService() method of IServiceProvider to grab a service instance. The GetService() accepts the type of service being accessed - INotificationHelper. GetService() returns plain object and hence you need to typecast it into INotificationHelper.

Although you can use IServiceProvider as illustrated above, try to avoid using it directly unless there is some good reason to do so. Prefer to inject explicit service types in the constructor (or action) whenever possible.

Using HttpContext.RequestServices

In the preceding example we injected IServiceProvider into the constructor. But there is a shortcut - you can grab a IServiceProvider using RequestServices property of HttpContext. The following code shows how this is done.

public IActionResult Index()
{
    INotificationHelper helper= (INotificationHelper)
HttpContext.RequestServices.GetService
(typeof(INotificationHelper));

    return View();
}

The code now uses IServiceProvider exposed through the RequestServices property of the HttpContext and calls the GetService() method on it.

As with the previous approach this approach too should be used sparingly.

That's it for now ! Keep coding !!


Bipin Joshi is a software consultant, trainer, author and spiritual yoga mentor having 23+ years of experience in software development. He teaches online training courses in ASP.NET Core, Angular, and Design Patterns to individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 29 January 2018


Tags : ASP.NET ASP.NET Core MVC C# Visual Studio