MVC5, Web API 2 and Ninject

asp.net Web-ApiNinjectasp.net Mvc-5

asp.net Web-Api Problem Overview


I have created a new MVC5 project with Web API 2, I then added the Ninject.MVC3 package from NuGet.

Constructor injection is working fine for the MVC5 controllers, but i am getting an error when trying to use it with the Web API Controllers.

> An error occurred when trying to create a controller of type 'UserProfileController'. Make sure that the controller has a parameterless public constructor.

Constructor for working MVC5 controller:

public class HomeController : Controller
{
    private IMailService _mail;
    private IRepository _repo;

    public HomeController(IMailService mail, IRepository repo)
    {
        _mail = mail;
        _repo = repo;
    }
}

Constructor for non-working Web API Controller:

public class UserProfileController : ApiController
{
    private IRepository _repo;

    public UserProfileController(IRepository repo)
    {
        _repo = repo;
    }
}

Below is the full NinjectWebCommon.cs file:

[assembly: WebActivator.PreApplicationStartMethod(typeof(DatingSite.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(DatingSite.App_Start.NinjectWebCommon), "Stop")]

namespace DatingSite.App_Start
{
using System;
using System.Web;

using Microsoft.Web.Infrastructure.DynamicModuleHelper;

using Ninject;
using Ninject.Web.Common;
using DatingSite.Services;
using DatingSite.Data;

public static class NinjectWebCommon
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start()
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <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;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
#if DEBUG
        kernel.Bind<IMailService>().To<MockMailService>().InRequestScope();

#else
        kernel.Bind<IMailService>().To<MailService>().InRequestScope();
#endif
        kernel.Bind<SiteContext>().To<SiteContext>().InRequestScope();
        kernel.Bind<IRepository>().To<Repository>().InRequestScope();
    }
}
}

asp.net Web-Api Solutions


Solution 1 - asp.net Web-Api

The Ninject.Web.WebApi NuGet package has just been released. From now on the preferred solution is using that package. I couldn't find any related documentation but after installing the package everything worked for me.

Install-Package Ninject.Web.WebApi 

After installation both the normal MVC and the API controller instances are provided by Ninject.

If you have Ninject.Web.Common already installed make sure to save your bindings from NinjectWebCommon.cs and let Nuget rewrite NinjectWebCommon.cs during install and put back your bindings when finished.

As pointed out in the comments depending on your execution context you will need one of the following packages as well:

  • Ninject.Web.WebApi.WebHost
  • Ninject.Web.WebApi.OwinHost
  • Ninject.Web.WebApi.Selfhost

The most common scenario is IIS for that pick the WebHost package.

In the case you start an IIS MVC5 web app from scratch and want to use Ninject install the following packages:

  • Ninject - Ninject core dll
  • Ninject.Web.Common - Common Web functionality for Ninject eg. InRequestScope()
  • Ninject.MVC5 - MVC dependency injectors eg. to provide Controllers for MVC
  • Ninject.Web.Common.WebHost - Registers the dependency injectors from Ninject.MVC5 when IIS starts the web app. If you are not using IIS you will need a different package, check above
  • Ninject.Web.WebApi WebApi dependency injectors eg. to provide Controllers for WebApi
  • Ninject.web.WebApi.WebHost - Registers the dependency injectors from Ninject.Web.WebApi when IIS starts the web app.

Solution 2 - asp.net Web-Api

You have this problem because Controller and ApiController use different Dependency Resolvers. Solution is very simple.

At first create new classes of Dependency Resolver and Dependency Scope. You can use this:

 public class NinjectResolver : NinjectScope, IDependencyResolver
{
    private readonly IKernel _kernel;
    public NinjectResolver(IKernel kernel)
        : base(kernel)
    {
        _kernel = kernel;
    }
    public IDependencyScope BeginScope()
    {
        return new NinjectScope(_kernel.BeginBlock());
    }
}

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;
    }
}

After that, add next line to method CreateKernel() in NinjectWebCommon

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

Solution 3 - asp.net Web-Api

I had the same problem. After installation of the following NuGet packages:

  • Ninject
  • Ninject.web.WebApi
  • Ninject.web.WebApi.WebHost
  • Ninject.MVC3
  • Ninject.web.Common
  • Ninject.web.Common.WebHost

everything works fine

Solution 4 - asp.net Web-Api

I'm found that assembly Ninject.Web.WebApi.dll define own DependencyResolver and register it with kernel in class Ninject.Web.WebApi.WebApiModule automatically.

So I simply add to NinjectWebCommon.CreateKernel one line...

GlobalConfiguration.Configuration.DependencyResolver = 
    kernel.Get<System.Web.Http.Dependencies.IDependencyResolver>();

Finally my project has following dependencies:

  • Ninject 3.2.0
  • Ninject.Web.Common 3.2.0
  • Ninject.Web.WebApi 3.2.4

Solution 5 - asp.net Web-Api

Just for others, who might have a similar set up to me, and got here via google like I did.

I had multiple applications using one WebApi project. I would get the above error if I hadn't included the binding in the RegisterServices method. So before pulling your hair out, just check you have the binding set up. The error doesn't tell you you have missing bindings. Which it would if the Application is in the same project as the WebApi.

Solution 6 - asp.net Web-Api

I recently had to get Web Api 2 working with so I can answer that part of the question.

These are the nuget packages needed for Web Api 2-

Ninject
Ninject.Web.Common
Ninject.Web.Common.WebHost
Ninject.Web.WebApi 
WebActivatorEx 

Then edit NinjectWebCommon.CreateKernel(..) including

RegisterServices(kernel);
// the next line is the important one
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;

I've written a more detailed post about this - http://NoDogmaBlog.bryanhogan.net/2016/04/web-api-2-and-ninject-how-to-make-them-work-together/ including a full solution to download.

Solution 7 - asp.net Web-Api

You are supposed to install these packages from Nuget in webAPI project.

  1. Ninject
  2. Ninject.Web.Common
  3. Ninject.Web.Common.WebHost
  4. Ninject.Web.WebApi
  5. Ninject.Web.WebApi.WebHost

Then you must install the Ninject package in the Repository project as well (the version must be the same as in API project). I had the same issue when there was a different version installed for Ninject.

Solution 8 - asp.net Web-Api

I had this issue in a solution where the project in which I was using Ninject was not using Web API (I have 6 projects so far in my solution). I kept on getting the dreaded "parameterless constructor required" which obviously meant when I added it the Ninject injection was not getting instantiated as it was dropping into the empty constructor. I tried various solutions but in the end I checked my Ninject packages and saw that the Ninject.Web.Webapi package was installed. I uninstalled this and did a clean and rebuild. This solved the issue. My other lower level project was referencing the Ninject.Web.Api package and stupidly I had installed that into my Web front end project.

I hope this may help other people who have tried all the Stack solutions and got no where.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDeclanView Question on Stackoverflow
Solution 1 - asp.net Web-ApiHariView Answer on Stackoverflow
Solution 2 - asp.net Web-ApiArtur MovsesyanView Answer on Stackoverflow
Solution 3 - asp.net Web-ApiOlegView Answer on Stackoverflow
Solution 4 - asp.net Web-Apiuser1295211View Answer on Stackoverflow
Solution 5 - asp.net Web-ApiRichard FranceView Answer on Stackoverflow
Solution 6 - asp.net Web-ApiBryanView Answer on Stackoverflow
Solution 7 - asp.net Web-ApiSh.ImranView Answer on Stackoverflow
Solution 8 - asp.net Web-ApiMike CaveView Answer on Stackoverflow