Web API 2 and ninject, how to make them work together

Full source code to download.

I’ve been using ninject for a few years, but every time I use it with Web Api I hit some problem and they usually stem from not including the right nuget packages, not changing the DependencyResolver or (once) forgetting how to make a binding!

For my future self and your reference, here is how it is done.

1. Nuget packages

Add Ninject.Web.WebApi using nuget to your Web Api project.

That will install two other package dependencies:
Ninject
Ninject.Web.Common

To make everything work you need to add one more nuget package
Ninject.Web.Common.WebHost

This will pull down the WebActivatorEx package and add a new class called NinjectWebCommon to your App_Start directory.

2. Edit NinjectWebCommon.cs

NinjectWebCommon.cs is missing a key feature if you want to use ninject to construct the controllers, and I presume that is why you are using ninject inside a Web Api project.

In the CreateKernel() method add the second line shown below. Now ninject will be used to resolve controller dependencies.

RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;

You will need to add a couple of using statements too –

using System.Web.Http;
using Ninject.Web.WebApi;

3. Register some services

To actually register some services we move to the RegisterServices(..) method do some binding.

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<ICaclulator>().To<Caclulator>();
}

4. Use it all

And here is the usage in the controller.

    public class ValuesController : ApiController
    {
        private readonly ICaclulator _caclulator;
        public ValuesController(ICaclulator calculator)
        {
            _caclulator = calculator;
        }

        public int Get(int num1, int num2)
        {
            return _caclulator.Add(num1, num2);
        }
    }

Full source code to download.

45 thoughts on “Web API 2 and ninject, how to make them work together

  1. I am getting Entry point was not found Exception. If i comment below line i am not seeing that exception
    “GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);”

    Why it is happening ?

  2. Perfect. Just what I needed. This was hard to find. I had spent a good hour trying to figure this one out on my own. Thanks.

  3. Seriously dude, i do not have words to thank you. I have spent hours to figure out why my VS 2015 MVC-WebApi would not work using Ninject. Followed your steps and there you go..worked like charm…!

    Thanks
    TheAqua

  4. I can’t believe I spent more than 10 hours to make this work. I have one large Solution Project which has MVC app, WebApi app, SignalR app, Business layer and DataAccess layer. I included Ninject in the MVC, WebApi and SignalR apps because even though they are in one solution, they are separate self-hosting applications.

    Because I had multiple projects in the solution and they all had several mutual dependencies to each other but also to external NuGet libraries I often encountered exceptions of type “Could not load file or assembly ‘AssemblyName PublicKeyToken=null’ or one of its dependencies”. This exceptions were due to the usage of different versions from the external libraries that my modules used.
    To solve this problem I decided that the easiest and cleanest way was to right click on the Solution Project and click Manage NuGet packages for solution. This way I made sure that anytime I added some Library to any of my project, that exact same library will be also added to another project from the solution if I were to need it.
    BUT this was huge mistake and I needed more than 10 hours to figure out how to configure Ninject in the three modules that I needed it. I naively installed and reinstalled the Ninject packages from the NuGet Package Manager and of course those packages contained some libraries that I would need on one place but not on another.

    After hours of pulling hair and reading the Stack Overflow forums I finally came across this simple blog post which solved the problem with the WebApi (I managed to configure the MVC and SignalR projects successfully).
    I learned a valuable lesson today. That is, do not paste code or include libraries unless you are absolutely sure what is the reason for the existence of that code and how it should be used.

    • Hi Dejan,

      I lost quite a few hours with Ninject and Web API too, that’s way a I wrote it down for my future self (and others).

      Thanks for getting in touch.

      Bryan

  5. Well I was hoping this would have helped but your source code doesn’t include your NinjectDependencyResolver class as far as I can see, and you don’t reference it at all in this post except for the line where you set it as the resolver in NinjectWebCommon.

    I’m having an issue running my API project with ninject when I have a solution with multiple startup projects (a WebAPI2 project, and an asp.net MVC5 project).

      • I see what you are saying now, however my issue is persisting even after a complete wipe of all ninject in my API project and following through this and a couple other possible methods for setting ninject up (wiping each time I tried a different method…). None of them are working, which is super frustrating because I’ve gotten this type of setup to work previously, and the same type of setup isn’t working now.

        • What do you mean by wiping?
          What is not working?

          I have occasionally seen some problems with ninject which required me to go into the bin and obj folders and delete everything by hand – Clean in Visual Studio was not enough.

          • By wiping I am referring to completely uninstalling Ninject from the troublesome project. I have done so again, including the ninject stuff in the bin/obj folders, and still I am unable to instantiate a controller via ninject.

            I know sometime in the last year or two the recommended approach for Ninject on the Api side of things was to not set the global resolver, I will now be looking into that again and see if the new preferred method works for me.

  6. I introduced the dependency into home controller like this. Note its an mvc controller.

    public class HomeController : Controller
    {
    public ActionResult Index(ICaclulator calculator)
    {
    ViewBag.Title = “Home Page”;

    return View();
    }
    }

    Now its not working.

    Server Error in ‘/’ Application.

    Cannot create an instance of an interface.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.MissingMethodException: Cannot create an instance of an interface.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Any idea why?

  7. I’m writing an WebApi2 only app (without ASP.NET MVC – create new project, select empty web app + WebApi2 checkbox, then add Ninject.Web.WebApi.WebHost package, and then set up DependencyResolver as you did). When I run the application I get the following exception:

    ————–
    An exception of type ‘Ninject.ActivationException’ occurred in Ninject.dll but was not handled in user code

    Additional information: Error activating ModelValidatorProvider using binding from ModelValidatorProvider to NinjectDefaultModelValidatorProvider

    A cyclical dependency was detected between the constructors of two services.

    Activation path:

    3) Injection of dependency ModelValidatorProvider into parameter defaultModelValidatorProviders of constructor of type DefaultModelValidatorProviders

    2) Injection of dependency DefaultModelValidatorProviders into parameter defaultModelValidatorProviders of constructor of type NinjectDefaultModelValidatorProvider

    1) Request for ModelValidatorProvider

    Suggestions:

    1) Ensure that you have not declared a dependency for ModelValidatorProvider on any implementations of the service.

    2) Consider combining the services into a single one to remove the cycle.

    3) Use property injection instead of constructor injection, and implement IInitializable

    if you need initialization logic to be run after property values have been injected.
    —————-

    Any thoughts?

    • “A cyclical dependency was detected between the constructors of two services.” You’ll have to break that dependency, without knowing more about your code I can’t really suggest much else.

    • I don’t see any references to Ninject or any other DI in your code. I suggest downloading my sample solution and developing your code on top of it.

  8. Thanks for the article! I’m getting this error: An error occurred when trying to create a controller of type ‘TestController’. Make sure that the controller has a parameterless public constructor., any ideas?

  9. Thanks for this, I’ve used Ninject 50 times, but never for an API, so I was pulling my hair out trying to figure out why it wasn’t working. You saved my weekend!

  10. Great post. Out of curiosity, why in Startup.Auth.cs are you using app.CreatePerOwinContext(ApplicationDbContext.Create) (line 26)?

    Let’s say a controller or service needs the ApplicationDbContext injected, this would be injected from the OwinContext and not Ninject. Is there a reason for the mix?

  11. Pingback: Reusing Polly Policies with Dependency Injection | no dogma blog

Leave a Reply

Your email address will not be published. Required fields are marked *