15

Вот след: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 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; 
     } 
    } 

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. Он находится в пределах NinjectConfigurator.cs внутри private void ConfigureNHibernate(IKernel container) { ... }

+0

Недостаточно стека, чтобы узнать, в чем проблема, поэтому, пожалуйста, разместите код своего 'ContinentsController'! – nemesv

+0

Вы скопировали код 'ContinentsController' дважды ... но что угодно. Проблема в том, что одна из ваших зависимостей contructor 'ISession session, IContinentMapper continentMapper, IHttpContinentFetcher continentFetcher, IDateTime dateTime' не зарегистрирована в Ninject. Удостоверьтесь, что все зарегистрировано или отправлено привязки к ядру, чтобы сообщить нам, чего не хватает. И ваш UserController отлично работает, потому что он имеет совершенно другой набор зависимостей. – nemesv

+0

@nemesv Я добавил то, что вы просили. – Komengem

ответ

14

Эта ошибка является известной ошибкой, когда вы не устанавливаете преобразователь зависимостей в своем приложении. Контроллер не смог найти конструктор без параметров для создания контроллера и выполнить метод действия (или метод глагола?). Таким образом, вы должны создать класс распознавателя зависимостей и установить его при инициализации своего веб-приложения. Он будет определять зависимости ваших контроллеров.

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.

+3

Мне нужно было просто добавить 'GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver (ядро); 'моему NinjectWebCommon, не нужно было вызывать метод в global.asax.cs. Thanks – Jaanus

2

Я также столкнулся с этой идентичной ошибкой, но по другой причине, используя Ninject. У меня на самом деле были правильные преобразователи зависимостей и правильная настройка. На самом деле приложение работало хорошо, пока я не попытался решить другую новую зависимость. У меня была регистрация для него, поэтому я не мог понять, чего не хватает.

Вопрос был я случайно разрешил интерфейс к же интерфейсу, в отличие от решения для надлежащего конкретного типа. Таким образом, используя пример из OP я сделал следующее, что приводит к одинаковой ошибки:

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

Примечание разрешающую к IUserManager, который был недосмотр, но делает приводят к одинаковому ошибки из ОП. Очевидно, что исправление заключается в разрешении на конкретный конкретный тип.

13

Вы должны сообщить Ninject, как правильно разрешать зависимости API.

Вы можете использовать ответ Фелипе Ориани, но если вам нравится, пакет NuGet называется WebApiContrib.IoC.Ninject, который сделает это за вас.

  1. В Visual Studio Перейти к: Инструменты> Диспетчер NuGet пакет> Управление NuGet Пакеты для решения

  2. Установите пакет WebApiContrib.IoC.Ninject

  3. Edit: 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.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.

0

Это распространенная проблема возникает, главным образом, при работе с контейнером для инъекций Ninject Dependency. Чтобы решить эту проблему, выполните следующие действия.  Make sure you have Installed the following packages.

Опять идти на это и установить this- enter image description here

Теперь проверьте на App_start folder.You найти следующую вещь (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; 
     } 
    } 

и зарегистрировать ваш dependincy как этот

private static void RegisterServices(IKernel kernel) 
    { 

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

Я уверен, что это сделает ваше решение Работа.

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

Убедитесь, чтобы <> часть представляет собой конкретный класс не интерфейс, так как это создаст ту же ошибку также!

Смежные вопросы