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 и веб-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
находятся в .
container.Bind<ISession>().ToMethod(CreateSession);
is NHibernate
. Это внутри NinjectConfigurator.cs
внутри private void ConfigureNHibernate(IKernel container) { ... }
8 ответов
эта ошибка является ошибкой, когда вы не установите решатель зависимостей в вашем приложении. Фабрика контроллеров не смогла найти конструктор без параметров для создания контроллера и выполнения метода action (или метода verb?). Итак, вам нужно создать класс распознавателя зависимостей и установить его при инициализации вашего веб-приложения. Он разрешит зависимости ваших контроллеров.
используя 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
метод.
вам нужно сказать Ninject, как правильно разрешить зависимости веб-API.
вы можете использовать ответ Фелипе Ориани, но если вам нравится, есть пакет NuGet под названием WebApiContrib.МОК.Ninject, который сделает это для вас.
в Visual Studio перейдите по ссылке:Инструменты > Менеджер Пакетов NuGet > Управление Пакеты NuGet для решения
установить WebApiContrib.МОК.Ninject пакет
-
изменить: NinjectWebCommon.cs обновить CreateKernel () способ включить: GlobalConfiguration.Конфигурация.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; } }
Я также столкнулся с этой идентичной ошибкой, но по другой причине, используя Ninject
. На самом деле у меня был распознаватель зависимостей и правильная конфигурация. На самом деле приложение работало хорошо, пока я не попытался решить еще одну новую зависимость. У меня была регистрация, поэтому я не мог понять, чего не хватает.
проблема была в том, что я случайно разрешен интерфейс к то же самое интерфейс в отличие от разрешения на правильный конкретный тип. Так используя пример из OP я сделал следующее, что приводит к идентичной ошибке:
container.Bind<IUserManager>().To<IUserManager>();
обратите внимание на разрешение IUserManager
что было упущением, но это тут привести к идентичной ошибке из OP. Очевидно, что исправление состоит в том, чтобы решить правильный конкретный тип.
принятый ответ от 2014. так как тонны людей имели эту проблему, по состоянию на 2016 есть рецепт для этого. это просто добавляет к принятому ответу.
то, как я это делаю, - это установка пакетов Ninject.MVC3
и WebApiContrib.IoC.Ninject
. Файл под названием NinjectWebCommon
добавляется к вашему . Затем вы можете использовать встроенный 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
.
У меня тоже была эта проблема, но оказалось, что один из моих интерфейсов фактически не был реализован никакими классами (я забыл добавить его в объявление класса).
эта распространенная проблема возникает в основном при работе с контейнером инъекций зависимостей Ninject. Для решения этой проблемы выполните следующие действия.
снова перейдите к этому и установите это-
теперь проверьте папку App_Start.Вы найдете следующую вещь (NinjectWebcommon.цезий.)
теперь дважды щелкните и проверьте следующую строку в 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();
}
Я уверен, что это заставит ваше решение работать.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICountingKsRepository>().To<CountingKsRepository>();
убедитесь, что часть To является конкретным классом, а не интерфейсом, так как это также создаст ту же ошибку!
для меня, это был просто вопрос добавления Ninject.Сеть.Веб-API.Пакет Webhost NuGet.
для моих приложений, которые используют как MVC, так и WebApi2, у меня есть следующие пакеты для Ninject:
- Ninject
- Ninject.MVC5
- Ninject.Сеть.Common
- Ninject.Сеть.Общий.WebHost
- Ninject.Сеть.Веб-API
- Ninject.Сеть.Веб-API.WebHost