Я следовал этому руководству, которое отлично работало, пока я не изменил свой, DbContext
чтобы иметь дополнительный конструктор. У меня возникли проблемы с разрешением, и я не знаю, что делать, чтобы это исправить. Есть ли простой способ заставить его захватить конструктор без параметров, или я подхожу к этому неправильно?
DbContext
с двумя конструкторами:
public class DashboardDbContext : DbContext
{
public DashboardDbContext() : base("DefaultConnection") { }
public DashboardDbContext(DbConnection dbConnection, bool owns)
: base(dbConnection, owns) { }
}
SiteController
конструктор:
private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
_repo = repo;
}
Репозиторий:
DashboardDbContext _context;
public DashboardRepository(DashboardDbContext context)
{
_context = context;
}
UnityResolver
код:
public class UnityResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityResolver(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = _container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
_container.Dispose();
}
}
WebApiConfig:
var container = new UnityContainer();
container.RegisterType<IDashboardRepository, DashboardRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
Ошибка при вызове WebApi:
System.InvalidOperationException: произошла ошибка при попытке создать контроллер типа «SiteController». Убедитесь, что в контроллере есть открытый конструктор без параметров.
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()
InnerException: System.ArgumentException: Тип «Dashboard.Web.Controllers.SiteController» не имеет конструктора по умолчанию.
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)
Учебник был отличным и работал у меня хорошо, пока я не добавил второй конструктор.
источник
SiteController
это то, что должно иметь конструктор без параметров, а неDashboardDbContext
.SiteController
?DbContext
в репозиторий?Ответы:
Дело в том, что вас укусила эта проблема . По сути, произошло то, что вы явно не зарегистрировали свои контроллеры в своем контейнере. Unity пытается разрешить незарегистрированные конкретные типы за вас, но, поскольку не может решить эту проблему (из-за ошибки в вашей конфигурации), возвращает null. Он принудительно возвращает null, потому что веб-API заставляет его делать это из-за
IDependencyResolver
контракта. Поскольку Unity возвращает значение null, веб-API попытается создать сам контроллер, но поскольку у него нет конструктора по умолчанию, он выдаст исключение «Убедитесь, что у контроллера есть открытый конструктор без параметров». Это сообщение об исключении вводит в заблуждение и не объясняет истинную причину.Вы бы увидели гораздо более четкое сообщение об исключении, если бы явно зарегистрировали свои контроллеры, и поэтому вы всегда должны регистрировать все корневые типы явно.
Но, конечно, ошибка конфигурации возникает из-за того, что вы добавляете второй конструктор в свой
DbContext
. Unity всегда пытается выбрать конструктор с наибольшим количеством аргументов, но не знает, как разрешить этот конкретный конструктор.Итак, настоящая причина в том, что вы пытаетесь использовать возможности автоматического подключения Unity для создания файла
DbContext
.DbContext
это особый тип, который не должен подключаться автоматически. Это тип фреймворка, поэтому вам следует отказаться от его регистрации с помощью фабричного делегата :источник
IDependencyResolver
а толькоIControllerActivator
вместо него.В моем случае это произошло из-за исключения внутри конструктора моей внедренной зависимости (в вашем примере - внутри конструктора DashboardRepository). Исключение было обнаружено где-то внутри инфраструктуры MVC. Я обнаружил это после того, как добавил логи в соответствующие места.
источник
Make sure that the controller has a parameterless public constructor.
но вполне возможно, что зависимость настроена, но исключение глубоко в недрах помешало ее разрешению.У меня была такая же проблема, и я решил ее, внеся изменения в файл UnityConfig.cs. Чтобы решить проблему зависимости в файле UnityConfig.cs, вы должны добавить:
источник
У меня такая же проблема. Два дня гуглил. Наконец я случайно заметил, что проблема была в модификаторе доступа конструктора Контроллера. Я не ставил
public
ключевое слово за конструктор контроллера.Я добавляю этот опыт в качестве еще одного ответа, возможно, кто-то другой совершил аналогичную ошибку.
источник
Иногда из-за того, что вы разрешаете свой интерфейс в ContainerBootstraper.cs, очень сложно обнаружить ошибку. В моем случае произошла ошибка при разрешении реализации интерфейса, который я ввел в контроллер api. Мне не удалось найти ошибку, потому что я разрешил интерфейс в моем bootstraperContainer следующим образом:
container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
затем я добавил следующую строку в свой контейнер начальной загрузки:
container.RegisterType<MyController>();
поэтому, когда я компилирую проект, компилятор пожаловался и остановился в строке выше и показал ошибку .источник
Если у вас есть интерфейс в вашем контроллере
Вы должны зарегистрировать их в контейнере внедрения зависимостей.
источник
У меня возникла эта ошибка, когда я случайно определил свойство как конкретный тип объекта вместо типа интерфейса, определенного в UnityContainer.
Например:
Определение UnityContainer:
SiteController (неправильный путь - обратите внимание на тип репо):
SiteController (правильный путь):
источник
Если вы используете UnityConfig.cs, чтобы сопротивляться сопоставлениям вашего типа, как показано ниже.
Вы должны сообщить
**webApiConfig.cs**
о контейнереисточник
В моем случае Unity оказалась отвлекающим маневром. Моя проблема возникла в результате того, что разные проекты были ориентированы на разные версии .NET. Unity был настроен правильно, и все было правильно зарегистрировано в контейнере. Все скомпилировано нормально. Но тип был в библиотеке классов, а библиотека классов была настроена на .NET Framework 4.0. Проект WebApi, использующий Unity, был настроен на .NET Framework 4.5. Изменение библиотеки классов на 4.5 также устранило проблему.
Я обнаружил это, закомментировав конструктор DI и добавив конструктор по умолчанию. Я закомментировал методы контроллера и заставил их выбросить NotImplementedException. Я подтвердил, что могу связаться с контроллером, и, увидев мое исключение NotImplementedException, сказал мне, что экземпляр контроллера работает нормально. Затем в конструкторе по умолчанию я вручную создал экземпляр цепочки зависимостей вместо того, чтобы полагаться на Unity. Он все еще скомпилирован, но когда я его запустил, сообщение об ошибке вернулось. Это подтвердило для меня, что я все еще получаю ошибку, даже когда Unity не используется. Наконец, я начал с нижней части цепочки и продвигался вверх, комментируя одну строку за раз и повторно тестируя, пока не перестану получать сообщение об ошибке. Это указывало мне на проблемный класс, и оттуда я понял, что он изолирован от одной сборки.
источник