MVC 4 Web Api Controller does not have a default constructor?

asp.net-mvc-4, asp.net-web-api, c#, inversion-of-control, ninject

Solution

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.

Problem

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) { ... }`

Original source