web-dev-qa-db-ja.com

ninjectを使用したASP.NET Web APIバインディング

私はmvc4 rc更新プログラムをインストールしたばかりで、ほとんど運のないAPIアプリケーションを構築しようとしています。

Ninjectを使用していますが、コントローラーをロードできません。エラーが発生し続ける

タイプ「Api.Controllers.ConsumerController」にはデフォルトのコンストラクタがありません

私はmvcとインジェクションを使用するのが非常に新しいので、我慢してください。

私はnugetを介して作成されるデフォルトのバインディングに特別なことは何もしていません

 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)
    {
        kernel.Bind<IConsumerRepository>().To<ConsumerRepository>();
    }        
}

私のコントローラーは次のようになります

   private readonly IConsumerRepository _repository;

    public ConsumerController(IConsumerRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public IQueryable<Consumer> Get(Guid id)
    {
        return _repository.Get(id).AsQueryable();
    }

APIコントローラーをninjectで動作させるには何が必要ですか?

これがシンプルなものなら申し訳ありません

しかし、webcommon.csをこれに変更した後、Michaelの提案を試しました。

  private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(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)
    {
        kernel.Bind<IConsumerRepository>().To<ConsumerRepository>();
    }

次の場合にエラーが発生します

var kernel = new StandardKernel();

と呼ばれます

アセンブリ「Ninject.Web.WebApi、Version = 3.0.0.0、Culture = neutral、PublicKeyToken = c7192dc5380945e7」のタイプ「Ninject.Web.WebApi.Filter.DefaultFilterProvider」のメソッド「GetFilters」には実装がありません。

私は何が欠けていますか?

36
Diver Dan

Brad Wilson について尋ねたところ、MVC4 RCで変更されました。

GlobalConfiguration.Configuration.ServiceResolverGlobalConfiguration.Configuration.DependencyResolverに移動しました

この実装を使用して、Web APIのNinject DependencyResolverを作成します。 https://Gist.github.com/2417226

NinjectWebCommon.cs

// Register Dependencies
RegisterServices(kernel);

// Set Web API Resolver
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
60
Michael Baird

NuGetパッケージWebApiContrib.IoC.Ninjectをインストールし、次のコード行をNinjectWebCommon.csに追加できます。

GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
6
Ryan Spears

この一般的なエラーメッセージ

タイプ「Api.Controllers.ConsumerController」にはデフォルトのコンストラクタがありません

コンストラクタをパブリックにしない場合、または引数が欠落しているためにIoCコンテナによって依存関係を解決できない場合にも発生します。

エラーメッセージは控えめに言っても誤解を招きます。

6
badikumar

「...デフォルトコンストラクターがありません」を検索中にここに到着した人のために、静かに失敗する構成をデバッグする簡単な方法を探しています:

  1. コンストラクターが呼び出されるまで、コンストラクターが注入したオブジェクトを削除する
  2. 以前に注入され、現在は初期化されていないオブジェクトのそれぞれについて、次を使用して呼び出します。

ServiceLocator.Current.GetInstance<[OBJ-TYPE]>()

問題のオブジェクトは、説明的なメッセージでActivationExceptionを引き起こします。あなたは何かを手に入れるでしょう。

ServiceLocatorの修正後の呼び出しを忘れずに削除してください。すなわち。これはnotデバッグ外でサービスロケーターアンチパターンを使用することを推奨します。

1
corolla

私はその古い投稿を知っていますが、いくつかのリンクで解決策を見つけたので、ここで共有します。それが役に立てば幸い。

http://weblogs.asp.net/hajan/archive/2013/03/16/quick-tip-how-to-make-ninject-work-with-asp-net-web-api.aspx? CommentPosted = true#commentmessage

0
Rasshme Chawla

まだ誰かが問題を抱えている場合は、なんらかの理由でninjectがmvc 4で期待する動作をしていないことを聞いてください。WebAPIでは、このコードを書く必要があります

public DefaultController() : base() { }  

これにより、デフォルトコンストラクターがないというエラーがなくなり、getメソッドからデータを取得する必要がある場合は、次のコードを記述します。

public IEnumerable<YourModelGoesHere> Get() 
{
    return context.YourData;  
} 

たとえば、ここでもdbクラスにアクセスする必要があります。

DefaultConnection context = new DefaultConnection(); 
0
user3247368

うまくいけば、これは他の誰かに役立つ...

私は同じ問題を抱えていましたが、コントローラの初期化を担当するアセンブリの登録を担当するクラスを移動することに関連していました。 Webからフレームワークプロジェクトに移動しました。

Autofacを使用しますが、他のコンテナにも同じことが適用されます。

呼び出していました:

builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

Webアプリケーション内にある場合は正常に動作しますが、実行中のアセンブリにコントローラーが含まれなくなったため、フレームワークプロジェクトに移動すると上記の例外がスローされました。

代わりに更新する必要がありました:

builder.RegisterApiControllers(Assembly.GetCallingAssembly());
0
timothyclifford

Ninjectは、IOC依存関係が適切に設定されていない場合に通常発生するように、例外をスローしなかったようです。この問題に対する私の解決策はここにありましたが、私が発見したことから、それは多くの異なるタイプのセットアップの問題である可能性があります。

コントローラー:

public class ContestsController : ApiController
{
    //Ninject wouldn't inject this CTOR argument resulting in the error
    public ContestsController(IContestEntryService contestEntryService)
    {

依存関係:

public class ContestEntryService : IContestEntryService
{

    public ContestEntryService(IContestsContext contestsContext)
    {

誤った構成:

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IContestsContext>()
              .To<ContestsContext>()
              .InRequestScope();

        kernel.Bind(x =>
            x.FromAssembliesMatching("MyNameSpace.*")
             .SelectAllClasses()
             .BindAllInterfaces()
         );

正しい構成:

    private static void RegisterServices(IKernel kernel)
    {
         kernel.Bind(x =>
            x.FromAssembliesMatching("MyNameSpace.*")
             .SelectAllClasses()
             .BindAllInterfaces()
         );

         kernel.ReBind<IContestsContext>()
              .To<ContestsContext>()
              .InRequestScope();

一般的に、Ninjectはこれらの種類のエラーの報告については非常に優れているため、実際にこのエラーをループさせることになりました。

0
John Culviner

ninject.MvcXXXパッケージをインストールするだけです。XXX-MVCのバージョン...

0
Andrey Burykin

このエラーメッセージもありましたが、インターフェイスの1つが実際にはどのクラスにも実装されていないことがわかりました(クラス宣言に追加するのを忘れていました)。

0
Mark Cidade

コンテナをフレームワークに登録しましたか?私はautofacを使用することを好みます。autofacをAPIとともに使用する方法の例を次に示します。 http://alexmg.com/post/2012/03/08/Autofac-ASPNET-Web-API-%28Beta%29-Integration.aspx

また、Mark SeemanはWebAPIを使用したDIに関する一般的な投稿をしています。

http://blog.ploeh.dk/2012/03/20/RobustDIWithTheASPNETWebAPI.aspx

プロエから:

GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
    t => this.container.Kernel.HasComponent(t) ?
        this.container.Resolve(t) :
        null,
    t => this.container.ResolveAll(t).Cast<object>());

上記はglobal.asaxで実行する必要があります

0
jflood.net