这是跟踪:
<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>
我觉得这很奇怪,因为public class UsersController : ApiController { ... }
工作正常。我比较了2个控制器,所有的设置和结构都是相似的。
我正在使用Ninject
,我的系统设置类似于Jamie Kurtz
Asp.Net Mvc 4 and the Web Api: Building a REST Service from Start to Finish。
从堆栈跟踪中,是否有人能够发现问题以及如何解决问题?谢谢!
按要求。
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 :工作得很好。
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);
}
}
我正在使用NinjectWebCommon.cs
并且在其中,我有这个和其他一些默认方法。:
private static void RegisterServices(IKernel kernel)
{
var containerConfigurator = new NinjectConfigurator();
containerConfigurator.Configure(kernel);
GlobalConfiguration.Configuration.MessageHandlers.Add(kernel.Get<BasicAuthenticationMessageHandler>());
}
然后我有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>();
.........
}
.......
}
NinjectWebCommon.cs
和NinjectConfigurator.cs
都位于App_Start
文件夹中。
container.Bind<ISession>().ToMethod(CreateSession);
是NHibernate
。它位于NinjectConfigurator.cs
内private void ConfigureNHibernate(IKernel container) { ... }
答案 0 :(得分:16)
如果未在应用程序中设置依赖项解析程序,则此错误是已知错误。 Controller Factory找不到无参数构造函数来创建控制器并执行action方法(或动词方法?)。因此,您必须创建依赖项解析程序类并将其设置为Web应用程序的初始化。它将解决控制器的依赖关系。
使用ninject
,你可以尝试这样的事情:
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());
}
}
}
NinjectDependencyResolver
类将Ninject StandardKernel
对象作为构造函数参数,并且只要对依赖项作用域进行流水线操作,就会使用此引用。
为了使这一切正常,NinjectDependencyResolver
类被分配给应用程序的全局配置:
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;
}
在Application_Start事件结束时的Global.asax.cs
文件中,调用此CreateKernel
方法。
答案 1 :(得分:16)
您需要告诉Ninject如何正确解析Web API依赖项。
您可以使用Felipe Oriani的答案,但如果您愿意,可以使用名为WebApiContrib.IoC.Ninject的NuGet软件包来为您执行此操作。
在Visual Studio中转到:工具&gt; NuGet包管理器&gt;管理 NuGet解决方案包
安装 WebApiContrib.IoC.Ninject 包
编辑: NinjectWebCommon.cs 并更新 CreateKernel()方法以包含: 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;
}
}
答案 2 :(得分:2)
我也遇到了这个相同的错误,但是使用Ninject
来自另一个原因。我实际上有依赖解析器和配置正确。事实上,该应用程序运行良好,直到我尝试解决另一个新的依赖项。我有注册设置,所以我无法弄清楚缺少什么。
问题是我意外将接口解析为相同的接口,而不是解析为正确的具体类型。因此,使用OP中的示例,我执行以下操作会导致相同的错误:
container.Bind<IUserManager>().To<IUserManager>();
请注意解析为IUserManager
这是一个疏忽,但 会导致OP出现相同的错误。显然,解决方法是解决适当的具体类型。
答案 3 :(得分:1)
接受的回答是从2014年开始。由于很多人都有这个问题,截至2016年已经有了这个问题。这只会增加接受的答案。
我这样做的方法是安装包Ninject.MVC3
和WebApiContrib.IoC.Ninject
。名为NinjectWebCommon
的文件会添加到您的App_Start
文件夹中。然后,您可以使用内置的NinjectResolver
。
只需添加此方法:
private static void AddWebApiSupport(StandardKernel kernel)
{
// Support WebAPI
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider), new NinjectWebApiFilterProvider(kernel));
}
并在致电RegisterServices
之前调用它。
答案 4 :(得分:0)
我也有这个问题,但事实证明我的一个接口并没有被任何类实际实现(我忘了将它添加到类声明中)。
答案 5 :(得分:0)
这是一个常见问题,主要发生在使用Ninject Dependency injection Container时。 请按照步骤解决此问题。 的 强>
现在检查App_start文件夹。您将找到以下内容(NinjectWebcommon.cs)。
现在双击并检查CreateKernel()方法中的以下行,如下所示
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;
}
}
然后像这样注册你的依赖
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IProductDetails>().To<ProductDetails>().InRequestScope();
}
我相信这会使您的解决方案有效。
答案 6 :(得分:0)
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICountingKsRepository>().To<CountingKsRepository>();
确保To&lt;&gt; part是具体类而不是接口,因为它也会产生相同的错误!
答案 7 :(得分:0)
如果有任何SimpleInjector
用户最终出现在这里...
对我来说,只是因为我忘记将SimpleInjectorInitializer.Initialize();
添加到我的Application_Start()
方法中。
这几天我通常会在SimpleInjectorInitializer
文件夹中创建一个App_Start
类,在其中我进行container.Verify()
和GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
调用;在调用我的GetInitializeContainer()
方法之后,该方法正在执行所有类型注册等。
答案 8 :(得分:0)
当我在web.config文件中没有提及依赖项注入的接口和类时,这就是我发生的事情。