Last weekend I watched two great talks about ASP.net MVC by Steve Sanderson and Sebastian Lambla at Developer Day Scotland. One of the main points I got from both talks was the benefits of a IOC container in you MVC projects. So I decided to try out an IOC container for myself :) I kept hearing good things about Ninject on Twitter and various blogs I read, so I decided to take the plunge with Ninject.
Quick note - I’m going to write about using Ninject 2.0 beta which is hosted on GitHub, and not the 1.5 version which is the current release that is linked on their website. Don’t make the mistake I did and grab the wrong version, doh! If you skip to the bottom of the post you can also see where I've posted my global.ascx file used in the project in it’s entirety.
Downloading and building the 2.0 beta source
The first step in getting Ninject up and running is to grab the source and build the latest version. Ninject is currently hosted on GitHub: http://github.com/enkari/ninject/tree/master
Github also hosts the Ninject ASP.MVC extension that makes it easier for us to integrate Ninject into our MVC project so you’ll want to grab that as well. Once you’ve downloaded both simply run their respective build scripts to produce the Ninject assemblies.
Adding Ninject to your project
Now you need to copy the Ninject.dll and Ninject.Web.Mvc.dll files to your project, I store all the external assemblies for my project in a folder called ‘libs’ however where you place them is up to you. Where ever you do place them you need to add references to both these assemblies in your project:
Setting up MVC to use Ninject
Most of the configuration of Ninject takes place in your projects Global.asax file. The first step is to change the MvcAppplicaton class to inherit from NinjectHttpApplication instead of System.Web.HttpApplication like so:
public class MvcApplication : NinjectHttpApplication
NinjectHttpApplication contains it’s own implementation of the Application_Start() method which helps to initialize the Ninject Kernel. It also setups up your project to use the Ninject Controller Factory allowing you to use Dependency Injection for your controllers.
Because Ninject uses its own Application_Start() method, it provides you with a new method called OnApplicationStarted(), which you override, that you can use in its place:
protected override void OnApplicationStarted()
{
RegisterAllControllersIn(Assembly.GetExecutingAssembly());
RegisterRoutes(RouteTable.Routes);
}
In the code above I’ve simply moved the RegisterRoutes methods into OnApplicationStarted(), the first line tells Ninject to register all the controllers in our MVC Assembly in our Ninject Kernel.
Next we implement Ninject’s CreateKernel() method to initialize our kernel and tell it the bindings that we want Ninject to handle:
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}
The first line creates the kernel and then in the second line we are telling it to search our projects assembly to look for any Bindings that we have created.
Creating bindings for Ninject
To create bindings for your container you simply create a new class file and inherit from the NinjectModule class:
public class WebModule : NinjectModule
{
public override void Load()
{
Bind<IRepositiory<Job>>().To<JobsRepositiory>();
}
}
For each module we override the Load() method and provide our bindings, You can find out more about Ninject Modules & Bindings on the Ninject Wiki
Conclusion
I hope you’ve found this useful, I’ve only being playing with Ninject for the last couple of days but so far I'm impressed, once you get it up and running it’s really easy to add new bindings and start to build your application in a more test friendly & loosely coupled manner. Ninject is also seriously lightweight – the two assemblies are only 98kb combined :)
Full Global.ascx listing:
public class MvcApplication : NinjectHttpApplication
{
protected 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 = ""
} // Parameter defaults
);
}
protected override void OnApplicationStarted()
{
RegisterAllControllersIn(Assembly.GetExecutingAssembly());
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}
}