How to use Ninject for Dependency Injection in ASP.NET MVC application?

Recently, I published some posts that covers very important concepts like when to use Dependency Inversion Principle, Unit of Work, Repository design patterns in application. I recommend you to read these posts if you are new to these concepts. In this post, I’ll tell you how to use Ninject for Dependency Injection in ASP.NET MVC application. The same concept can also be applied to ASP.NET Web API application or any other .NET application as well.
Dependency Injection
The basic idea of the Dependency Injection is to have a separate object, an assembler, that populates a field in the lister class with an appropriate implementation for the finder interface.
– Martin Fowler
In other words, the idea behind inversion of control is that, rather than tie the classes in your application together and let classes “new up” their dependencies, you switch it around so dependencies are instead passed in during class construction.
I’ve been using same code in the posts linked above. In my last post to explain Dependency Inversion Principle, I refactored existing code to work with abstractions so that controllers doesn’t need to directly depend on any repository or entity framework detail. Just to recap, the code used in that post looks like following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class EventsController : Controller { private readonly IUnitOfWork _unitOfWork; public EventsController() { _unitOfWork = new UnitOfWork(new ApplicationDbContext()); } public ActionResult Details(int id) { var event = _unitOfWork.Events.GetEvent(id); if (event == null) return HttpNotFound(); var viewModel = new EventDetailsViewModel { Event = event }; return View("Details", viewModel); } [Authorize] public ActionResult MyEvents() { var userId = User.Identity.GetUserId(); var events = _unitOfWork.Events.GetUpcomingEventsByArtist(userId); return View(events); } } |
The highlighted statement above creates an instance of UnitOfWork
and ApplicationDbContext
classes. So, this controller is directly dependent on these two classes.
Let’s now add Ninject to move the responsibility of creating instances of classes from this controller to Ninject. I’m using ASP.NET MVC version 5, so I’ll be using Ninject’s MVC5 package for my application using Nuget package manager. Package Manager Console can also be used to install this via following command: install-package Ninject.Mvc5
and make sure the correct MVC project is selected in the project dropdown option.
Next, to add Ninject support for Web API controllers, add Ninject.Web.WebAPI
package as well. I’m using Ninject’s 3.2.1.0
version for both of the packages.
After adding these packages, Ninject has added a new file in App_Start
folder named NinjectWebCommon.cs
that we will be using to register our services. The method named RegisterServices
is where we will register application services by telling the IKernel
parameter about the application requirements.
One way is bind the classes and interfaces manually as shown below. But this is a poor way of configuring as every-time you add an interface or modify your class, you will need to configure it here. And this can be risky as if developer forgets to define a binding configuration then application may have runtime failure. Example:
1 2 3 4 5 6 7 8 |
/// <summary> /// Load your modules or register your services here! /// </summary> /// <param name="kernel">The kernel.</param> private static void RegisterServices(IKernel kernel) { kernel.Bind<IUnitOfWork>().To<UnitOfWork>(); } |
The above code instructs Ninject that whenever IUnitOfWork
is requested by a class, always provide an instance of UnitOfWork
class.
A better way is to do dependency injection by convention over configuration to avoid mistakes like above. This way, Ninject can easily find the interfaces and their implementations in the assembly and bind them automatically for you. For this, another package is required named as ninject.extensions.conventions
from nuget. Now, the only change that is required in NinjectWebCommon.cs
file is following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/// <summary> /// Creates the kernel that will manage your application. /// </summary> /// <returns>The created kernel.</returns> private static IKernel CreateKernel() { var kernel = new StandardKernel(); try { kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); RegisterServices(kernel); kernel.Bind(x => { x.FromThisAssembly() .SelectAllClasses() .BindDefaultInterface(); }); return kernel; } catch { kernel.Dispose(); throw; } } |
Constructor & Property Injection
To inject instances of classes to constructor parameters, no additional steps are required. But for properties, use Inject
attribute to decorate the property that needs an instance of a class that implements particular interface.
Result
With the above changes, the controller code is now simplified even more as shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class EventsController : Controller { private readonly IUnitOfWork _unitOfWork; public EventsController(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public ActionResult Details(int id) { var event = _unitOfWork.Events.GetEvent(id); if (event == null) return HttpNotFound(); var viewModel = new EventDetailsViewModel { Event = event }; return View("Details", viewModel); } [Authorize] public ActionResult MyEvents() { var userId = User.Identity.GetUserId(); var events = _unitOfWork.Events.GetUpcomingEventsByArtist(userId); return View(events); } } |
As highlighted above, controller get an instance of UnitOfWork
class as this class implements IUnitOfWork
interface. Ninject is also smart enough to pass an instance of ApplicationDbContext
class to UnitOfWork
class constructor as it needs it at the time of construction based on following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class UnitOfWork : IUnitOfWork { private readonly ApplicationDbContext _context; public IEventRepository Events { get; private set; } public UnitOfWork(ApplicationDbContext context) { _context = context; Events = new EventRepository(context); } public void Complete() { _context.SaveChanges(); } } |
I hope this article explains you clearly how to use Ninject for Dependency Injection in ASP.NET MVC application. As I said in the beginning, the same concept can also be applied to ASP.NET Web API and other .NET applications.