MVC5,Web API 2和Ninject


72

我使用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();
    }
}
}

1
该消息表示未正确为WebAPI注册注入。我怀疑这样的事情可能需要MVC5了。
约阿希姆·伊萨克森

@JoachimIsaksson我怀疑同一件事,您知道我需要做什么才能注册吗?
Declan 2013年

1
@Declan ... Joachim的链接告诉您需要做什么,我在CreateKernel中看到的唯一区别是您没有此行:GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
2013年

@Declan,如果您有30秒的时间,我相信您可以为我解决这个问题。stackoverflow.com/questions/22401403/...
路易斯·戈维亚

Answers:


105

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

Install-Package Ninject.Web.WebApi 

安装后,Ninject会同时提供普通的MVC和API控制器实例。

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

如注释中所指出的,具体取决于您的执行上下文,您还将需要以下软件包之一

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

IIS最常见的情况是选择WebHost软件包。

如果您是从头开始运行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注册依赖项注入器。

50
为了使它与IIS完美配合,我需要安装Ninject.Web.WebApi.WebHost。这提供了WebActivatorEx和NinjectWebCommon,这对于新的WebApi项目似乎是必需的。
Arical

我们可以在同一项目中使用MVC网站和WebAPI吗?
Jitendra Pancholi 2015年

3
安装软件包时,这没有提示覆盖任何文件,但是添加Ninject.Web.WebApi和Ninject.Web.WebApi.WebHost解决了我组合的MVC + Web API应用程序中的问题。
jmsb 2015年

3
不要忘记添加 GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);RegisterServices(kernel);
jaybro

截至2017年7月13日,使用WebApi2和MVC5,此解决方案不适用于我。本页上的每个代码段thisdevmind.com/2015/01/19/…。我按照建议卸载了WebApi和WebApi.WebHost,“滚动了自己的解析器”,并且能够使所有工作正常进行。我遵循了此指南:peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api
凯尔(Kyle)

37

您有此问题,因为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);

1
这个答案解释DependencyResolver要使用的,当(与Ninject库使用)stackoverflow.com/a/22255403/280564

2
我强烈建议使用现在发布的nuget软件包。我遇到了与上述
类似的

1
-1,因为IActivationBlock并非首选方式,因此会很快被删除(planetgeek.ch/2012/04/23/future-of-activation-blocks)。请更新您的解决方案。我在实施上述解决方案时遇到的问题是,在SingletonScope中注册的所有依赖项均表现为TransientScope。这是另一个链接:stackoverflow.com/questions/26708979/…–
shankbond

请使用上面的注释更新您的答案,我将删除-1
shankbond

29

我有同样的问题。安装以下NuGet软件包后:

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

一切正常


8
+1谢谢!我没有安装“ Ninject.web.WebApi.WebHost”,在您发布之后,我就完成了。现在一切都很好。
分钟

3
我还需要Ninject.web.WebApi.WebHost感谢您的协助!
ChaseHardin

2
Ninject.web.WebApi.WebHost创建您需要的所有文件。您只需要在提供的RegisterServices中编写实现。其他答案令人困惑。这是您唯一需要做的事情。
Erik Bergstedt

这也是对我有用的答案。但是,我想知道为什么我们需要所有这些软件包。谁能推荐我一个链接或教程来解释引擎盖下发生了什么?
xabush

24

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

因此,我只需向NinjectWebCommon.CreateKernel添加一行...

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

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

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

1
天哪!另外,GlobalConfiguration必须使用System.Web.Http;命名空间。
Chutipong Roobklom

最简单,最好的答案
avidenic

对我有用,我在“ RegisterServices(kernel);”之前添加了;在try {}块中。谢谢!
rochasdv's

谢谢。你太棒了。我浪费了几个小时。这在MVC项目中不是必需的,但在Web API中是必需的。
Manish Jain

3

仅针对其他人,他们可能对我有类似的设置,并且像我一样通过Google到达了这里。

我使用一个WebApi项目有多个应用程序。如果我没有在RegisterServices方法中包含绑定,则会收到上述错误。因此,在拉出头发之前,只需检查一下绑定设置即可。该错误并不表示您缺少绑定。如果应用程序与WebApi在同一个项目中,将如何处理。


2
得到错误“确保控制器具有无参数的公共构造函数。” 在这种情况下极具误导性。经过数小时的其他尝试,这个答案对我有用。只是一个简单的缺少绑定!
Jededh

2

最近,我不得不使用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//包括全文解决方案下载。


1

您应该从webAPI项目中的Nuget安装这些软件包。

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

然后,您还必须Ninject在Repository项目中安装该软件包(版本必须与API项目中的版本相同)。当为Ninject安装了其他版本时,我遇到了相同的问题。


0

我在使用Ninject的项目未使用Web API的解决方案中遇到了这个问题(到目前为止,我的解决方案中有6个项目)。我一直在获取可怕的“必需的无参数构造函数”,这显然意味着,当我添加它时,Ninject注入并没有实例化,因为它正在放入空的构造函数中。我尝试了各种解决方案,但最后检查了我的Ninject软件包,并看到已安装Ninject.Web.Webapi软件包。我卸载了它,并进行了清理和重建。这解决了问题。我的另一个下层项目引用了Ninject.Web.Api软件包,但愚蠢地将其安装到Web前端项目中。

我希望这可以对尝试过所有Stack解决方案但无所适从的其他人有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.