19

Here is the trace:

<Error>
   <Message>An error has occurred.</Message>

   <ExceptionMessage>
      Type 'ProjectName.Web.Api.Controllers.ContinentsController' does not have a default constructor
   </ExceptionMessage>

   <ExceptionType>System.ArgumentException</ExceptionType>

   <StackTrace>
      at System.Linq.Expressions.Expression.New(Type type)

      at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)

      at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)

      at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
   </StackTrace>
</Error>

I find this weird as public class UsersController : ApiController { ... } is working just fine. I have compared the 2 controllers, all the settings and structures are similar.

I am using Ninject and i have my system setup similar to Jamie Kurtz Asp.Net Mvc 4 and the Web Api: Building a REST Service from Start to Finish.

From the stack trace, is anyone able to spot the problem and how to solve it? Thanks!

As Requested.

ContinentsController

[LoggingNHibernateSession]
public class ContinentsController : ApiController
{
    private readonly ISession _session;
    private readonly IContinentMapper _continentMapper;
    private readonly IHttpContinentFetcher _httpContinentFetcher;
    private readonly IDateTime _dateTime;

    public ContinentsController(ISession session, IContinentMapper continentMapper, IHttpContinentFetcher continentFetcher, IDateTime dateTime)
    {
        _session = session;
        _continentMapper = continentMapper;
        _httpContinentFetcher = continentFetcher;
        _dateTime = dateTime;
    }

    public IEnumerable<Continent> Get()
    {
        var continents = _session
            .Query<Data.Model.Continent>()
            .Select(_continentMapper.CreateContinent)
            .ToList();

        return continents;
    }

    public Continent Get(long id)
    {
        var modelContinent = _httpContinentFetcher.GetContinent(id);
        var continent = _continentMapper.CreateContinent(modelContinent);

            return continent;
        }
  }

UsersController: Works just fine.

    public class UsersController : ApiController
    {
        private readonly ISession _session;
        private readonly IUserManager _userManager;
        private readonly IUserMapper _userMapper;
        private readonly IHttpUserFetcher _userFetcher;

        public UsersController(
            IUserManager userManager,
            IUserMapper userMapper,
            IHttpUserFetcher userFetcher,
            ISession session)
        {
            _userManager = userManager;
            _userMapper = userMapper;
            _userFetcher = userFetcher;
            _session = session;
        }

        [Queryable]
        public IQueryable<Data.Model.User> Get()
        {
            return _session.Query<Data.Model.User>();
        }

        [LoggingNHibernateSession]
        public User Get(Guid id)
        {
            var user = _userFetcher.GetUser(id);
            return _userMapper.CreateUser(user);
        }
    }

I am using NinjectWebCommon.cs and in it, i have this and a few other default methods.:

        private static void RegisterServices(IKernel kernel)
        {
            var containerConfigurator = new NinjectConfigurator();
            containerConfigurator.Configure(kernel);

            GlobalConfiguration.Configuration.MessageHandlers.Add(kernel.Get<BasicAuthenticationMessageHandler>());
        }

Then i have NinjectConfigurator.cs:

public class NinjectConfigurator
{
    ......
    private void AddBindings(IKernel container)
        {
            .....
            container.Bind<IDateTime>().To<DateTimeAdapter>();
            container.Bind<IDatabaseValueParser>().To<DatabaseValueParser>();

            //HttpFetchers
            container.Bind<IHttpUserFetcher>().To<HttpUserFetcher>();
            container.Bind<IHttpContinentFetcher>().To<HttpContinentFetcher>();                                

            //TypeMappers
            container.Bind<IUserManager>().To<UserManager>();
            container.Bind<IMembershipInfoProvider>().To<MembershipAdapter>();
            container.Bind<IUserMapper>().To<UserMapper>();
            container.Bind<IContinentMapper>().To<ContinentMapper>();    
            .........
        }
     .......
}

Both NinjectWebCommon.cs and NinjectConfigurator.cs are located in the App_Start folder.

container.Bind<ISession>().ToMethod(CreateSession); is NHibernate. It is within NinjectConfigurator.cs inside private void ConfigureNHibernate(IKernel container) { ... }

Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
Komengem
  • 3,662
  • 7
  • 33
  • 57
  • The stacktrace is not enough to find out what is your problem, so please post the code of your `ContinentsController`! – nemesv Jul 04 '13 at 05:02
  • 1
    You have copied the code of the `ContinentsController` twice... but whatever. The problem is that one of the your contructor dependencies `ISession session, IContinentMapper continentMapper, IHttpContinentFetcher continentFetcher, IDateTime dateTime` is not registered in Ninject. Make sure that everything is registered or post your kernel bindings to lets us what is missing. And your UserController works fine because it has a completely different set of dependencies. – nemesv Jul 04 '13 at 05:15
  • @nemesv I added what you requested. – Komengem Jul 04 '13 at 05:29
  • 1
    One more thing you can check: make sure that also all the constructor paramters of the `HttpContinentFetcher` and `ContinentMapper` also have been registered in the contianer... – nemesv Jul 04 '13 at 05:46
  • @nemesv `HttpContinentFetcher` has `ISession` and `ContinentMapper` would take in child object's Mappers. `ISession` is already registered, and if i had a child of Continents i.e country, it would be registered. – Komengem Jul 04 '13 at 06:27
  • Did you set the Dependency Resolver on start up of your application? – Felipe Oriani Jul 05 '13 at 18:16
  • @FelipeOriani I have Dependency Resolver, and UserController works just fine. – Komengem Jul 05 '13 at 20:16

10 Answers10

18

You need to tell Ninject how to correctly resolve Web API dependencies.

You can use Felipe Oriani's answer, but if you like there is a NuGet package called WebApiContrib.IoC.Ninject which will do this for you.

  1. In Visual Studio Go to: Tools > NuGet Package Manager > Manage NuGet Packages for Solution

  2. Install the WebApiContrib.IoC.Ninject package

  3. Edit: NinjectWebCommon.cs and update the CreateKernel() method to include: GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
    
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
    
            RegisterServices(kernel);
    
            //Note: Add the line below:
            GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
    
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }
    
16

This error is a known error when you do not set the dependency resolver in your application. The Controller Factory could not find a parameterless constructor to create the controller and execute the action method (or verb method?). So, you have to create a dependency resolver class and set it on the initialization of your web app. It will resolve dependencies of your controllers.

Using ninject, you could try something like this:

using Ninject; 
using Ninject.Syntax; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics.Contracts; 
using System.Web.Http.Dependencies; 

namespace MyApplication.App_Start 
{     
    public class NinjectDependencyScope : IDependencyScope     
    {         
        private IResolutionRoot resolver;         

        internal NinjectDependencyScope(IResolutionRoot resolver)         
        {             
            Contract.Assert(resolver != null);             
            this.resolver = resolver;         
        }         

        public void Dispose()         
        {             
            IDisposable disposable = resolver as IDisposable;             
            if (disposable != null)                 
                disposable.Dispose();             
            resolver = null;         
        }         

        public object GetService(Type serviceType)         
        {             
            if (resolver == null)                 
                throw new ObjectDisposedException("this", "This scope has already been disposed");             

            return resolver.TryGet(serviceType);         
        }   

        public IEnumerable GetServices(Type serviceType)         
        {             
            if (resolver == null)                 
                throw new ObjectDisposedException("this", "This scope has already been disposed");             

            return resolver.GetAll(serviceType);         
        }     
    }     

    public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver     
    {         
        private IKernel kernel;         
        public NinjectDependencyResolver(IKernel kernel)             
            : base(kernel)         
        {             
            this.kernel = kernel;         
        }         

        public IDependencyScope BeginScope()         
        {             
            return new NinjectDependencyScope(kernel.BeginBlock());         
        }     
    } 
}

The NinjectDependencyResolver class takes a Ninject StandardKernel object as a constructor argument and this reference is used whenever a dependency scope is pipelined. To make this all work, the NinjectDependencyResolver class is assigned to the application's global configuration:

private static IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
    kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

    // register all your dependencies on the kernel container
    RegisterServices(kernel);

    // register the dependency resolver passing the kernel container
    GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

    return kernel;
}

On your Global.asax.cs file in the end of Application_Start event, call this CreateKernel method.

Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
  • 3
    I had to just add `GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel); ` to my NinjectWebCommon, didn't have to call method in global.asax.cs. Thanks – Jaanus Jan 16 '14 at 16:41
  • `in the end of Application_Start event` -> this is important! I am using Unity, not Ninject, but I was getting all kinds of exceptions as I was setting the Resolver too early. Moving it to the end of this handler fixed it. Thanks Felipe! – thisextendsthat May 17 '19 at 12:45
5

For me, it was just a matter of adding the Ninject.Web.WebApi.Webhost NuGet package.

For my applications that use both MVC and WebApi2, I have the following packages for Ninject:

  • Ninject
  • Ninject.MVC5
  • Ninject.Web.Common
  • Ninject.Web.Common.WebHost
  • Ninject.Web.WebApi
  • Ninject.Web.WebApi.WebHost
Jamie M
  • 870
  • 1
  • 8
  • 18
  • 2
    Had to add the Ninject.Web.Common.WebHost and Ninject.Web.WebApi.WebHost packages after updating Ninject 3.2.x to 3.3.x – Rubenisme Feb 11 '19 at 19:09
2

I also ran into this identical error but from another cause using Ninject. I actually had the dependency resolver and configuration correct. In fact the app was working well until I tried to resolve another new dependency. I had the registration set for it, so I could not figure out what was missing.

The issue was I accidentally resolved the Interface to the same Interface as opposed to resolving to the proper concrete type. So using an example from the OP I did the following which results in the identical error:

container.Bind<IUserManager>().To<IUserManager>();

Notice resolving to IUserManager which was an oversight but it does lead to the identical error from the OP. Obviously the fix is to resolve to the proper concrete type.

atconway
  • 20,624
  • 30
  • 159
  • 229
1

I had this problem, too, but it just turned out that one of my interfaces weren't actually implemented by any classes (I forgot to add it to the class declaration).

Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
1

The accepted answer is from 2014. Since tons of people had this issue, as of 2016 there's a recipe for it. This just adds to the accepted answer.

The way I do it is by installing packages Ninject.MVC3 and WebApiContrib.IoC.Ninject. A file called NinjectWebCommon gets added to your App_Start folder. You can then use the built-in NinjectResolver.

Just add this method:

private static void AddWebApiSupport(StandardKernel kernel)
{
  // Support WebAPI
  GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
  GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider), new NinjectWebApiFilterProvider(kernel));
}

and call it before calling RegisterServices.

andrei.ciprian
  • 2,895
  • 1
  • 19
  • 29
0

This is a common problem occurs mainly when you work with Ninject Dependency injection Container. Please follow the steps to resolve this problem.  Make sure you have Installed the following packages.

Again go for this and Install this- enter image description here

Now check the the App_start folder.You will find the following thing(NinjectWebcommon.cs). enter image description here

Now double click and check the following line in CreateKernel() method like this

 private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

And then Register your dependincy like this

 private static void RegisterServices(IKernel kernel)
    {

        kernel.Bind<IProductDetails>().To<ProductDetails>().InRequestScope();
    }      

I am sure this will make your solution work.

Debendra Dash
  • 5,334
  • 46
  • 38
0
private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<ICountingKsRepository>().To<CountingKsRepository>();

Make sure the To<> part is a concrete class not an interface, as that will create the same error also!

Andrew Day
  • 563
  • 10
  • 23
0

In case any SimpleInjector users end up in here...

For me, it was simply that I had forgotten to add SimpleInjectorInitializer.Initialize(); to my Application_Start() method.

I typically create a SimpleInjectorInitializer class in the App_Start folder these days, within which I do the container.Verify() and GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container); calls; after I've called my GetInitializeContainer() method that's doing all the type registrations, etc.

Scott Fraley
  • 378
  • 4
  • 14
0

It was happening with me when I did not mention the interface and class for dependency injection in the web.config file.

Mehul Parmar
  • 347
  • 4
  • 21