15

はトレースです:public class UsersController : ApiController { ... }がうまく働いているようMVC 4 Web APIのコントローラにデフォルトコンストラクタがありませんか?ここ

<Error> 
    <Message>An error has occurred.</Message> 

    <ExceptionMessage> 
     Type 'ProjectName.Web.Api.Controllers.ContinentsController' does not have a default constructor 
    </ExceptionMessage> 

    <ExceptionType>System.ArgumentException</ExceptionType> 

    <StackTrace> 
     at System.Linq.Expressions.Expression.New(Type type) 

     at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) 

     at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) 

     at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) 
    </StackTrace> 
</Error> 

は、私は、これは奇妙見つけます。私は2つのコントローラを比較して、すべての設定と構造が似ています。

私はNinjectを使用していますが、Jamie KurtzAsp.Net Mvc 4 and the Web Api: Building a REST Service from Start to Finishと似たシステム設定をしています。

スタックトレースから、誰でも問題を見つけて解決する方法は?ありがとう!

リクエストされました。

ContinentsController

[LoggingNHibernateSession] 
public class ContinentsController : ApiController 
{ 
    private readonly ISession _session; 
    private readonly IContinentMapper _continentMapper; 
    private readonly IHttpContinentFetcher _httpContinentFetcher; 
    private readonly IDateTime _dateTime; 

    public ContinentsController(ISession session, IContinentMapper continentMapper, IHttpContinentFetcher continentFetcher, IDateTime dateTime) 
    { 
     _session = session; 
     _continentMapper = continentMapper; 
     _httpContinentFetcher = continentFetcher; 
     _dateTime = dateTime; 
    } 

    public IEnumerable<Continent> Get() 
    { 
     var continents = _session 
      .Query<Data.Model.Continent>() 
      .Select(_continentMapper.CreateContinent) 
      .ToList(); 

     return continents; 
    } 

    public Continent Get(long id) 
    { 
     var modelContinent = _httpContinentFetcher.GetContinent(id); 
     var continent = _continentMapper.CreateContinent(modelContinent); 

      return continent; 
     } 
    } 

がUserController:だけで正常に動作します。

public class UsersController : ApiController 
    { 
     private readonly ISession _session; 
     private readonly IUserManager _userManager; 
     private readonly IUserMapper _userMapper; 
     private readonly IHttpUserFetcher _userFetcher; 

     public UsersController(
      IUserManager userManager, 
      IUserMapper userMapper, 
      IHttpUserFetcher userFetcher, 
      ISession session) 
     { 
      _userManager = userManager; 
      _userMapper = userMapper; 
      _userFetcher = userFetcher; 
      _session = session; 
     } 

     [Queryable] 
     public IQueryable<Data.Model.User> Get() 
     { 
      return _session.Query<Data.Model.User>(); 
     } 

     [LoggingNHibernateSession] 
     public User Get(Guid id) 
     { 
      var user = _userFetcher.GetUser(id); 
      return _userMapper.CreateUser(user); 
     } 
    } 

私はこれと他のいくつかのデフォルトのメソッドを持って、NinjectWebCommon.csとそれにを使用しています。:

 private static void RegisterServices(IKernel kernel) 
     { 
      var containerConfigurator = new NinjectConfigurator(); 
      containerConfigurator.Configure(kernel); 

      GlobalConfiguration.Configuration.MessageHandlers.Add(kernel.Get<BasicAuthenticationMessageHandler>()); 
     } 

その後、私はNinjectConfigurator.csを持っている:

public class NinjectConfigurator 
{ 
    ...... 
    private void AddBindings(IKernel container) 
     { 
      ..... 
      container.Bind<IDateTime>().To<DateTimeAdapter>(); 
      container.Bind<IDatabaseValueParser>().To<DatabaseValueParser>(); 

      //HttpFetchers 
      container.Bind<IHttpUserFetcher>().To<HttpUserFetcher>(); 
      container.Bind<IHttpContinentFetcher>().To<HttpContinentFetcher>();         

      //TypeMappers 
      container.Bind<IUserManager>().To<UserManager>(); 
      container.Bind<IMembershipInfoProvider>().To<MembershipAdapter>(); 
      container.Bind<IUserMapper>().To<UserMapper>(); 
      container.Bind<IContinentMapper>().To<ContinentMapper>();  
      ......... 
     } 
    ....... 
} 

両方NinjectWebCommon.csNinjectConfigurator.csですApp_Startフォルダーにあります。

container.Bind<ISession>().ToMethod(CreateSession);は、NHibernateである。これはNinjectConfigurator.csの内部private void ConfigureNHibernate(IKernel container) { ... }

+0

stacktraceで問題が分かりにくいので、 'ContinentsController'のコードを投稿してください! – nemesv

+0

あなたは 'ContinentsController'のコードを2回コピーしましたが、何でも。問題は、あなたのコンストラクタの依存関係のうちの1つが、Ninjectに登録されていない、「セッションセッション、IContinentMapper、continentMapper、IHttpContinentFetcher、continentFetcher、IDateTime dateTime」が登録されていないことです。すべてが登録されていることを確認するか、カーネルのバインディングを投稿して、欠けているものを私たちに教えてください。あなたのUserControllerは完全に異なる依存関係を持っているのでうまく動作します。 – nemesv

+0

@nemesvあなたがリクエストしたものを追加しました。 – Komengem

答えて

14

このエラーは、アプリケーションに依存関係リゾルバを設定しないとわかっているエラーです。コントローラファクトリはコントローラを作成し、アクションメソッド(または動詞メソッド?)を実行するためのパラメータのないコンストラクタを見つけることができませんでした。したがって、依存関係リゾルバクラスを作成し、Webアプリケーションの初期化時にクラスを設定する必要があります。それはあなたのコントローラの依存関係を解決します。 ninjectを使用して

は、あなたがこのような何かを試みることができる:

using Ninject; 
using Ninject.Syntax; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics.Contracts; 
using System.Web.Http.Dependencies; 

namespace MyApplication.App_Start 
{  
    public class NinjectDependencyScope : IDependencyScope  
    {   
     private IResolutionRoot resolver;   

     internal NinjectDependencyScope(IResolutionRoot resolver)   
     {    
      Contract.Assert(resolver != null);    
      this.resolver = resolver;   
     }   

     public void Dispose()   
     {    
      IDisposable disposable = resolver as IDisposable;    
      if (disposable != null)     
       disposable.Dispose();    
      resolver = null;   
     }   

     public object GetService(Type serviceType)   
     {    
      if (resolver == null)     
       throw new ObjectDisposedException("this", "This scope has already been disposed");    

      return resolver.TryGet(serviceType);   
     } 

     public IEnumerable GetServices(Type serviceType)   
     {    
      if (resolver == null)     
       throw new ObjectDisposedException("this", "This scope has already been disposed");    

      return resolver.GetAll(serviceType);   
     }  
    }  

    public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver  
    {   
     private IKernel kernel;   
     public NinjectDependencyResolver(IKernel kernel)    
      : base(kernel)   
     {    
      this.kernel = kernel;   
     }   

     public IDependencyScope BeginScope()   
     {    
      return new NinjectDependencyScope(kernel.BeginBlock());   
     }  
    } 
} 

NinjectDependencyResolverクラスは、コンストラクタの引数としてNinject StandardKernelオブジェクトを取得し、依存関係のスコープをパイプライン化されたときには、この参照が使用されています。 は、このすべての作品にするために、NinjectDependencyResolverクラスは、アプリケーションのグローバル設定に割り当てられている:

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

    // register all your dependencies on the kernel container 
    RegisterServices(kernel); 

    // register the dependency resolver passing the kernel container 
    GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel); 

    return kernel; 
} 

をのApplication_Startイベントの最後には、あなたのGlobal.asax.csファイルでは、このCreateKernelメソッドを呼び出します。

+3

'GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(カーネル)を追加するだけでした。 '私のNinjectWebCommonには、global.asax.csのメソッドを呼び出す必要はありませんでした。ありがとう – Jaanus

2

この同じエラーが発生しましたが、別の原因でもNinjectを使用しました。私は実際に依存リゾルバと構成が正しいと思っていました。実際、別の新しい依存関係を解決しようとするまで、アプリはうまく機能していました。私はそれのために登録が設定されていたので、何が欠けていたのか分からなかった。

問題は、適切なコンクリートの型に解決するとは対照的に、私は同じインタフェースへのインタフェースを解決し、誤ってました。だから、OPからの例を使用して、私は同じエラーになり、次のやった:

container.Bind<IUserManager>().To<IUserManager>(); 

お知らせがIUserManagerに解決監督だったが、それはOPから同じエラーにリードを行います。明らかに、修正は適切な具体的なタイプに解決することです。

13

Web APIの依存関係を正しく解決する方法をNinjectに伝える必要があります。

あなたはFelipe Orianiの答えを使用できますが、好きな場合は、これを行うWebApiContrib.IoC.NinjectというNuGetパッケージがあります。

  • WebApiContrib.IoC.Ninjectパッケージをインストールソリューションのためツール]> [NuGetパッケージマネージャ]> [管理 NuGetパッケージ

  • 編集:Visual Studioで

    1. にしますNinjectWebCommon.csを更新するCreateKernel()メソッドには: GlobalConfiguration.Configuration.DependencyResolver =新しいNinjectResolver(カーネル);

      private static IKernel CreateKernel() 
      { 
          var kernel = new StandardKernel(); 
      
          try 
          { 
           kernel.Bind<Func<IKernel>>().ToMethod(ctx =>() => new Bootstrapper().Kernel); 
           kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 
      
           RegisterServices(kernel); 
      
           //Note: Add the line below: 
           GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); 
      
           return kernel; 
          } 
          catch 
          { 
           kernel.Dispose(); 
           throw; 
          } 
      } 
      
  • +1

    ねえ男!ありがとう、これは私のwebApiアプリケーションで完璧に動作します。 MVC 5 – willyMon

    +1

    ありがとう、ありがとう、それは大きな助けになった幸せなコーディング:d –

    0

    私も、この問題を抱えていたが、それはちょうど私のインターフェイスのいずれかが実際に(私はクラス宣言に追加するのを忘れて)任意のクラスで実装されていないことが判明。

    1

    受け入れられる回答は2014年です。数多くの人々がこの問題を抱えていたため、2016年の時点でそれにはレシピがあります。これは受け入れられた答えに追加するだけです。

    パッケージのインストール方法は、Ninject.MVC3WebApiContrib.IoC.Ninjectです。ファイルNinjectWebCommonApp_Startフォルダに追加されます。組み込みのNinjectResolverを使用することができます。

    ただ、この方法で追加します:

    private static void AddWebApiSupport(StandardKernel kernel) 
    { 
        // Support WebAPI 
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); 
        GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider), new NinjectWebApiFilterProvider(kernel)); 
    } 
    

    をしてRegisterServicesを呼び出す前に、それを呼び出します。

    0

    これは、主にNinject Dependency injection Containerで作業するときに発生する一般的な問題です。 この問題を解決する手順を実行してください。  Make sure you have Installed the following packages.

    は再び、このために行くと、次のこと(NinjectWebcommon.cs)を見つけるでしょうApp_start folder.Youをチェック今this- enter image description here

    をインストールします。 enter image description here

    ダブルクリックして、この

    private static IKernel CreateKernel() 
        { 
         var kernel = new StandardKernel(); 
         try 
         { 
          kernel.Bind<Func<IKernel>>().ToMethod(ctx =>() => new Bootstrapper().Kernel); 
          kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 
    
          RegisterServices(kernel); 
          GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); 
          return kernel; 
         } 
         catch 
         { 
          kernel.Dispose(); 
          throw; 
         } 
        } 
    

    ようCreateKernel()メソッドに次の行をチェックし、私は、これはあなたのソリューションを作ると確信しています。この

    private static void RegisterServices(IKernel kernel) 
        { 
    
         kernel.Bind<IProductDetails>().To<ProductDetails>().InRequestScope(); 
        }  
    

    のようなあなたのdependincyを登録作業。

    0
    private static void RegisterServices(IKernel kernel) 
         { 
          kernel.Bind<ICountingKsRepository>().To<CountingKsRepository>(); 
    

    <>の部分に確認してくださいそれはまた同じエラーが作成されますよう、具体的なクラスではないインタフェースです!

    関連する問題