【问题标题】:Ninject in ASP.NET MVC4ASP.NET MVC4 中的 Ninject
【发布时间】:2012-07-13 12:09:27
【问题描述】:

因此,经过一番折腾,我终于将 Ninject 连接起来并在我的 MVC4 应用程序中编译。我遇到的问题是 IDependencyScope 接口不再存在,并且 System.Web.Http.Dependencies 命名空间已被取消。

所以,我现在的问题是我已经连接了所有东西,并且在运行我得到的应用程序时:

    Sequence contains no elements

    [InvalidOperationException: Sequence contains no elements]
   System.Linq.Enumerable.Single(IEnumerable`1 source) +379
   Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectMvcHttpApplicationPlugin.cs:53
   Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:52
   Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:31
   Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:53
   Ninject.Web.Common.NinjectHttpApplication.Application_Start() in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\NinjectHttpApplication.cs:81

我无法追踪甚至无法理解它的来源。

我在 Global.asax.cs 中的标准 Ninject 方法如下所示:

        protected override IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());
            kernel.Bind<IRenderHelper>().To<RenderHelper>();

            GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
            return kernel;
        }

        protected override void OnApplicationStarted()
        {
            base.OnApplicationStarted();
            AreaRegistration.RegisterAllAreas();
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            BundleTable.Bundles.RegisterTemplateBundles();
        }

还有我的自定义解析器:

public class NinjectDependencyResolver : IDependencyResolver
{
    private readonly IKernel _kernel;

    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public object GetService(Type serviceType)
     {
         return _kernel.TryGet(serviceType);
     }

     public IEnumerable<object> GetServices(Type serviceType)
     {
         try
         {
             return _kernel.GetAll(serviceType);
         }
         catch (Exception)
         {
             return new List<object>();
         }
     }

     public void Dispose()
     {
         // When BeginScope returns 'this', the Dispose method must be a no-op.
     }
}

这里的任何见解将不胜感激。我已经花了太多时间试图将任何 DI 框架连接到在 .NET 4.5 上运行的最新 MVC4 RC 中,现在已经达到了我对根本不工作的东西的容忍度..

编辑#1 在 github 中深入研究 ExtensionsForIEnumerableOfT.cs 并没有多大帮助:

https://github.com/ninject/ninject/blob/master/src/Ninject/Infrastructure/Language/ExtensionsForIEnumerableOfT.cs

如果我自己写的话,我可能会开始理解这一点,但 Bootstrapper.cs 也没有太大帮助。

https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/Bootstrapper.cs

希望这些细节能让任何可能对 Ninject 有更多经验的人更轻松。

Edit #2遇到的错误具体是在NinjectMvcHttpApplicationPlugin.cs中:

违规行是:

ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());

生活在以下方法中:

public void Start()
{
    ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
    DependencyResolver.SetResolver(this.CreateDependencyResolver());
    RemoveDefaultAttributeFilterProvider();
}

ModelValidatorProviders 集合包含 2 个元素: {System.Web.Mvc.DataErrorInfoModelValidatorProvider} {System.Web.Mvc.ClientDataTypeModelValidatorProvider}

它正在尝试删除单个实例:

System.Web.Mvc.DataAnnotationsModelValidatorProvider

这显然没有加载到 ModelValidationProviders.Providers 集合中。这里有什么想法吗?

解决上述例外并进入下一个

为了解决 ModelValidatorProviders 中的问题,我必须手动添加它所期望的对象。所以现在我的 CreateKernel 方法看起来像:

protected override IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Load(Assembly.GetExecutingAssembly());

    kernel.Bind<IRenderHelper>().To<RenderHelper>();
    kernel.Unbind<IDocumentViewerAdapter>();

    GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
    ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
    FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
    return kernel;
}

现在它运行并进入了 Ninject 的实际内容,但仍然存在一个问题,又一个毫无意义的问题:

Exception Details: Ninject.ActivationException: Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
 3) Injection of dependency IntPtr into parameter method of constructor of type Func{IKernel}
 2) Injection of dependency Func{IKernel} into parameter lazyKernel of constructor of type HttpApplicationInitializationHttpModule
 1) Request for IHttpModule

Suggestions:
 1) Ensure that you have defined a binding for IntPtr.
 2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
 3) Ensure you have not accidentally created more than one kernel.
 4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
 5) If you are using automatic module loading, ensure the search path and filters are correct.

【问题讨论】:

  • 任何急于寻找谷歌搜索答案的人可能不会得到它,但欢迎您尝试。我已经阅读了通过我自己在 google 上的前 10 页搜索可以找到的每一篇文章。目前还没有任何关于我可能做错了什么的见解。
  • 我已经在我的 MVC4 应用程序中安装了 Ninject.MVC3 nuget 包,并且 DI 开箱即用。可以尝试一下吗?
  • 这里也一样,MVC4 和 Ninject.MVC3 包是一种享受...虽然在 .NET 4 上,而不是 4.5...
  • 我认为这就是问题所在…… System.Web.Http 命名空间中发生了一些变化,并且删除了 Dependencies 命名空间。 IDependencyResolver 现在位于 System.Web.Http.Services 中,不在 Dependencies 下。
  • 嗨,让标题简短地显示问题是什么总是有帮助的。

标签: c# ninject asp.net-mvc-4


【解决方案1】:

好吧,在我的头撞墙太久之后,我弄清楚发生了什么。在 .NET 4.5 上运行的 MVC4 的默认项目类型引用了 System.Web.Http 的原始 RC 版本,而不是更新版本。

命名空间丢失,对象不存在,生活并不美好。

解决步骤:

  1. 在 MVC4 项目中删除对 System.Web.Http 的引用
  2. 添加引用 -> System.Web.Http
  3. 删除您为使 System.Web.Http 的旧垃圾版本正常工作而投入的所有变通方法
  4. 在 Ninject 中重新应用标准流程进行接线。

    但是,错误:

    异常详细信息:Ninject.ActivationException:激活 IntPtr 时出错 没有匹配的绑定可用,并且该类型不可自绑定。 激活路径: 3) 将依赖 IntPtr 注入到 Func{IKernel} 类型的构造函数的参数方法中 2) 将依赖Func{IKernel}注入到HttpApplicationInitializationHttpModule类型构造函数的参数lazyKernel中 1) 请求 IHttpModule

    建议: 1) 确保您已为 IntPtr 定义绑定。 2) 如果绑定是在模块中定义的,请确保该模块已加载到内核中。 3) 确保您没有意外创建多个内核。 4) 如果您使用构造函数参数,请确保参数名称与构造函数参数名称匹配。 5) 如果您使用自动加载模块,请确保搜索路径和过滤器正确。

更新通过将 MVC 从 MVC4 Beta 更新到 MVC4 RC 解决了这个问题。

【讨论】:

  • 将服务器升级到 .NET 4.5 后,我遇到了同样的错误。你的帖子让我想到发布后可能会有一些旧的 bin 文件挂出来。我删除了文件夹中的所有内容并重新发布,一切都很好。
  • 很高兴这篇文章对您有所帮助!
【解决方案2】:

查看Pro ASP.NET MVC 3 book。我昨晚刚刚将此代码从 MVC3 移植到 MVC4 并正常工作。准确地说是第 322 页。

我没有看到您将界面映射到具体项目的位置。

Bind<ISomething>().To<Something>();

添加另一个构造函数并添加调用您的映射的方法;

public NinjectDependencyResolver() {
    _kernal = new StandardKernel();
    RegisterServices(_kernel);
}

public static void RegisterServices(IKernel kernel) {
    kernel.Bind<ISomething>().To<Something>();
}

这是解析器可能/应该是什么样子的;

   public class NinjectDependencyResolver : IDependencyResolver {
    private IKernal _kernel;

    public NinjectDependencyResolver(){
        _kernal = StandardKernal();
        AddBindings();
    }

    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public object GetService(Type serviceType)
     {
         return _kernel.TryGet(serviceType);
     }

     public IEnumerable<object> GetServices(Type serviceType)
     {
        return _kernal.GetAll(serviceType);
     }

    public IBindingToSyntax<T> Bind<T>() {
      return _kernal.Bind<T>();
    }

     public static void RegisterServices(IKernel kernel){
      //Add your bindings here. 
      //This is static as you can use it for WebApi by passing it the IKernel
     }
}

Global.Asx -

Application_Start()

方法

DependencyResolver.SetResolver(new NinjectDependencyResolver());

就是这样。


2012 年 11 月 14 日更新

附带说明,如果您正在使用 MVC WebAPI,您将需要使用来自 nuget 的 WebApiContrib.IoC.Ninject。另外,请查看他们的示例asp.net.com 中的“联系人管理器”。这有助于清理 Ninject 的实现

【讨论】:

  • 我看过关于那本书的博客文章。它适用于 .NET 4.0 而不是 .NET 4.5。您是否遇到了 IDependencyScope 不再存在或命名空间 System.Web.Http.Dependencies 不再存在?如果你这样做了,我们也许可以交谈,但给我一个亚马逊书的链接对我绝对没有好处。时间是个问题。
  • 这是您的 .NET 4.0 答案,感谢您的更新,但仍然没有太多帮助。我从那本书上看到了一篇博客文章,相信我我试过了。 DependencyResolver 不再存在,注册行现在看起来像: GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));我会脱掉-1,但仍然对我没有多大帮助。将您的解决方案升级到 .NET 4.5 并将您的 System.Web.Http 引用更新到 4.5,然后您将和我在同一条船上。
  • 嗯,我的目的不仅仅是为您提供代码,而是帮助解决问题。不管你的假设如何——每个人都会时不时地忽略一些事情。教一个人钓鱼……他用鱼钩刺你的眼睛……? =(
  • 感谢 anAgent 的帮助,在花了一整天的时间之后,我有点脾气暴躁。我发现了这个问题,它与 MVC4 项目中加载的程序集的初始 RC 版本有关。他们完全错了。更新参考解决了这个问题,现在我必须删除我在过去 14 小时内所做的所有工作......我累了......而且小便和我的绑定调用在那里......所以比我应该做的更卑鄙。我很抱歉。
【解决方案3】:

只需从您的项目中删除NinjectWebCommon.cs 文件(它位于App_Start 文件夹中)。一切都应该正常。

来源:http://mlindev.blogspot.com.au/2012/09/how-to-implement-dependency-injection.html

【讨论】:

【解决方案4】:

当您从 NuGet 包安装最新的 Ninject.MVC3 时,我们会在 NinjectWebCommon.cs 文件顶部找到以下代码:

[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]

[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]

在这种情况下,我们不需要在 global.asax 中显式注册 ninject

我发现了一篇关于使用 Ninject 和 MVC 4 here 的好内容

【讨论】:

【解决方案5】:

我倾向于将我的 Ninject 引导程序放在一个单独的项目中。为了使用IBindingInSyntax&lt;T&gt;.InRequestScope() 扩展方法,我通过 Nuget 添加了 Ninject.Web.Common 库。唉,这个库包括 app_start 引导程序,导致重复的 NinjectWebCommon 类和通过 WebActivator 的附件(所述项目中的 1 个,MVC 项目本身中的 1 个)。

我从我的引导项目中删除了重复的 App_Start 文件夹,这解决了它。

【讨论】:

    【解决方案6】:

    我遇到了同样的问题,不太确定在以下更改后解决了什么问题

    将 Ninject.MVC4 添加到项目中

    删除了 NinjectWebCommon.cs(生成的文件,因为 global.ascx.cs 文件中已经存在集成)

    【讨论】:

      【解决方案7】:

      我正在使用 DD4T,遇到了同样的错误。

      确认所有包都被nuget包管理器安装后, 我发现缺少一些 DLL/引用(newtonsoft 等):

      然后,在重新安装 Newtonsoft.Json(要重新安装包,请在 Nuget 包管理器中使用以下命令:Update-Package –reinstall Newtonsoft.Json)并从 Tridion Deployer bin 中放入 netrtsn.dll 后,我收到此错误- “序列不包含任何元素”,堆栈跟踪与此问题中给出的完全相同。

      感谢 Naga 提供此解决方案 删除了 NinjectWebCommon.cs(生成的文件,因为集成已经存在于 global.ascx.cs 文件中),呜呜呜!!!所有错误都已解决,Tridion + MVC4 = DD4T 现在运行良好。

      【讨论】:

        【解决方案8】:

        当我在我实际的 MVC 网站项目引用的项目中使用 nuget 安装 Ninject.MVC4 时,我也遇到了这个问题。

        问题是引用项目的App_Start目录下自动安装的NinjectWebCommon.cs文件与我的网站项目中安装的(实际的,有用的)有冲突。从引用的项目中删除 NinjectWebCommon.cs 文件可解决该错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多