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) { ... }
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.
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.
In Visual Studio Go to: Tools > NuGet Package Manager > Manage NuGet Packages for Solution
Install the WebApiContrib.IoC.Ninject package
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; } }
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.
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
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
.
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).
This is a common problem occurs mainly when you work with Ninject Dependency injection Container.
Please follow the steps to resolve this problem.
Again go for this and Install this-
Now check the the App_start folder.You will find the following thing(NinjectWebcommon.cs).
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.
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!
来源:https://stackoverflow.com/questions/17462175/mvc-4-web-api-controller-does-not-have-a-default-constructor