Asp.Net MVC 3.0 with dependency injection using Ninject container.

I did not use the famous jargon “Inversion Of Control IOC” intentionally here so that developers who are taking a shot at implementing(or understanding the existing application) dependency injection in their MVC application are not puzzled by the debate over comparing/relating IOC  with DI.

For now, let’s settle on that   “IOC is an architecture principle and DI is configurable piece of code which follows IOC.”

I am going to cover the much needed  WHY,WHERE and HOW of DI

WHY to use DI: Even though MVC represents Separation of Concerns quite strongly, yet controllers are tightly coupled to Data access model/service.

// using Entity framework here.
private NorthwindEntities _Db = new NorthwindEntities();
public ActionResult CustomerList()
 {
 var model = _Db.Customers.ToList();
 return View(model);
 }

In the above code, we have NorthwindEntities entity framework context used for Data access. let’s say we need to change the data access methodology for some reason (trust me it happens more often than you assume), then we need to change controller codes all across the application.  So, why not creating a way where controller can become loosely coupled with data access methodology.

Hence here are few situations when to use IOC – DI

  1. When we need our components to be loosely coupled.
  2. When Unit testing is important and database may not be ready in the beginning. Test Driven Development TDD.
So, rather than instantiating the database context object we should pass an interface to the controller. This reduces extra work to create a test/mock data for testing. Even the database is not ready we can test our action methods easily as all  controller needs is an Interface.
WHERE to use DI:
  1. Initialization of controllers should be changed. controller’s constructor should accept interface to a repository (ICustomerRepository).
  2. In Global.asax and under Application_Start event setup the binding to interface.
 HOW to use:  piece of code to implement.
Interface and Repository classes
</pre>
</div>
<div>
public interface ICustomerRepository
 {
List<Customer> GetAll();
 }

// entity framework data access

public class CustomerEFRepository : ICustomerRepository
 {
 #region ICustomerRepository Members

public List<MVC_IOC_DI.EF.Customer> GetAll()
 {
 NorthwindEntities _db = new NorthwindEntities();
 return _db.Customers.ToList();
 }

#endregion
 }

// Sql to Linq data access

public class CustomerLinqRepository : ICustomerRepository
 {
 #region ICustomerRepository Members

public List<Customer> GetAll()
 {
 NorthwindLinqDataContext _db = new NorthwindLinqDataContext();
 return _db.Customers.ToList();
 }

#endregion
 }

// Home Controller

public class HomeController : Controller
 {
 private readonly ICustomerRepository irepository;

public HomeController(ICustomerRepository repository )
 {
 irepository = repository ;
 }

// right click on this method and Add View (as List template) strongly typed to Customer object.
public ActionResult CustomerList()
 {
 var model = irepository.GetAll() ;
 return View(model);
 }

}</div>
<div>
Ninject IOC container related code:  You can download Ninject libraries for MVC3.0 from http://nuget.org/packages/Ninject.MVC3 . If you are using VS2010 just go to NuGet Package manager and search for Ninject and install it (Nuget really rocks :))
</div></div>
<div>
<pre><div>
using Ninject;
using Ninject.Syntax;</div>
<div></div>
<div>//You would need a dependency resolver class to instruct MVC about the binding/mapping you need to specify in //global.asax.</div>
<div>

public class NinjectDependencyResolver : IDependencyResolver
 {
 private readonly IResolutionRoot _resolutionRoot;

public NinjectDependencyResolver(IResolutionRoot kernel)
 {
 _resolutionRoot = kernel;
 }

public object GetService(Type serviceType)
 {
 return _resolutionRoot.TryGet(serviceType );
 }

public IEnumerable<object> GetServices(Type serviceType)
 {
 return _resolutionRoot.GetAll(serviceType);
 }

}

</div>
<pre>// call this method ins Application_Start event</pre>
private void SetupDependencyInjection()
 {
 // create Ninject DI kernel
 IKernel kernel = new StandardKernel();

// register repository with specific data access repository DI container
 kernel.Bind<ICustomerRepository>().To<CustomerLinqRepository>();
// Later you may change it to EF data access easily.
//kernel.Bind<ICustomerRepository>().To<CustomerEFRepository>();
// Tell mvc to use our DI Ninject container
 DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
 }
<pre>

Here is the summary of the whole implementation.

  1. Include Ninject libraries in your application.
  2. Write Interface for each entity repository. — ICustomerRepository
  3. Write repository classes which implements the interface. — CustomerEFRepository or CustomerLinqRepository
  4. Controller should have interface as a class variable.
  5. Write a constructor for the controller which accepts this interface as parameter.
  6. Write a dependency resolver class for Ninject container. Which will change the dafualt way of how the MVC  resolves the dependency.
  7. Map the bindings in Application_Start event of Global.asax.cs.
These steps are for a very basic implementation of DI in MVC 3. 

For a beginner, it is a good start. Once the skeleton is ready, it’s easy to put on some fat :).

I hope it is useful.


Advertisements

About saxenapraveen

I work with Microsoft and have 12 years of experience in developing,designing and leading reliable and scalable solutions for cloud and device ready businesses.

Posted on February 29, 2012, in .NET, ASP.NET MVC, C# and tagged , , , , , , , . Bookmark the permalink. 1 Comment.

  1. The way you have presentedt the things are really good and easy for a beginner to get start on DI without going into lot of complexities

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: