Getting Started with Ninject 2.0 and ASP.NET MVC 2.0

5/17/2010 9:32 PM

Let’s face it, dependency injection makes sense when you want to write a highly testable application. Since one of my goals with the Tombatron website was to have it as testable as possible, I decided that I too would add dependency injection. For Tombatron I chose Ninject. Ninject was chosen for two reasons. First, cool name huh? Second, once you have Ninject setup actually injecting the dependencies is a snap! In this post I will cover the basics of implementing Ninject with your ASP.NET MVC web application and then cover how to perform some basic unit testing of your new implementation.

 

Getting Started

Before you get started you are going to need a few things. The first thing that you are going to need is a brand new ASP.NET MVC 2.0 web application. It is beyond the scope of the article to show you how to make one of these, but if you need more information on how to create a new one you can look here. Secondly, you are going to need the latest version of Ninject. To download Ninject go here and download the version for “.NET Framework 3.5”. Lastly you are going to need the MVC extension for Ninject, which can be found here. For the MVC extension there are no pre-compiled binaries so you’ll have to download the source and compile it yourself. Don’t worry it’s a well maintained project and compiling it isn’t horrible at all.

 

Project Configuration

The first thing you will need to do is add references to the “Ninject.dll” and “Ninject.Web.Mvc.dll” libraries to your project. After you have the references added, go ahead and open the “Global.asax.cs” file so we can get started. By default the “Global.asax.cs” inherits from the “System.Web.HttpApplication” class. We are going to change that. First thing you need to do is import the required Ninject namespaces:


using Ninject;
using Ninject.Web.Mvc;

 


Next we need to change the “MvcApplication” class so that it inherits from the “NinjectHttpApplication” instead of the “System.Web.HttpApplication” class. Basically, when you are finished you should have something that looks kind of like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

using Ninject;
using Ninject.Web.Mvc;

namespace MvcApplication1
{

    public class MvcApplication : NinjectHttpApplication
    {
        //There would be stuff here.
    }
}

 

By default the “MvcApplication” class will have a method called “Application_Start”, this method is going to be replaced by an overridden method from the “NinjectHttpApplication” class called “OnApplicationStarted”. Another overridden method called “CreateKernel” will be added to the “MvcApplication” class.

 

The “OnApplicationStarted” method handles all of the functionality of the “Application_Start” method and then goes the extra step of registering all of the controllers for injection. The “CreateKernel” method spins up a new “StandardKernel” object with any Ninject modules that you specify. The kernel is the workhorse of Ninject, it takes care of all the “jecting”… Yeah.

 

When you replace the “Application_Start” method with the “OnApplicationStarted” method you should have something similar to:

protected override void OnApplicationStarted()
{
  AreaRegistration.RegisterAllAreas();

  RegisterRoutes(RouteTable.Routes);

  RegisterAllControllersIn(Assembly.GetExecutingAssembly());
}

 

The “CreateKernel” override is much easier to define.

 

protected override IKernel CreateKernel()
{
  return new StandardKernel(new Bootstrapper());
}

 

The above code is quite simple. I’m spinning up a new instance of “StandardKernel” with a new instance of the “Bootstrapper” class. The “Bootstrapper” class is a Ninject module that instructs the kernel how to handle different dependencies. The syntax for creating dependency mappings is very straightforward. The following is a basic example of a Ninject module:


using System;

using ExampleWebsite.Models;

using Ninject;
using Ninject.Modules;

namespace ExampleWebsite
{
    public class Bootstrapper : NinjectModule
    {
        public override void Load()
        {
            Bind<IExampleRepository>().To<ExampleRepository>();
        }
    }
}

 

With the above module loaded, any time an MVC controller has a property of type “IExampleRepository” that is decorated with the “Inject” attribute, the kernel will inject a new instance of the “ExampleRepository” for you. Here’s an example of how to specify a property for injection:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using ExampleWebsite.Models;

using Ninject;

namespace ExampleWebsite.Controllers
{
    public class ExampleController : Controller
    {
        [Inject]
        public IExampleRepository ExampleRepo { get; set; }

        //Controller Actions...

    }
}

That’s really all there is to it! But wait… There’s more!

 

How do I test it?

Great question! As it is now, if you were to write a unit test and create an instance of the “ExampleController” class, that property awaiting injection would simply be null. Outside of the normal MVC application, there is nothing to call for an instance of the “StandardKernel” object, and nothing to register all of the controllers for injection. Luckily for us, replacing that functionality isn’t really that difficult. The following is just an example of how to make this work, I’ll leave it to you to make it sexy.

using System;
using System.Collections.Generic;
using System.Web.Mvc;

using ExampleWebsite.Controllers;
using ExampleWebsite.Models;

using Ninject;
using NMock2;
using NUnit.Framework;

namespace ExampleUnitTesting.Controllers
{
    [TestFixture]
    public class ExampleControllerTests
    {
        IKernel k;
        Mockery mock;

        IExampleRepository mockExampleRepo;

        [TestFixtureSetUp]
        public void TestSetup()
        {
            //Create instance of StandardKernel.
            k = new StandardKernel();
            mock = new Mockery();

            //Create a mock instance of the ExampleRepository.
            mockExampleRepo = mock.NewMock<IExampleRepository>();

            //Bind the mock instance of the ExampleRepostiory.
            k.Bind<IExampleRepository>().ToConstant(mockExampleRepo);
        }

        [Test]
        public void CanInvokeDefaultActionResultTest()
        {
            //Set mock expectations if any...

            var ec = new ExampleController();

            //Here is where we tell the kernel to inject.
            k.Inject(ec);

            //Rest of the unit test...
        }

    }
}

 

As you can see from the above example, my unit testing framework of choice is NUnit, and I’m using NMock2 for my object mocking. It really doesn’t matter which frameworks you use, the idea is the same. You are simply spinning Ninject up manually.

Conclusion

One thing to keep in mind, I’m just scratching the surface when it comes to using Ninject (I’ve just started myself). The next step is to find out what else it can do. While working with Ninject, I’ve found the best resource really is StackOverflow. Resource links at the bottom.

Resources

Ninject Download Page
Ninject.Web.Mvc Extension Page

StackOverflow: Ninject

loading...
Comment Entry


Twitterings - Follow Me

  • If you're looking for a kick ass regular expression tests check this out: http://bit.ly/2K8TKT
  •  
  • Saw an application that I work on being used by an end user today. Incredibly satisfying!
  •  
  • Lightning delay at the Bucs game... Welcome to Tampa!
  •  
  • Working on the website, finally got some basic twitter integration working...
  •  
  • If Rick Scott is elected governor, do you think he'll assert his 5th amendment right when taking the oath of office?
  •