Dependency Injection in ASP.NET MVC Tutorial

March 07, 2017
6 min read
Dependency Injection in ASP.NET MVC pc screenshot
Introduction

The scope of this tutorial is to unravel (hopefully) some of the mistery behind Dependency Injection, a widely used pattern, that although its implementation may seem complicated (and it may very well be), the concept on the other hand is relatively simple and quite useful.

Terminology

In the same context you may encounter three different terms that are related but not quite synonyms, and these are:

  • Dependency Injection (DI)
  • Inversion of Control (IoC)
  • Dependency Inversion Principle (DIP)

Dependency Injection (DI)

In software engineering, dependency injection is a design pattern whereby one object supplies the dependencies of another object. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client's state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

Dependency injection is one form of the broader (more general) technique of inversion of control.

The intent behind dependency injection is to decouple objects to the extent that no client code has to be changed simply because an object it depends on needs to be changed to a different one.

Inversion of Control (IoC)

In software engineering, inversion of control is a design principle used to increase modularity of the program and make it extensible.
More specifically this means that objects do not create other objects on which they rely to do their work. Instead, they get the objects that they need from an outside source. So we invert/revert the control (hence the name IoC), by delegating the responsibility of creating objects/instances to code outside the class where we need these dependencies. Fortunately there are dependency injection frameworks (commonly know as IoC containers) that make our life easier by taking care of creating these objects (the term usually used is getting or  resolving instances). 
There are several basic techniques to implement inversion of control (i.e. factory pattern, service locator pattern, dependency injection and so on).

Dependency Inversion Principle Tutorial (DIP)

In object-oriented design, the dependency inversion principle refers to a specific form of decoupling software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details. The principle states: 
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.
In the practical sense this means that you should make use of interfaces when applying this principle as illustrated in the example.

Example of Dependency Injection in ASP.NET MVC 

For this tutorial, let`s consider a simple example where we want to save something to the database and take for instance the user creation in an ASP.NET MVC application. So first we need a UserController class and a Create action method (overlooked return statement for practical reasons).


public class UserController : Controller
    {            
        public ActionResult Create(User user)
        {
            // save user to database            
        }
    }

From here, as usual, we have several options. The worst would be to write here the actual code that saves the user to the database. Adding a separate method in UserController that does the saving would also be bad because:

  • Controllers should have mostly action methods and no business logic
  • It violates the Single Responsibility Principle (aside from its intended responsibility we would charge the controller with the responsibility of saving to the database)

The solution would be to create a separate class that has the responsibility of working with the database.


public class UserController : Controller
    {            
        public ActionResult Create(User user)
        {            
            var repository = new Repository();
            repository.Save(user);
        }
    }

This solves the SRP issue described above but by creating a Repository object in UserController we get a dependency that is hard to change (tight coupling). Suppose we would also want to update existing user information.


public class UserController : Controller
    {            
        public ActionResult Create(User user)
        {            
            var repository = new Repository();
            repository.Save(user);
        }

        public ActionResult Edit(User user)
        {
            var repository = new Repository();
            repository.Update(user);
        }
    }

So now we have two actions with a dependency on Repository but there could also be different entities (i.e. Product, ShoppingCart, Order, etc.) in different controllers, all depending on Repository. Imagine a scenario where we would like to use a different Repository (i.e. MySqlRepository, MongoDbRepository, etc.) or even just provide mock objects for unit testing. We would then have to change every line and replace new Repository() with the one in question. Of course we do not want to do this. First, this is no fun. Second, this is error-prone. Third, this is stupid, repetitive work for a trained monkey. So what do we do? 
This is where Dependency Injection comes in. The solution would be to inject a Repository dependency in the UserController constructor (there is also setter injection and property injection but constructor injection is the most common). By injecting the dependencies we achieve great flexibility in our application since we can now swap, decorate and intercept dependencies without the consuming class knowing. In other words, changing the Repository does not imply any change in UserController (or any other for that matter).


public class UserController : Controller
    {
        private readonly Repository _repository;

        public UserController(Repository repository)
        {
            _repository = repository;
        }

        public ActionResult Create(User user)
        {                                                
            _repository.Save(user);
        }

        public ActionResult Edit(User user)
        {            
            _repository.Update(user);
        }
    }

Now, when we change the Repository, we need only change the constructor parameter and the field. But we can take this even further by following the Dependency Inversion Principle through shared abstractions which will truly imply no change at all in the controllers. Practically speaking we could use an interface that every repository will need to implement. So instead of Repository we use IRepository.


 
public class UserController : Controller
    {
        private readonly IRepository _repository;

        public UserController(IRepository repository)
        {
            _repository = repository;
        }

        public ActionResult Create(User user)
        {                                                
            _repository.Save(user);
        }

        public ActionResult Edit(User user)
        {            
            _repository.Update(user);
        }
    }

As mentioned earlier there are DI frameworks, also know as IoC containers that take care of resolving the instances. For example, using Castle Windsor IoC container we need only register / install the services (in our case the IRepository service). This would look something like this:


 
public void Install(IWindsorContainer container, IConfigurationStore store)
        {
container.Register(Component.For<IRepository>().ImplementedBy<Repository>().LifeStyle.Transient);            
        }

Now if we want to change the Repository we change it only here, in one place. Of course that in order for this to work you also need to add a custom ControllerFactory and install your IoC container registrations but this is beyond the scope of this tutorial which is meant to focus more on the concept and the advantages you get by using Dependency Injection.

Pros
  • loosely coupled code
  • reusable code
  • testable code
  • readable code
  • increases modularity and adds extensibility
Cons
  • adds a degree of complexity
  • the learning curve may be an issue
Conclusion

Even if you never plan to change the injected service (in this case the Repository) and you never plan to do Unit Testing I still highly recommend you to use Dependency Injection whenever is suited and this tutorial is meant to help you succeed easier with your plans (i.e. in controllers as illustrated in the example).

Share on:

Want to stay on top of everything?

Get updates on industry developments and the software solutions we can now create for a smooth digital transformation.

* I read and understood the ASSIST Software website's terms of use and privacy policy.

Frequently Asked Questions

ASSIST Software Team Members

See the past, present and future of tech through the eyes of an experienced Romanian custom software company. The ASSIST Insider newsletter highlights your path to digital transformation.

* I read and understood the ASSIST Software website's terms of use and privacy policy.

Follow us

© 2024 ASSIST Software. All rights reserved. Designed with love.