06:54 pm
February 10
Dependency Injection in ASP.NET MVC4 and Webapi using Ninject
( 7 Votes )
Written by: Blogging Team Views : 6639
Attachments with this blog:
Source code 

After using spring.net in asp.net for long, I looked for a simple, fast and no xml Dependency Injector. For an ASP .Net MVC4 application I finally settled on Ninject because of its no XML approach, simplicity and ease of use.

So, how to choose a Dependency Injector? Well, every dependency Injector has its strengths and weaknesses and comes with a different feature set. Choosing Dependency Injector is a matter of evaluation and what you expect out of it.

Ninject is an open source Dependency Injector for .NET, created by Nate Kohari, and it comes with good set of extension and one of them is extension for ASP .NET MVC3. Ninject is a lightning-fast, ultra-lightweight dependency injector for .NET applications. It helps you split your application into a collection of loosely-coupled highly-cohesive pieces, and then glue them back together in a flexible manner. By using Ninject to support your software’s architecture, your code will become easier to write, reuse, test, and modify.

Anyways, like me if you also like to try new and promising stuff, you will to use Ninject, you can read more about Ninject on Ninject.org

There are several benefits of using dependency injection rather than having components satisfy their own dependencies. Some of the benefits are:

Reduced Dependencies

Dependency injection makes it possible to eliminate, or at least reduce, a components unnecessary dependencies. A component is vulnerable to change in its dependencies. If a dependency changes, the component might have to adapt to these changes. For instance, if a method signature of a dependency is changed, the component will have to change that method call. When a components dependencies are reduced it is less vulnerable to changes.

More Reusable Code

Reducing a components dependencies typically makes it easier to reuse in a different context. The fact that dependencies can be injected and therefore configured externally, increases the reusability of that component. If a different implementation of some interface is needed in a different context, or just a different configuration of the same implementation, the component can be configured to work with that implementation. There is no need to change the code.

More Testable Code

Dependency injection also increases a components testability. When dependencies can be injected into a component it is possible to inject mock implementations of these dependencies. Mock objects are used for testing as replacement for a real implementation. The behaviour of the mock object can be configured. That way the component using the mock can be tested to handle all behaviours correctly. For instance, handling both when the mock returns a correct object, when null is returned and when an exception is thrown. In addition mock objects normally record what methods were invoked on them, so the test can verify that the component using the mock, have used them as expected.

More Readable Code

Dependency injection moves the dependencies to the interface of components. This makes it easier to see what dependencies a component has, making the code more readable. You don't have to look through all the code to see what dependencies you need to satisfy for a given component. They are all visible in the interface.

Reduced Dependency Carrying

Another nice benefit of dependency injection is that it eliminates what I call "dependency carrying". Dependency carrying is when an object takes a parameter in one of its methods that it doesn't need itself, but is needed by one of the objects it calls to carry out its work.

So, next step to integrate Ninject in ASP .NET MVC4

Download Ninject and its ASP .NET MVC3 extension (there is no extension for ASP .NET MVC4 yet). You can download it from https://github.com/ninject/ninject/downloads or install it using nuget gallery http://nuget.org/packages/Ninject.MVC3

Add Ninject dependencies to the project. You need to add reference to following DLLs in your ASP .NET MVC4 Project

  1. Ninject.dll
  2. Ninject.Web.Common.dll
  3. Ninject.Web.Mvc.dll

Modify controller code to declare a read-only member variable of your service and modify the constructor to introduce the service instance parameter as below:

namespace NinjectMvc4.Controllers
{
    public class HomeController : Controller
    {
        private readonly IMessageService _messageService;
        public HomeController(IMessageService  messageService)
        {
            _messageService = messageService;
        }

        public ActionResult Index()
        {
            ViewBag.Message = _messageService.GetWelcomeMessage();

            return View();
        }
    }
}

I have IMessageService interface and want to inject _messageService with the implementation MessageService using Ninject

namespace NinjectMvc4.ServiceLayer
{
    public class MessageService:IMessageService
    {
        public string GetWelcomeMessage()
        {
            return "Welcome to Ninject MVC4 Example";
        }
    }
}
namespace NinjectMvc4.ServiceLayer
{
    public interface IMessageService
    {
        string GetWelcomeMessage();
    }
}

Modify Global.asax, Inherit MvcApplication class from abstract class NinjectHttpApplication which is part of Ninject.Web.Common namespace.

Implement CreateKernel, Method as follows: Create instance of StandardKernel, Load Executing assembly using the kernel, Bind Service Interface with the implementation to be injected.

In this example, while constructing the controllers this will inject the MessageService instance inside HomeController’s constructor so that it can be assigned to _messageService member variable.

namespace NinjectMvc4
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801
    public class MvcApplication : NinjectHttpApplication
    {
        protected override IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());
            kernel.Bind<IMessageService>().To<MessageService>();
            return kernel;
        }

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

            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}

Override OnApplicationStarted to Register Filters and bundles etc. (standard ASP .NET MVC4 stuff which we used to do in Application_Start event when not using ninject).

Now, you are done, lets run the application an see that welcome message is now coming from the MessageService, which got injected into the HomeController.

screenshot

Ninject I now integrated with asp .net MVC4, no different than the approach used to integrate it with ASP .NET MVC3.

If you want to integrate it with asp .net webapi, (injecting into apicontrollers) using DependencyResolver approach just implement System.Web.Http.Dependencies.IDependencyResolver at your own. Because currently Ninject’s Dependency Resolver comes with implementation of System.Web.Mvc.IDependencyResolver which cannot be assigned to GlobalConfiguration.Configuration o WebApi Application, it expects an instance of System.Web.Http.Dependencies.IDependencyResolver instead of System.Web.Mvc.IDependencyResolver.

namespace NinjectMvc4
{
    class LocalNinjectDependencyResolver:System.Web.Http.Dependencies.IDependencyResolver
    {
        public LocalNinjectDependencyResolver(IKernel k)
        {
        }

        public System.Web.Http.Dependencies.IDependencyScope BeginScope()
        {
            throw new NotImplementedException();
        }

        public object GetService(Type serviceType)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            throw new NotImplementedException();
        }

        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }
}

And modify the CreateKernel Method as below to assign an instance of LocalNinjectDependencyResolver to GlobalConfiguration.

/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
    kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
    
    RegisterServices(kernel);
    return kernel;
}

That’s it, we can live with this work around for now. Please, download the source code for a better understanding of this example.



( 7 Votes )