11

I'm stuck. I was using the method outlined here for wcf web api p6 Ninject working with WCF Web API Preview 5, however things are quite a bit different with the mvc implementation in the beta. There is a good article here http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver that talks about building your own custom dependency resolver, however i would like to use the same implementation i'm using for my mvc view controllers...e.g. Ninject. I've tried a few things based on the IoC Unity example in the article too, but nothing has panned out yet. Any help pointing me in the right direction would be much appreciated. I'm going to keep digging on my own as well. Thanks in advance!

Here's where I'm at. I was using WebActivator to bootstrap the code but I've since dropped it to the Application_Start() just to take one more thing out of the equation.

    protected void Application_Start()
    {
        var kernel = new StandardKernel(new MyNinjectModule());
        GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
    }

And am receiving the following error:
The type Ninject.Web.Mvc.NinjectDependencyResolver does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator.
Parameter name: commonServiceLocator

Found the solution
Perhaps there is/will be a more elegant way but this is now working for me. I'm also adding my custom message handler here as well.

[assembly: WebActivator.PreApplicationStartMethod(typeof(MyApp.AppStart.ApiBootstrapper), "Start")]
namespace MyApp.AppStart
{
    public class ApiBootstrapper
    {
        public static void Start()
        {
            var kernel = new StandardKernel(new MyNinjectModule());
            var resolver = new NinjectDependencyResolver(kernel);
            GlobalConfiguration.Configuration.ServiceResolver.SetResolver(resolver.GetService, resolver.GetServices);
            GlobalConfiguration.Configuration.MessageHandlers.Add(new ApiAuthHandler());
        }
    }
}
Community
  • 1
  • 1
Chris Kirby
  • 685
  • 6
  • 14
  • This is a fairly nice solution: http://haacked.com/archive/2012/03/11/itrsquos-the-little-things-about-asp-net-mvc-4.aspx – Luke Belbina Mar 22 '12 at 23:00
  • also check out @Remo Gloor 's package below if you want to use the same bindings for both types of controllers. You can find it on github and install it from nuget. – Chris Kirby Jun 06 '12 at 16:22

5 Answers5

3

I never used the WebAPI but since the semantic of the IDependencyResolver is exactly the same as the one from MVC3 you should be able to use the same implementation: https://github.com/ninject/ninject.web.mvc/blob/master/mvc3/src/Ninject.Web.Mvc/NinjectDependencyResolver.cs

Update: The Ninject.Web.WebAPi extension adds support for ApiControllers

Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • 2
    This is actually one of the things I tried, with no joy unfortunately. for example ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel)) produces the following error: _Ninject.Web.Mvc.NinjectDependencyResolver does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator_ – Chris Kirby Feb 23 '12 at 18:06
  • The solution was ultimately to use the ninjectdepencencyresolver class, I just had to use an alternate method signature on setresolver. Thanks for the answer! – Chris Kirby Feb 24 '12 at 00:27
1

I found the answer and updated my question above with the solution. The solution itself was more or less present in the Using the Web API Dependency Resolver article, i just had to keep tweaking for ninject. Both answers helped me quickly narrow this down so thanks to @Remo and @James.

Chris Kirby
  • 685
  • 6
  • 14
  • 1
    Can you give some code examples from when you start the binding and the rest of adapter code in one? – Shawn Mclean Mar 25 '12 at 22:10
  • 1
    @ShawnMclean I'm not sure i'm following you. In my solution above, i'm using the webactivator nuget package on a custom class to register the ninject dependency resolver with webapi (defining my bindings in a separate class derived from ninjectmodule). You could also take that same method code and put it in your global.asax files Application_Start() method, i just prefer this bootstrapping approach. There is also a response above that mentions Phil Haack's solution, which essentially allows you to use the same bindings for both mvc and web api. However I prefer my method for the time being. – Chris Kirby Mar 26 '12 at 22:27
0

May sound silly but have you made sure you have a reference to the CommonServiceLocator / CommonServiceLocator.NinjectAdapter nuget package or associated assemblies. Your NinjectDependencyResolver may not be able to resolve the reference to IServiceLocator.

James Alexander
  • 6,132
  • 10
  • 42
  • 56
  • I installed both packages, but still no luck. You can see how the ninject.mvc packacke currently wires itself up via a custom bootstrapper using webactivator...but it must be outside of the apicontroller request lifecycle since the reqeust does not actually go to the controller directly...its created for you by the framework. – Chris Kirby Feb 23 '12 at 21:38
  • The problem was that my code was resolving to this method signature http://msdn.microsoft.com/en-us/library/hh835505(v=vs.108).aspx when i thought it was using this one http://msdn.microsoft.com/en-us/library/hh835218(v=vs.108).aspx . Thankfully there is a 3rd option which gets around the type problem. Thanks for the answer Hamaze! – Chris Kirby Feb 24 '12 at 00:33
0

The same code will work for both MVC and the WebApi, however because the WebApi was inspired by MVC and the MVC assemblies do not have to be referenced in order to use WebApi (or vise versa), there is a fair amount of duplication of code between the two frameworks. If you want to use MVC you're dependencies will come from System.Web.Mvc, if you want to use WebApi you'll use System.Web.Http. If you want to use both you'll have to differentiate in your code which to use when, using a more explicit namespace resolution.

In your case your problem is that MVC came first and the NinjectDependancyResolver class inherits from System.Web.Mvc.IDependencyResolver. You'll want to create an exact duplicate of the NinjectDependancyResolver class and instead inherit from System.Web.Http.IDependencyResolver instead. Use THIS class to setup your IoC and you'll be good to go.

Nick Albrecht
  • 16,607
  • 10
  • 66
  • 101
  • thanks for the response! This is essentially what i did in my answer above because of the duplication problem you are describing. However, because this overload exists on setresolver http://msdn.microsoft.com/en-us/library/hh834083(v=vs.108).aspx i was able to get around creating a duplicate ninject dependency resolver which implements the system.web.http version of the interface. I do wish they had come up with a better way to handle this though. I really should be able to use the same dependency resolver for both. – Chris Kirby Feb 27 '12 at 18:07
0

I found a nice solution here.

It's pretty easy if you're already using the Ninject CommonServiceLocator / Bootstrapper:

private static IKernel CreateKernel() {
   var kernel = new StandardKernel();
   RegisterServices(kernel);

   GlobalConfiguration.Configuration.ServiceResolver
      .SetResolver(new NinjectServiceLocator(kernel));
   return kernel; 
}
Marcel de Castilho
  • 5,812
  • 2
  • 20
  • 19