web-dev-qa-db-ja.com

MVC 4 Web Api Controllerにはデフォルトのコンストラクターがありませんか?

トレースは次のとおりです。

_<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>
_

_public class UsersController : ApiController { ... }_がうまく機能しているので、これは奇妙です。 2つのコントローラーを比較しましたが、すべての設定と構造は似ています。

私はNinjectを使用しており、_Jamie Kurtz_に似たシステム設定を持っています Asp.Net Mvc 4およびWeb API:REST=開始から終了まで

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

リクエストに応じて

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;
        }
  }
_

UsersController:正常に動作します。

_    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.cs_と_NinjectConfigurator.cs_の両方が_App_Start_フォルダーにあります。

container.Bind<ISession>().ToMethod(CreateSession);NHibernateです。 private void ConfigureNHibernate(IKernel container) { ... }内の_NinjectConfigurator.cs_内にあります

17
Komengem

このエラーは、アプリケーションで依存関係リゾルバーを設定しない場合の既知のエラーです。 Controller Factoryは、コントローラーを作成してアクションメソッド(または動詞メソッド?)を実行するパラメーターなしのコンストラクターを見つけることができませんでした。そのため、依存関係リゾルバークラスを作成し、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;
}

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

17
Felipe Oriani

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

Felipe Orianiの答えを使用できますが、必要に応じてこれを行うWebApiContrib.IoC.NinjectというNuGetパッケージがあります。

  1. Visual Studioの場合:[ツール]> [NuGetパッケージマネージャー]> [ソリューション用のNuGetパッケージの管理]

  2. WebApiContrib.IoC.Ninjectパッケージをインストールします

  3. 編集:NinjectWebCommon.csおよびCreateKernel()メソッドを更新して、次を含めます:GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel );

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

私にとっては、Ninject.Web.WebApi.Webhost NuGetパッケージを追加するだけでした。

MVCとWebApi2の両方を使用するアプリケーションの場合、Ninjectには次のパッケージがあります。

  • Ninject
  • Ninject.MVC5
  • Ninject.Web.Common
  • Ninject.Web.Common.WebHost
  • Ninject.Web.WebApi
  • Ninject.Web.WebApi.WebHost
2
Jamie M

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

問題は、私が偶然インターフェースを同じインターフェースに解決したのに対し、適切な具体的なタイプに解決することでした。そのため、OPの例を使用して次のことを行いましたが、同じエラーになります。

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

IUserManagerの解決に注意してください。これは見落としでしたが、does OPからの同じエラーにつながります。明らかに、修正は適切な具体的な型に解決することです。

2
atconway

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

私が行う方法は、パッケージNinject.MVC3およびWebApiContrib.IoC.Ninjectをインストールすることです。 NinjectWebCommonというファイルがApp_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を呼び出す前に呼び出します。

1
andrei.ciprian

Web.configファイルで依存関係注入のインターフェイスとクラスに言及していなかったときに、それが起こっていました。

0
Mehul Parmar

SimpleInjectorユーザーがここにいる場合...

私にとっては、単にSimpleInjectorInitializer.Initialize();Application_Start()メソッドに追加するのを忘れていただけです。

私は通常、SimpleInjectorInitializerクラスを最近_App_Start_フォルダーに作成し、その中でcontainer.Verify()およびGlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);呼び出しを行います。すべての型登録などを行うGetInitializeContainer()メソッドを呼び出した後.

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

To <>部分がインターフェイスではなく具象クラスであることを確認してください。同じエラーが発生するためです!

0
Andrew Day

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

0
Mark Cidade

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

再びこれに行き、これをインストールします- enter image description here

App_startフォルダーを確認します。次のもの(NinjectWebcommon.cs)が見つかります。 enter image description here

ダブルクリックして、次のようなCreateKernel()メソッドの次の行をチェックします

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

そして、このようにあなたの依存関係を登録します

 private static void RegisterServices(IKernel kernel)
    {

        kernel.Bind<IProductDetails>().To<ProductDetails>().InRequestScope();
    }      

これにより、ソリューションが機能するはずです。

0
Debendra Dash