web-dev-qa-db-ja.com

MVC5、Web API 2およびNinject

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();
    }
}
}
72
Declan

Ninject.Web.WebApi NuGet package がリリースされました。これからは、そのパッケージを使用するのが望ましいソリューションです。関連するドキュメントは見つかりませんでしたが、パッケージをインストールした後、すべてがうまくいきました。

Install-Package Ninject.Web.WebApi 

インストール後、通常のMVCとAPIコントローラーインスタンスの両方がNinjectによって提供されます。

Ninject.Web.Commonが既にインストールされている場合は、NinjectWebCommon.csからバインディングを保存し、Nugetがインストール中にNinjectWebCommon.csを書き換え、完了したらバインディングを元に戻すようにしてください。

実行コンテキストに応じてコメントで指摘されているように、必要になります 1 以下のパッケージも同様です。

  • 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から依存関係インジェクターを登録します。
103
Hari

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);
38
Artur Movsesyan

同じ問題がありました。次のNuGetパッケージのインストール後:

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

すべてが正常に動作します

29
Oleg

Assembly Ninject.Web.WebApi.dllは独自のDependencyResolverを定義し、それをクラスNinject.Web.WebApi.WebApiModuleのカーネルに自動的に登録することがわかりました。

したがって、NinjectWebCommon.CreateKernelに1行追加するだけです...

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
24
user1295211

似たような設定をしていて、私と同じようにグーグル経由でここに来た人のために。

1つのWebApiプロジェクトを使用する複数のアプリケーションがありました。 RegisterServicesメソッドにバインディングを含めなかった場合、上記のエラーが発生します。そのため、髪を引っ張る前に、バインディングが設定されていることを確認してください。エラーは、不足しているバインディングがあることを通知しません。アプリケーションがWebApiと同じプロジェクトにある場合、どのようになりますか。

3
Richard France

最近、Web Api 2を使用する必要があったので、質問のその部分に答えることができます。

これらは、Web Api 2に必要なヌゲットパッケージです。

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 / ダウンロードする完全なソリューションを含む。

2
Bryan

Ninjectを使用していたプロジェクトがWeb APIを使用していないソリューションでこの問題が発生しました(これまでに6つのプロジェクトが私のソリューションにあります)。私は恐ろしい「パラメーターレスコンストラクターが必要」を取得し続けました。これは明らかに、Ninjectインジェクションが空のコンストラクターにドロップされるためインスタンス化されなかったことを意味します。さまざまなソリューションを試しましたが、最終的にNinjectパッケージを確認し、Ninject.Web.Webapiパッケージがインストールされていることを確認しました。これをアンインストールし、クリーンアップして再構築しました。これで問題は解決しました。私の他の下位レベルのプロジェクトはNinject.Web.Apiパッケージを参照していましたが、愚かにもそれをWebフロントエンドプロジェクトにインストールしていました。

これが、すべてのStackソリューションを試したが、どこにも行かない他の人々の助けになることを願っています。

0
Mike Cave