MVC5,Web API 2和Ninject

时间:2013-12-15 14:13:26

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

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

8 个答案:

答案 0 :(得分:102)

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

Install-Package Ninject.Web.WebApi 

安装完成后,普通的MVC和API控制器实例都由Ninject提供。

如果已经安装了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 core 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注册依赖注入器。

答案 1 :(得分:38)

您遇到此问题,因为Controller和ApiController使用不同的依赖关系解析器。解决方案很简单。

首先创建依赖性解析器和依赖关系范围的新类。你可以用这个:

 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);

答案 2 :(得分:29)

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

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

一切正常

答案 3 :(得分: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

答案 4 :(得分:3)

对于其他可能与我有相似设置的人,并像我一样通过谷歌来到这里。

我使用一个WebApi项目有多个应用程序。如果我没有在RegisterServices方法中包含绑定,我会得到上述错误。因此,在拔出头发之前,只需检查您是否已设置绑定。该错误并不能告诉您缺少绑定。如果应用程序与WebApi位于同一项目中,那将是什么。

答案 5 :(得分: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/,包括完整的下载解决方案。

答案 6 :(得分:1)

您应该在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安装了不同版本时,我遇到了同样的问题。

答案 7 :(得分:0)

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

我希望这可以帮助那些尝试过所有Stack解决方案但没有在任何地方的人。