Upewnij się, że kontroler ma parametrless public constructor error
Podążałem za tym tutorialem, który działał świetnie, dopóki nie zmodyfikowałem mojego DbContext
, aby mieć dodatkowy konstruktor. Mam teraz problemy z rezolucją i nie wiem, co zrobić, aby to naprawić. Czy jest łatwy sposób, aby zmusić go do złapania konstruktora bez parametru, czy podchodzę do tego niepoprawnie?
DbContext
z dwoma konstruktorami:
public class DashboardDbContext : DbContext
{
public DashboardDbContext() : base("DefaultConnection") { }
public DashboardDbContext(DbConnection dbConnection, bool owns)
: base(dbConnection, owns) { }
}
SiteController
konstruktor:
private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
_repo = repo;
}
Repozytorium:
DashboardDbContext _context;
public DashboardRepository(DashboardDbContext context)
{
_context = context;
}
UnityResolver
kod:
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);
Błąd wywołania WebApi:
System.InvalidOperationException: wystąpił błąd podczas próby utworzenia kontrolera typu "SiteController". Upewnij się, że kontroler ma bez parametru publiczny konstruktor.
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: Type ' Dashboard.Www.Kontrolery.SiteController ' nie posiada domyślnego konstruktora.
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)
Tutorial był świetnie i działa mi dobrze aż do momentu dodania drugiego konstruktora.
5 answers
Dzieje się tak, że jesteś ugryziony przez ten problem . Zasadniczo stało się tak, że nie zarejestrowałeś kontrolerów bezpośrednio w kontenerze. Unity próbuje rozwiązać niezarejestrowane konkretne typy dla ciebie, ale ponieważ nie może go rozwiązać (spowodowane błędem w konfiguracji), zwraca null. Jest on zmuszony do zwracania null, ponieważ Web API zmusza go do tego ze względu na kontrakt IDependencyResolver
. Ponieważ Unity zwraca null, Web API spróbuje stworzyć sam kontroler, ale ponieważ nie ma domyślnego konstruktora, rzuci on wyjątek "upewnij się, że kontroler ma parametrless public constructor". Ten Komunikat o wyjątku jest mylący i nie wyjaśnia prawdziwej przyczyny.
Zobaczyłbyś o wiele jaśniejszy komunikat o wyjątkach, gdybyś zarejestrował swoje Kontrolery jawnie i dlatego zawsze powinieneś jawnie zarejestrować wszystkie typy rootów.
Ale oczywiście błąd konfiguracji wynika z dodania drugiego konstruktora do Twój DbContext
. Unity zawsze próbuje wybrać konstruktor z największą liczbą argumentów, ale nie ma pojęcia, jak rozwiązać ten konkretny konstruktor.
Więc prawdziwą przyczyną jest to, że próbujesz wykorzystać możliwości automatycznego okablowania Unity do stworzenia DbContext
. DbContext
jest specjalnym typem, który nie powinien być automatycznie podłączony. Jest to typ frameworka i powinieneś , dlatego możesz go zarejestrować za pomocą delegata fabrycznego :
container.Register<DashboardDbContext>(
new InjectionFactory(c => new DashboardDbContext()));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-11 11:30:36
W moim przypadku było to spowodowane wyjątkiem wewnątrz konstruktora mojej iniekcyjnej zależności (w twoim przykładzie - wewnątrz konstruktora DashboardRepository). Wyjątek został złapany gdzieś wewnątrz infrastruktury MVC. Znalazłem to po dodaniu logów w odpowiednich miejscach.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-25 03:56:49
Miałem ten sam problem i rozwiązałem go, wprowadzając zmiany w UnityConfig.plik cs w celu rozwiązania problemu zależności w UnityConfig.plik cs musisz dodać:
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-26 19:31:55
Czasami, ponieważ rozwiązujesz swój interfejs w ContainerBootstraper.cs bardzo trudno złapać błąd. W moim przypadku wystąpił błąd w rozwiązaniu implementacji interfejsu, który wstrzyknąłem do kontrolera api. Nie mogłem znaleźć błędu, ponieważ rozwiązałem interfejs w moim bootstraperContainer w następujący sposób:
container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
następnie dodałem następujący wiersz w moim kontenerze bootstrap: container.RegisterType<MyController>();
więc kiedy kompiluję projekt , kompilator narzekał i zatrzymał się w powyżej linia i pokazał błąd.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-03 04:59:13
Miałem ten sam problem. Wygooglowałem to przez dwa dni. W końcu przypadkowo zauważyłem, że problemem był modyfikator dostępu konstruktora kontrolera.
Nie umieściłem public
słowa kluczowego za konstruktorem kontrolera.
public class MyController : ApiController
{
private readonly IMyClass _myClass;
public MyController(IMyClass myClass)
{
_myClass = myClass;
}
}
Dodaję to doświadczenie jako kolejną odpowiedź może ktoś inny popełnił podobny błąd.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-05 10:34:23