After ASP.NET Web API was beta-released in February, a number of blog posts came out explaining how to plug Ninject (and other IoC-s, for that matter) to your application through the use of the IDependencyResolver adapter. There was even a NuGet Ninject extension for that (here).

However, these approaches don’t work anymore if you are using the latest ASP.NET Web API (and release candidate) – either from Codeplex source or nightly build packages.

Let’s explore why is that and what you need to do now to be able to use Ninject with ASP.NET Web API.

Important Update: 02 June 2012

As mentioned in the comments, for the builds between 16 May and 02 June (not RC, and not any of the latest so don’t worry), there are issues with methods accepting parameters (i.e. Get(int id)). This has been raised at Codeplex here by Tim (from the comments), I added a repro project there, and turns out, as posted by Brad Wilson, that:

The issue was that we had a concrete internal type in the services container, and Ninject (and surely several other DI containers) would eagerly try to create an instance of that type when they shouldn’t have. Shifted to an internal interface instead to prevent the eager creation.

This has been modified in the ASP.NET Web Stack commit c7e396eec520. So if you are using a build from the above mentioned dates and encounter this problem, make sure to take the latest nightlies or the latest build from Codeplex. Thanks to the readers – Mark, Tim and everyone involved, and especially to Brad for having a look at this!

The old and new IDependencyResolver

The old (beta-compatible) approach for using Ninject with Web API was based on implementing a class deriving from IDependencyResolver. That interface looked like this in beta:

namespace System.Web.Http.Services { public interface IDependencyResolver { object GetService(Type serviceType); IEnumerable<object> GetServices(Type serviceType); } } 1 2 3 4 5 6 7 8 namespace System . Web . Http . Services { public interface IDependencyResolver { object GetService ( Type serviceType ) ; IEnumerable < object > GetServices ( Type serviceType ) ; } }

However, that has changed, and in the current version of Web API (and, as far as I know, the same will be in the release candidate), this interface is as follows:

namespace System.Web.Http.Dependencies { public interface IDependencyResolver : IDependencyScope, IDisposable { IDependencyScope BeginScope(); } } 1 2 3 4 5 6 7 namespace System . Web . Http . Dependencies { public interface IDependencyResolver : IDependencyScope , IDisposable { IDependencyScope BeginScope ( ) ; } }

With IDependencyScope being:

namespace System.Web.Http.Services { public interface IDependencyResolver { object GetService(Type serviceType); IEnumerable<object> GetServices(Type serviceType); } } 1 2 3 4 5 6 7 8 namespace System . Web . Http . Services { public interface IDependencyResolver { object GetService ( Type serviceType ) ; IEnumerable < object > GetServices ( Type serviceType ) ; } }

And IDisposable, obviously:

public interface IDisposable { void Dispose(); } 1 2 3 4 public interface IDisposable { void Dispose ( ) ; }

All the Ninject dependency resolvers targeted at beta will not work now, because there are a couple more interfaces and methods that need to be implemented and catered for. The change is very well explained by Mike Wasson here. Let’s use his Unity example to provide support for Ninject.

We’ll need two classes – one that implements IDependencyScope and the other that implements.

NinjectScope : IDependencyScope

This is our scope container – think of it as a child scope. Our NinjectScope class is going to implement IDependencyScope.

public class NinjectScope : IDependencyScope { protected IResolutionRoot resolutionRoot; public NinjectScope(IResolutionRoot kernel) { resolutionRoot = kernel; } public object GetService(Type serviceType) { IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true); return resolutionRoot.Resolve(request).SingleOrDefault(); } public IEnumerable<object> GetServices(Type serviceType) { IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true); return resolutionRoot.Resolve(request).ToList(); } public void Dispose() { IDisposable disposable = (IDisposable)resolutionRoot; if (disposable != null) disposable.Dispose(); resolutionRoot = null; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class NinjectScope : IDependencyScope { protected IResolutionRoot resolutionRoot ; public NinjectScope ( IResolutionRoot kernel ) { resolutionRoot = kernel ; } public object GetService ( Type serviceType ) { IRequest request = resolutionRoot . CreateRequest ( serviceType , null , new Parameter [ 0 ] , true , true ) ; return resolutionRoot . Resolve ( request ) . SingleOrDefault ( ) ; } public IEnumerable < object > GetServices ( Type serviceType ) { IRequest request = resolutionRoot . CreateRequest ( serviceType , null , new Parameter [ 0 ] , true , true ) ; return resolutionRoot . Resolve ( request ) . ToList ( ) ; } public void Dispose ( ) { IDisposable disposable = ( IDisposable ) resolutionRoot ; if ( disposable != null ) disposable . Dispose ( ) ; resolutionRoot = null ; } }

We are going to use this to get service of specific type. To adhere to the requirements of IDependencyScope, we implement IDisposable. To resolve the dependencies, we use IRequest, to avoid depndency on ResolutionExtensions.

NinjectResolver : NinjectScope, IDependencyResolver

This is going to be our entry point. Think of it as global scope, which will be responsible for passing the activation block to the child scope.

public class NinjectResolver : NinjectScope, IDependencyResolver { private IKernel _kernel; public NinjectResolver(IKernel kernel) : base(kernel) { _kernel = kernel; } public IDependencyScope BeginScope() { return new NinjectScope(_kernel.BeginBlock()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 public class NinjectResolver : NinjectScope , IDependencyResolver { private IKernel _kernel ; public NinjectResolver ( IKernel kernel ) : base ( kernel ) { _kernel = kernel ; } public IDependencyScope BeginScope ( ) { return new NinjectScope ( _kernel . BeginBlock ( ) ) ; } }

We implement IDependencyResolver here, and the rest of the interface is catered for by the fact that we inherit from our previously created NinjectScope.

Now things are ready to roll.

Enabling it in the web application

So, if you have Ninject.MVC3 added to you solution, you’d go to NinjectWebCommon.cs (or Global.asax, depending on you activation preferences) and would add this (after you register your services):

GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); 1 GlobalConfiguration . Configuration . DependencyResolver = new NinjectResolver ( kernel ) ;

Please note that from the Web API Beta, the configuration changed its place and type, as it’s now a property of GlobalConfiguration.Configuration.

Trying it out

In my case I have a simple pair of IUrlRepository and UrlRepository. It’s the same stuff I used here before.

So I register the service:

private static void RegisterServices(IKernel kernel) { kernel.Bind().To(); } 1 2 3 4 private static void RegisterServices ( IKernel kernel ) { kernel . Bind ( ) . To ( ) ; }

And then set up my ApiController:

public class ValuesController : ApiController { private readonly IUrlRepository _repo; public ValuesController(IUrlRepository repo) { _repo = repo; } public IQueryable Get() { return _repo.GetAll(); } } 1 2 3 4 5 6 7 8 9 10 11 12 public class ValuesController : ApiController { private readonly IUrlRepository _repo ; public ValuesController ( IUrlRepository repo ) { _repo = repo ; } public IQueryable Get ( ) { return _repo . GetAll ( ) ; } }

Now I can fire up the controller, and voila:

IoC with Ninject, running smoothly with ASP.NET Web API!

Source code

I put up source code for the two classes on github (no point in adding entire project). It would make sense that this is merged into Ninject.Web.WebAPI on Nuget, but since that project is dependent on ASP.NET Web API (the NuGet version), I guess it won’t happen until ASP.NET Web API RC is available on Nuget (unless that dependency is removed).

Anyway, till next time!

– source on GitHub