MVC 4 Web Api控制器没有默认构造函数?
这是跟踪:
An error has occurred. Type 'ProjectName.Web.Api.Controllers.ContinentsController' does not have a default constructor System.ArgumentException 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)
我觉得这很奇怪,因为public class UsersController : ApiController { ... }
工作得很好。 我比较了2个控制器,所有设置和结构都相似。
我正在使用Ninject
,我的系统设置类似于Jamie Kurtz
Asp.Net Mvc 4和Web Api:从头到尾构建REST服务 。
从堆栈跟踪,是否有人能够发现问题以及如何解决它? 谢谢!
按照要求。
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 Get() { var continents = _session .Query() .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 Get() { return _session.Query(); } [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()); }
然后我有NinjectConfigurator.cs
:
public class NinjectConfigurator { ...... private void AddBindings(IKernel container) { ..... container.Bind().To(); container.Bind().To(); //HttpFetchers container.Bind().To(); container.Bind().To(); //TypeMappers container.Bind().To(); container.Bind().To(); container.Bind().To(); container.Bind().To(); ......... } ....... }
NinjectWebCommon.cs
和NinjectConfigurator.cs
都位于App_Start
文件夹中。
container.Bind().ToMethod(CreateSession);
是NHibernate
。 它位于NinjectConfigurator.cs
内private void ConfigureNHibernate(IKernel container) { ... }
如果未在应用程序中设置依赖项解析程序,则此错误是已知错误。 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>().ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind().To(); // 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
方法。
您需要告诉Ninject如何正确解析Web API依赖项。
您可以使用Felipe Oriani的答案,但如果您愿意,可以使用名为WebApiContrib.IoC.Ninject的NuGet包,它将为您执行此操作。
-
在Visual Studio中转到: 工具> NuGet包管理器>管理解决方案的NuGet包
-
安装WebApiContrib.IoC.Ninject包
-
编辑: NinjectWebCommon.cs并更新CreateKernel()方法以包含:GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
private static IKernel CreateKernel() { var kernel = new StandardKernel(); try { kernel.Bind
>().ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind ().To (); RegisterServices(kernel); //Note: Add the line below: GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); return kernel; } catch { kernel.Dispose(); throw; } }
我也遇到了这个相同的错误,但是使用Ninject
另一个原因。 我实际上有依赖解析器和配置正确。 事实上,该应用程序运行良好,直到我尝试解决另一个新的依赖项。 我有注册设置,所以我无法弄清楚缺少什么。
问题是我意外地将接口解析为相同的接口而不是解析为适当的具体类型。 因此,使用OP中的示例,我执行以下操作会导致相同的错误:
container.Bind().To ();
请注意解析IUserManager
这是一个疏忽但它确实导致OP的相同错误。 显然,解决方法是解决适当的具体类型。
接受的答案是从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
之前调用它。
我也有这个问题,但事实certificate我的一个接口实际上并没有被任何类实现(我忘了把它添加到类声明中)。
这是一个常见问题,主要发生在使用Ninject Dependency injection Container时。 请按照步骤解决此问题。
再次这样做并安装此 –
现在检查App_start文件夹。您将找到以下内容(NinjectWebcommon.cs)。
现在双击并检查CreateKernel()方法中的以下行
private static IKernel CreateKernel() { var kernel = new StandardKernel(); try { kernel.Bind>().ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind().To(); RegisterServices(kernel); GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); return kernel; } catch { kernel.Dispose(); throw; } }
然后像这样注册你的依赖
private static void RegisterServices(IKernel kernel) { kernel.Bind().To().InRequestScope(); }
我相信这会使你的解决方案有效。
private static void RegisterServices(IKernel kernel) { kernel.Bind().To();
确保To <>部分是具体类而不是接口,因为它也会产生相同的错误!
对我来说,这只是添加Ninject.Web.WebApi.Webhost NuGet包的问题。
对于同时使用MVC和WebApi2的应用程序,我有Ninject的以下包:
- Ninject
- Ninject.MVC5
- Ninject.Web.Common
- Ninject.Web.Common.WebHost
- Ninject.Web.WebApi
- Ninject.Web.WebApi.WebHost