3 Comments

The following are the detailed steps to use Ninject IoC with ASP.NET MVC

Download and install TortoiseSVN
TortoiseSVN is a Subversion client that allows you to manage source control tasks from within Windows Explorer.
Download the source code for Ninject from google code
The Ninject source code is hosted in Google Code website. To download the code to PC, we will use TortoiseSVN. Before that we need the URL of the repository. This is available in the following url: http://code.google.com/p/ninject/source/checkout Ninja1 Then using Windows Explorer use the “Export” option of TortoiseSVN to get a copy of the source code as shown in the figures below: Ninja2 Ninja3 Ninja4
Build the Ninject source code
Once we have the source code, we need to build it to generate the two assemblies we need. We will run the Build.cmd file that will trigger a Nant build script which will eventually build the entire source. Ninja5 Once we have built the source code successfully, we can find the two assemblies we need in the /bin/debug folder as shown below: Ninja6
Create a new MVC project
Now, let us create a new MVC project using Visual Studio 2008. MVC1 MVC2 MVC3 Let us test if all is fine by running the application MVC4
Making the MVC project a meaningful project
Before jumping into adding references to the Ninject assemblies, let us modify this MVC project to do something useful. We are going to create an application that will help us browse through the bills in a Parliament. The Parliament has two chambers. House of Lords and House of Commons and each have their own bills at anytime which they are legislating about. I am going to show only the code relevant to this topic, so will not show in detail all the steps in creating this. The source code for this can be downloaded to view the complete implementation minus Ninject integration. Some screen shots of the application is shown below:
Home Page
Parl1
Bills page
Parl2
Bills in House of Lords
Parl3
Bills in House of Commons
Parl4 The following shown the Solution Explorer highlighting the Code Files needed to accomplish the above application. MVC5
The case for Dependency Injection
The List of Bills displayed in the website is at the moment “fake” data coming from a class called “FakeDepository”.
Code Snippet
  1. namespaceJoeBloggsStore.DataModel.Concrete
  2. {
  3.     publicclassFakeDataRepository : IDataRepository
  4.     {
  5.         // fake list of bills in house of lords
  6.         privatestaticIQueryable<string> lordsBills = newList<string>{
  7.             "Live Music Bill [HL]",
  8.             "Constitutional Reform Bill [HL]"
  9.         }.AsQueryable();
  10.         // fake list of bills in house of commons
  11.         privatestaticIQueryable<string> commonsBills = newList<string>{
  12.             "Maximum Wage Bill",
  13.             "Bankers' Pensions (Limits) Bill"
  14.         }.AsQueryable();
  15.         publicIQueryable<string> LordsBills
  16.         {
  17.             get { returnlordsBills; }
  18.         }
  19.         publicIQueryable<string> CommonsBills
  20.         {
  21.             get { returncommonsBills; }
  22.         }
  23.     }
  24. }
At the moment, although we have based this class on an interface, we are using this in a tightly-coupled fashion in the “BillController” as shown below:
Code Snippet
  1. publicActionResultLords()
  2.         {
  3.             ViewData["House"] = "Lords";
  4.             ViewData["Bills"] = newFakeDataRepository().LordsBills.ToList();
  5.             returnView("Index");
  6.         }
  7.         publicActionResultCommons()
  8.         {
  9.             ViewData["House"] = "Commons";
  10.             ViewData["Bills"] = newFakeDataRepository().CommonsBills.ToList();
  11.             returnView("Index");
  12.         }
This is not a good practice to Program to an implementation (Line 4 and Line 10 in Figure). Instead, we should be Programming to an interface and make use loose-coupling where ever applicable.
Programming to an Interface
The following code shows the modified BillController that takes in an IDataRepository in it’s constructor. (Lines 5 up to 10 in Figure) The interface variable “dataRepository” is then used to get the Bills (Line 24 and 30 in Figure)
Code Snippet
  1. namespaceJoeBloggsStore.Controllers
  2. {
  3.     publicclassBillController : Controller
  4.     {
  5.         privateIDataRepositorydataRepository;
  6.         
  7.         publicBillController(IDataRepositoryrepos)
  8.         {
  9.             this.dataRepository = repos;
  10.         }
  11.         //
  12.         // GET: /Bill/
  13.         publicActionResultIndex()
  14.         {
  15.             ViewData["House"] = "Parliament";
  16.             ViewData["Bills"] = null;
  17.             returnView();
  18.         }
  19.         publicActionResultLords()
  20.         {
  21.             ViewData["House"] = "Lords";
  22.             ViewData["Bills"] = this.dataRepository.LordsBills.ToList();
  23.             returnView("Index");
  24.         }
  25.         publicActionResultCommons()
  26.         {
  27.             ViewData["House"] = "Commons";
  28.             ViewData["Bills"] = this.dataRepository.CommonsBills.ToList();
  29.             returnView("Index");
  30.         }
  31.     }
  32. }
But, who is going to pass in the correct IDataRepository instance to the BillController. This is where Ninject comes in.
Integrating Ninject for Constructor Injection
The BillController depends on an appropriate instance of IDataRepository to be passed when it’s constructed using the constructor. By default, MVC Framework creates an instance of BillController by using a parameterless constructor. In our case, we have want MVC to call our constructor with IDataRepository parameter and pass in the correct instance that we will configure. To instruct the MVC framework to do this, we have to modify the Global.asax.cs. The default Global.asax.cs file is as follows:
Code Snippet
  1. namespaceJoeBloggsStore
  2. {
  3.     // Note: For instructions on enabling IIS6 or IIS7 classic mode,
  4.     // visit http://go.microsoft.com/?LinkId=9394801
  5.     publicclassMvcApplication : System.Web.HttpApplication
  6.     {
  7.         publicstaticvoidRegisterRoutes(RouteCollectionroutes)
  8.         {
  9.             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  10.             routes.MapRoute(
  11.                 "Default",                                              // Route name
  12.                 "{controller}/{action}/{id}",                           // URL with parameters
  13.                 new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
  14.             );
  15.         }
  16.         protectedvoidApplication_Start()
  17.         {
  18.             RegisterRoutes(RouteTable.Routes);
  19.         }
  20.     }
  21. }
We need to first make the MvcApplication derive from “Ninject.Framework.Mvc.NinjectHttpApplication” as shown below:
Code Snippet
  1. publicclassMvcApplication : Ninject.Framework.Mvc.NinjectHttpApplication
To do this, we need to add two references to our project. Before that let us copy the two assemblies we need to a “lib” folder inside our Visual Studio solution folder: Ninja6 Ninja7 Let us then add the references: Ninja8 Upon adding the reference, the NinjectHttpApplication requires us to implement two Abstract members
  1. CreateKernel()
  2. RegisterRoutes(RouteCollection)
The CreateKernel is where we tell Ninject which Concrete Class needs to be injected when the Constructor of BillController is called. The RegisterRoutes is where we configure the MVC Routing options. We need to do two things now:
  1. Ensure the Routing still works (because the Application_Start() is now moved into NinjectHttpApplication and RegisterRoutes is also made abstract in NinjectHttpApplication)
  2. Create a configuration that tells Ninject to inject FakeDepository whenever IDataRepository is requested.
First, change the RegisterRoutes from being a private method to an overridden protected method  as shown below:
Code Snippet
  1.         protectedoverridevoidRegisterRoutes(RouteCollectionroutes)
  2.         {
  3.             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  4.             routes.MapRoute(
  5.                 "Default",                                              // Route name
  6.                 "{controller}/{action}/{id}",                           // URL with parameters
  7.                 new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
  8.             );
  9.         }
Now, the configuration to Ninject is provided by creating a Module that derives from  Ninject.Core.StandardModule (There are other modules which we will not delve into now) The following code shows such a Module: Ninja9
Code Snippet
  1. namespaceJoeBloggsStore
  2. {
  3.     publicclassWebModule : StandardModule
  4.     {
  5.         publicoverridevoidLoad()
  6.         {
  7.             Bind<IDataRepository>().To<FakeDataRepository>().Using<OnePerRequestBehavior>();            
  8.         }
  9.     }
  10. }
The Line 7 in above Figure says, “Ninject, please provide one instance of FakeDataRepository per Request whenever IDataRepository is needed”. We have to now use this WebModule  in CreateKernel function in Global.asax.cs as shown below:
Code Snippet
  1.         protectedoverrideNinject.Core.IKernelCreateKernel()
  2.         {
  3.             IModule[] modules = newIModule[] { newAutoControllerModule(Assembly.GetExecutingAssembly()), newWebModule() };
  4.             returnnewStandardKernel(modules);
  5.         }
If we try to build and run this code, we might get an error saying “OnePerRequestModule has not been loaded”. This is because we have told which assembly contains this HttpModule. We can do this in the <httpModules> section of the web.config:
Code Snippet
  1.     <httpModules>
  2.       <add name="ScriptModule"type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  3.       <add name="UrlRoutingModule"type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  4.       <add name="OnePerRequestModule"type="Ninject.Core.Behavior.OnePerRequestModule, Ninject.Core"/>
  5.     </httpModules>
If we run the application now, we should see the application working as expected. In the future when we want to get the data from a SQL Server database, we can create a new class called SQLDataRepository. The possibilities of SQLDataRepository requiring a connectionString to the database is high. So, this can be configured in the WebModule as follows:
Code Snippet
  1.         publicoverridevoidLoad()
  2.         {
  3.             //Bind<IDataRepository>().To<FakeDataRepository>().Using<OnePerRequestBehavior>();
  4.             Bind<IDataRepository>().To<SQLDataRepository>().Using<OnePerRequestBehavior>().WithConstructorArgument("connectionString", WebConfigurationManager.ConnectionStrings["ApplicationServices"]);
  5.         }
The SQLDataRepository’s Constructor should obviously take a connectionstring as parameter for this to work. The source code for completed web application is available for download.

Comments

Comment by mgroves

An excellent tutorial, thank you very much! I want to add though, that you didn't mention this explicitly, but the Application_Start() method in the MvcApplication class needs to be marked as 'new'

Comment by ASP.NET MVC Archived Buzz, Page 1

[...] to Vote[Del.icio.us] How to use Ninject IoC with ASP.NET MVC « Peak bytes (1/24/2011)Monday, January 24, 2011 from [...]

Comment by Kishore K Barik

Really a excellent and easy tutorial for learning ninject,
Is this possible to a separate class from separate class library using reflection not by direct referencing in Load function of WebModule, if possible how it can be achieved, please reply me.

Kishore K Barik