Dependency Injection with Ninject and MVC 4

This week I uploaded a new version of www.cocktailsrus.com. I didn’t change all that much… just upgraded the server to .NET 4.5, upgraded MVC4 from beta to release, Entity Framework to 5.0, jQuery to 1.8.3, jQuery UI to 1.9.2 and jQuery Mobile to 1.2.0. Oh, and I finally made the move to storing the images on Amazon S3 (and, of course, I wrote a program to upload all the existing images ready for the new version).

So, not much change at all, then 🙂

I’ve been itching to make this change for a long time, but now that I’ve done it I have a potential problem: the production and development versions are using different data store types for images. I want to make sure that if I’m in debug mode I call the local file storage version of my PhotoRepository, and if I’m in release mode (and hence on the live server) I am using Amazon S3. There are all sorts of primitive ways I could manage this. I could, for example, change the using directive when I switch versions, going from cocktails.storage to cocktails.storage.amz. But all such approaches are fiddly and prone to human error. What I really want is an automated solution that picks the right object automatically without my intervention.

It’s time for dependency injection!

There are a number of DI frameworks available for .NET, but I decided to go with Ninject (since it looked a. reasonably simple and, b. sufficient for my purposes). Here is my design goal:

The application should automatically select the correct PhotoRepository depending upon whether it is in debug or release mode.

This is what I did to achieve it:

  1. Use NuGet to install the base Ninject framework and the MVC extensions into the MVC project

Don’t worry that it says MVC3 – it works in MVC 4 as well.

This will add a NinjectWebCommon file to App_Start. You could use this, but I did all my work inside Global.asax instead, so I excluded NinjectWebCommon from the project.

  1. Inherit Global.asax from NinjectHttpApplication instead of just HttpApplication and implement protected override Ninject.IKernel CreateKernel() and the override of OnApplicationStarted (which you might have to add yourself).
  2. Move all the code setting up routes etc. from the Application_Start routine to OnApplicationStarted and then remove Application_Start
  3. We’re now ready to start programming. Move to CreateKernal() and create a standard kernel. Then load the executing assembly.

  1. At this point, all the plumbing is in place – we can start setting up our dependencies. What I really want to do is set a dependency on the business/service layer – but for that I first need to create the dependency from the controller to the Service layer. So let’s add a mapping between IBeverageService and the BeverageService implementation:

Except, of course, I don’t actually have an IBeverageService interface because I haven’t needed one before now.

  1. So before I do anything else I have to refactor and create the appropriate interface

.

  1. Not only does that work, I can get Visual Studio to do all the heavy lifting for me. So I go right on and create interfaces for all of my Service classes.
  2. Now that I have interfaces, Ninject will look for the constructor with the most arguments in the specified implementation and use it to create the objects. So now I need to add constructors to all of my service methods so that Ninject can pass in the concrete implementations at runtime. I can then assign them to private read only variables. Like this:

  1. So now I need to tell Ninject which PhotoRepository implementation to use, and since I want different ones between development and production, our old friend conditional compilation can be really helpful here:

  1. Great. We can now pass through the appropriate PhotoRepository implementation to BeverageService. But first we have to add an appropriate constructor to our controller so that BeverageService itself is injected appropriately:

  1. And that’s it. Now when the application runs, Ninject is injecting the types specified inside my Gobal.asax – and giving me the appropriate image storage implementation. Here is the complete code for the CreateKernel() method with all the Service implementations assigned to the appropriate interfaces.

What do I like about this? The fact that my service layer does not even have to have a reference to either storage .dll, and that my application automatically switches to the appropriate back-end depending on the context.

What do I dislike about this? The fact that my UI, which previously only knew about the Service layer and was completely ignorant of the rest of the system now needs to have references to all the objects I might potentially inject. Is it a price worth paying? Definitely.

Kevin Rattan

For other related information, check out this course from Learning Tree:

Building Web Applications with ASP.NET MVC

Type to search blog.learningtree.com

Do you mean "" ?

Sorry, no results were found for your query.

Please check your spelling and try your search again.