【问题标题】:MVC5, Web API 2 and NinjectMVC5、Web API 2 和 Ninject
【发布时间】:2014-01-02 22:21:55
【问题描述】:

我使用 Web API 2 创建了一个新的 MVC5 项目,然后从 NuGet 添加了 Ninject.MVC3 包。

构造函数注入在 MVC5 控制器上运行良好,但在尝试将它与 Web API 控制器一起使用时出现错误。

尝试创建“UserProfileController”类型的控制器时出错。确保控制器有一个无参数的公共构造函数。

工作 MVC5 控制器的构造函数:

public class HomeController : Controller
{
    private IMailService _mail;
    private IRepository _repo;

    public HomeController(IMailService mail, IRepository repo)
    {
        _mail = mail;
        _repo = repo;
    }
}

非工作 Web API 控制器的构造函数:

public class UserProfileController : ApiController
{
    private IRepository _repo;

    public UserProfileController(IRepository repo)
    {
        _repo = repo;
    }
}

以下是完整的 NinjectWebCommon.cs 文件:

[assembly: WebActivator.PreApplicationStartMethod(typeof(DatingSite.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(DatingSite.App_Start.NinjectWebCommon), "Stop")]

namespace DatingSite.App_Start
{
using System;
using System.Web;

using Microsoft.Web.Infrastructure.DynamicModuleHelper;

using Ninject;
using Ninject.Web.Common;
using DatingSite.Services;
using DatingSite.Data;

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);
        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
#if DEBUG
        kernel.Bind<IMailService>().To<MockMailService>().InRequestScope();

#else
        kernel.Bind<IMailService>().To<MailService>().InRequestScope();
#endif
        kernel.Bind<SiteContext>().To<SiteContext>().InRequestScope();
        kernel.Bind<IRepository>().To<Repository>().InRequestScope();
    }
}
}

【问题讨论】:

  • 该消息表示没有为 WebAPI 正确注册注入。我怀疑 MVC5 也可能需要 something like this
  • @JoachimIsaksson 我怀疑同样的事情,你知道我需要做什么来注册这个吗?
  • @Declan ... Joachim 的链接告诉您需要做什么,我在 CreateKernel 中看到的唯一区别是您没有这一行: GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel) ;
  • @Declan,如果你有 30 秒的时间,我相信你可以帮助我解决这个问题......非常感谢! stackoverflow.com/questions/22401403/…

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


【解决方案1】:

你有这个问题是因为 Controller 和 ApiController 使用不同的依赖解析器。解决方法很简单。

首先创建 Dependency Resolver 和 Dependency Scope 的新类。你可以使用这个:

 public class NinjectResolver : NinjectScope, IDependencyResolver
{
    private readonly IKernel _kernel;
    public NinjectResolver(IKernel kernel)
        : base(kernel)
    {
        _kernel = kernel;
    }
    public IDependencyScope BeginScope()
    {
        return new NinjectScope(_kernel.BeginBlock());
    }
}

public class NinjectScope : IDependencyScope
{
    protected IResolutionRoot resolutionRoot;
    public NinjectScope(IResolutionRoot kernel)
    {
        resolutionRoot = kernel;
    }
    public object GetService(Type serviceType)
    {
        IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return resolutionRoot.Resolve(request).SingleOrDefault();
    }
    public IEnumerable<object> GetServices(Type serviceType)
    {
        IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return resolutionRoot.Resolve(request).ToList();
    }
    public void Dispose()
    {
        IDisposable disposable = (IDisposable)resolutionRoot;
        if (disposable != null) disposable.Dispose();
        resolutionRoot = null;
    }
}

之后,在 NinjectWebCommon 中的 CreateKernel() 方法中添加下一行

 GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);

【讨论】:

  • 这个答案解释了使用哪个 DependencyResolver 以及何时(与正在使用的 Ninject 库相关)stackoverflow.com/a/22255403/280564
  • 我强烈建议使用现已推出的 nuget 包。我遇到了与上面类似的代码问题
  • -1 因为 IActivationBlock 不是这样做的首选方式,很快就会被删除 (planetgeek.ch/2012/04/23/future-of-activation-blocks)。请更新您的解决方案。我在实现上述解决方案时遇到的问题是在 SingletonScope 中注册的所有依赖项都表现为 TransientScope。这是另一个链接:stackoverflow.com/questions/26708979/…
  • 请用上面的注释更新你的答案,我将删除 -1
【解决方案2】:

Ninject.Web.WebApi NuGet package 刚刚发布。从现在开始,首选的解决方案是使用该包。 我找不到任何相关文档,但安装软件包后一切都对我有用。

Install-Package Ninject.Web.WebApi 

安装后,普通 MVC 和 API 控制器实例均由 Ninject 提供。

如果您已经安装了 Ninject.Web.Common,请确保从 NinjectWebCommon.cs 保存您的绑定,并让 Nuget 在安装期间重写 NinjectWebCommon.cs,并在完成后放回您的绑定。

正如 cmets 中指出的,根据您的执行上下文,您还需要 一个 以下包:

  • Ninject.Web.WebApi.WebHost
  • Ninject.Web.WebApi.OwinHost
  • Ninject.Web.WebApi.Selfhost

最常见的场景是选择 WebHost 包的 IIS。

如果您从头开始启动 IIS MVC5 Web 应用并希望使用 Ninject,请安装以下软件包:

  • Ninject - Ninject 核心 dll
  • Ninject.Web.Common - Ninject 的通用 Web 功能,例如。 InRequestScope()
  • Ninject.MVC5 - MVC 依赖注入器,例如。为 MVC 提供控制器
  • Ninject.Web.Common.WebHost - 当 IIS 启动 Web 应用程序时,从 Ninject.MVC5 注册依赖注入器。如果您不使用 IIS,您将需要不同的包,请查看上方
  • Ninject.Web.WebApi WebApi 依赖注入器,例如。为 WebApi 提供控制器
  • Ninject.web.WebApi.WebHost - 当 IIS 启动 Web 应用程序时,从 Ninject.Web.WebApi 注册依赖注入器。

【讨论】:

  • 为了让它与 IIS 完美配合,我需要安装 Ninject.Web.WebApi.WebHost。这提供了 WebActivatorEx 和 NinjectWebCommon,这对于一个新的 WebApi 项目来说似乎是必要的。
  • 我们可以在同一个项目中使用 MVC 网站和 WebAPI 吗?
  • 当我安装软件包时,这并没有提示覆盖任何文件,但是添加 Ninject.Web.WebApi 和 Ninject.Web.WebApi.WebHost 解决了我的 MVC + Web API 组合应用程序中的问题。
  • 别忘了在RegisterServices(kernel);后面加上GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
  • 截至 2017 年 7 月 13 日,使用 WebApi2 和 MVC5,此解决方案对我不起作用。此页面上的每个 sn-p thisdevmind.com/2015/01/19/…。我根据建议卸载了 WebApi 和 WebApi.WebHost,“推出了我自己的解析器”,并且能够让一切正常工作。我遵循了本指南:peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api
【解决方案3】:

仅适用于其他可能与我有类似设置并像我一样通过谷歌到达这里的人。

我有多个应用程序使用一个 WebApi 项目。如果我没有在 RegisterServices 方法中包含绑定,我会收到上述错误。所以在拉出你的头发之前,只需检查你是否设置了绑定。该错误不会告诉您缺少绑定。如果应用程序与 WebApi 在同一个项目中,它会怎样。

【讨论】:

  • 收到错误“确保控制器具有无参数的公共构造函数。”在这种情况下极具误导性。经过数小时尝试各种其他东西后,这个答案对我有用。只是一个简单的缺失绑定!
【解决方案4】:

我遇到了同样的问题。 安装以下 NuGet 包后:

  • 忍者
  • Ninject.web.WebApi
  • Ninject.web.WebApi.WebHost
  • Ninject.MVC3
  • Ninject.web.Common
  • Ninject.web.Common.WebHost

一切正常

【讨论】:

  • +1 谢谢!。我没有安装“Ninject.web.WebApi.WebHost”,在你发布之后我就安装了。现在一切都好了。
  • 我还需要添加Ninject.web.WebApi.WebHost感谢您的帮助!
  • Ninject.web.WebApi.WebHost 创建您需要的所有文件。您只需要在它提供的 RegisterServices 中编写您的实现。其他答案令人困惑。这是您唯一需要做的事情。
  • 这也是对我有用的答案。但是,我想知道为什么我们需要所有这些软件包。谁能向我推荐一个链接或教程来解释幕后发生的事情?
【解决方案5】:

我发现程序集 Ninject.Web.WebApi.dll 定义了自己的 DependencyResolver 并在 Ninject.Web.WebApi.WebApiModule 类中自动将其注册到内核。

所以我只需在 NinjectWebCommon.CreateKernel 中添加一行...

GlobalConfiguration.Configuration.DependencyResolver = 
    kernel.Get<System.Web.Http.Dependencies.IDependencyResolver>();

最后我的项目有以下依赖:

  • 忍者3.2.0
  • Ninject.Web.Common 3.2.0
  • Ninject.Web.WebApi 3.2.4

【讨论】:

  • 天哪,它有效!此外,GlobalConfiguration 必须具有 using System.Web.Http; 命名空间。
  • 最简单最好的答案
  • 对我有用,我在“RegisterServices(kernel);”之前添加了行,在 try{} 块内。谢谢!
  • 谢谢。你真棒。我浪费了几个小时。这在 MVC 项目中不需要,但在 Web API 中需要。
【解决方案6】:

我最近不得不使用 Web Api 2,这样我才能回答这部分问题。

这些是 Web Api 2 所需的 nuget 包-

Ninject
Ninject.Web.Common
Ninject.Web.Common.WebHost
Ninject.Web.WebApi 
WebActivatorEx 

然后编辑NinjectWebCommon.CreateKernel(..),包括

RegisterServices(kernel);
// the next line is the important one
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;

我已经写了一篇关于这个的更详细的帖子 - http://NoDogmaBlog.bryanhogan.net/2016/04/web-api-2-and-ninject-how-to-make-them-work-together/ 包括一个完整的下载解决方案。

【讨论】:

    【解决方案7】:

    我在使用 Ninject 的项目没有使用 Web API 的解决方案中遇到了这个问题(到目前为止,我的解决方案中有 6 个项目)。我不断得到可怕的“需要无参数构造函数”,这显然意味着当我添加它时,Ninject 注入没有被实例化,因为它被放入空的构造函数中。我尝试了各种解决方案,但最后我检查了我的 Ninject 包,发现 Ninject.Web.Webapi 包已安装。我卸载了它并进行了清理和重建。这解决了这个问题。我的另一个较低级别的项目是引用 Ninject.Web.Api 包,我愚蠢地将它安装到我的 Web 前端项目中。

    我希望这可以帮助那些尝试了所有 Stack 解决方案但一无所获的人。

    【讨论】:

      【解决方案8】:

      您应该在 webAPI 项目中从 Nuget 安装这些包。

      1. 忍者
      2. Ninject.Web.Common
      3. Ninject.Web.Common.WebHost
      4. Ninject.Web.WebApi
      5. Ninject.Web.WebApi.WebHost

      那么你也必须在 Repository 项目中安装 Ninject 包(版本必须与 API 项目中的版本相同)。当为 Ninject 安装了不同的版本时,我遇到了同样的问题。

      【讨论】:

        猜你喜欢
        • 2016-04-12
        • 1970-01-01
        • 2015-06-02
        • 2014-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多