在我的API控制器完成其请求后,为什么会出现Ninject InvalidOperation异常?

时间:2012-12-18 10:46:34

标签: asp.net-mvc-4 asp.net-web-api ninject

我有一个MVC4网络应用程序项目作为更大解决方案的一部分。我也有一个测试项目。我正在使用一堆不会被重做的代码,所以我不能总是做出我想做的改变。

MVC4网络应用程序具有“普通”控制器和Web API控制器。我们使用的是Web API的RTM版本,而不是RC。

我试图将IoC引入项目中。使用NuGet安装技术(而不是下载DLL并直接引用它们),我安装了:

Ninject v3.0.1.10, 
Ninject.MVC3 v3.0.0.6
Ninject.Extensions.Factory v3.0.1.0
Ninject.Web.Common v 3.0.0.7

我的解决方案中没有其他引用的组件可以使用Ninject。

然后,按照Brad Wilson和他的Github Gist https://gist.github.com/2417226给出的建议,以及Filip W在http://www.strathweb.com/2012/05/using-ninject-with-the-latest-asp-net-web-api-source/给出的类似建议,我实施了一个NinjectResolver,并且“注册”了全局配置。

当我启动网络应用时,默认网页会映射到Index上的ProjectController操作。这将呈现一个视图,该视图使用Knockout通过调用名为ApiController的{​​{1}}操作来填充ViewModel。

我的ApiProjectController.Get()代码如下所示:

NinjectWebCommon.cs

using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Web.Http; using System.Web.Http.Dependencies; using Ninject.Extensions.Factory; using Ninject.Syntax; using OfficeWebApp.Utilities; [assembly: WebActivator.PreApplicationStartMethod(typeof(OfficeWebApp.App_Start.NinjectWebCommon), "Start")] [assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(OfficeWebApp.App_Start.NinjectWebCommon), "Stop")] namespace OfficeWebApp.App_Start { using System; using System.Web; using Microsoft.Web.Infrastructure.DynamicModuleHelper; using Ninject; using Ninject.Web.Common; public static class NinjectWebCommon { private static readonly Bootstrapper Bootstrapper = new Bootstrapper(); /// <summary> /// Starts the application /// </summary> public static void Start() { DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule)); DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule)); Bootstrapper.Initialize(CreateKernel); } /// <summary> /// Stops the application. /// </summary> public static void Stop() { Bootstrapper.ShutDown(); } /// <summary> /// Creates the kernel that will manage your application. /// </summary> /// <returns>The created kernel.</returns> private static IKernel CreateKernel() { var kernel = new StandardKernel(); kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); RegisterServices(kernel); GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel); return kernel; } /// <summary> /// Load your modules or register your services here! /// </summary> /// <param name="kernel">The kernel.</param> private static void RegisterServices(IKernel kernel) { kernel.Bind<IDataManagerConnection>().To<DataManagerConnection>().WithConstructorArgument("overriddenConnectionString", string.Empty); kernel.Bind<IDataManagerConnectionFactory>().ToFactory(); } } 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<object> 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()); } } } 代码为:

ProjectController

...和public class ProjectController : Controller { private readonly IDataManagerConnectionFactory _dataManagerConnectionFactory; public ProjectController(IDataManagerConnectionFactory dataManagerConnectionFactory) { _dataManagerConnectionFactory = dataManagerConnectionFactory; } [HttpGet] public ActionResult Index() { //TODO: ViewBag.Organisation = "Preview"; return View(); } }

ApiProjectController

public class ApiProjectController : ApiController { private readonly IDataManagerConnectionFactory _dataManagerConnectionFactory; public ProjectsController(IDataManagerConnectionFactory dataManagerConnectionFactory) { _dataManagerConnectionFactory = dataManagerConnectionFactory; } [HttpGet] public IEnumerable<ProjectTileModel> Get() { using (IDataManagerConnection connection = _dataManagerConnectionFactory.Create()) { List<ProjectTileModel> projectViewModels = connection.DataManager.GetProjectInfos() .ToList(); return projectViewModels; } } } 操作方法出现后,Ninject会向我抛出以下异常:

ApiProjectController.Get()

调用堆栈如下所示:

Error loading Ninject component ICache
No such component has been registered in the kernel's component container.

Suggestions:
  1) If you have created a custom subclass for KernelBase, ensure that you have properly
     implemented the AddComponents() method.
  2) Ensure that you have not removed the component from the container via a call to RemoveAll().
  3) Ensure you have not accidentally created more than one kernel.

Ninject.dll!Ninject.Components.ComponentContainer.Get(System.Type component) Line 160 C# Ninject.dll!Ninject.Components.ComponentContainer.Get<Ninject.Activation.Caching.ICache>() Line 116 + 0x46 bytes C# Ninject.Web.Common.dll!Ninject.Web.Common.OnePerRequestHttpModule.DeactivateInstancesForCurrentHttpRequest.AnonymousMethod__1(Ninject.IKernel kernel) Line 74 + 0x27 bytes C# Ninject.dll!Ninject.GlobalKernelRegistration.MapKernels(System.Action<Ninject.IKernel> action) Line 75 + 0xe bytes C# Ninject.Web.Common.dll!Ninject.Web.Common.OnePerRequestHttpModule.DeactivateInstancesForCurrentHttpRequest() Line 76 C# Ninject.Web.Common.dll!Ninject.Web.Common.OnePerRequestHttpModule.Init.AnonymousMethod__0(object o, System.EventArgs e) Line 56 + 0x9 bytes C# 文件中的以下Ninject代码中引发了此异常:

ComponentContainer.cs

注意:在上面指定的行中, Type implementation = _mappings[component].FirstOrDefault(); // <-- see note below... if (implementation == null) throw new InvalidOperationException(ExceptionFormatter.NoSuchComponentRegistered(component)); // <-- exception thrown here 集合只包含一个项目;密钥与我们要查找的_mappings匹配(Type),但ICache成员(Values)为空(0计数)

我应该使用List<Type>吗?是否有一些有趣的事情发生,因为我在我的绑定中使用OnePerRequestHttpModule?我真的不知道为什么.ToFactory()正在调用OnePerRequestHttpModule,但是Ninject似乎想要得到它的内部缓存(也许??)

我做错了什么?

1 个答案:

答案 0 :(得分:0)

我从未真正深入到此。我不知道它是否是Ninject中的错误,或者我是否只是错误地使用它。但是,我通过将IoC容器切换到AutoFAC解决了我的问题。