I've mentioned Ninject before, it's an excellent dependancy injection framework that lets you keep your code loosely coupled.
I've also mentioned that I've been working with the MVC Framework quite a lot of late, and what's neat is that hooks are provided that make it easy to use your own dependancy injection framework. To that end, this post will be looking at how Ninject can be integrated with MVC3, and why that's awesome!
I'll be working with a clean MVC3 project created in Visual Studio 2010. There are a couple of ways of integrating Ninject; using the IDependancyResolver interface, or inheriting from NinjectHttpApplication.
Option 1: IDependancyResolver
All we need to do here is implement IDependancyResolver and then register an instance of it on application startup.
So a simple implementation for Ninject will look something like this:
using System;
using System.Web.Mvc;
using System.Collections.Generic;
using Ninject;
using Ninject.Modules;
public class NinjectResolver : IDependencyResolver
{
IKernel kernel;
public NinjectResolver(INinjectModule[] modules)
{
kernel = new StandardKernel(modules);
}
public object GetService(Type serviceType)
{
return kernel.Get(serviceType);
}
public IEnumerable
And we register this in Application_Start with a simple call like so:
var resolver = new NinjectResolver(new MyModule());
DependencyResolver.SetResolver(resolver);
MVC3 will then use this object when trying to instantiate an instance of a class, but will fall back to it's built in methods for locating objects if this fails. What this means in practice is that you don't need to worry about registering all of the default objects MVC3 uses such as the controller factory, leaving you free to just deal with the stuff you care about.
Option 2: NinjectHttpApplication
The second option is to make use of Ninject's MVC3 extension which can be found here.
In this case, all we need to do is change our MvcApplication class (found in Global.asax) to inherit from NinjectHttpApplication instead of MvcApplication, and then implement CreateKernel to register the modules we've created.
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
public override IKernel CreateKernel()
{
return new StandardKernel(new MyModule());
}
}
And that's it; now Ninject will be used to resolve any dependencies that are requested when the object model is being built.
Which Approach?
But which of the two approaches should you use? It doesn't matter hugely, the first option allows for a very quick integration, you could even register a dependency resolver in a much more concise fashion making use of lambdas like so:
var kernel = new StandardKernel(modules);
DependencyResolver.SetResolver(
t => {
try { return kernel.Get(t); }
catch { return null; }
},
t => kernel.GetAll(t)
);
However, using Ninject's MVC3 extension is marginally more self contained, so I tend to prefer making use of NinjectHttpApplication instead. Note that Ninject will still find the right controllers without registering them, so there is no need to register all your controllers unless you want to add additional configuration to them.
If you think you're likely to want to change your DI framework, then it would make more sense to make use of the IDependancyResolver interface so that you can drop in a quick replacement, although personally I think that scenario is somewhat unlikely.
Now you're loosely coupled
So that's a couple of simple ways to integrate Ninject with MVC3; not too hard to achieve and provides a lot of power and flexibility.