Ich habe dieses Tutorial befolgt, das großartig funktioniert hat, bis ich mein geändert habe DbContext
, um einen zusätzlichen Konstruktor zu haben. Ich habe jetzt Probleme mit der Lösung und bin mir nicht sicher, was ich tun soll, um dies zu beheben. Gibt es eine einfache Möglichkeit, es zu zwingen, den parameterlosen Konstruktor zu greifen, oder gehe ich dies falsch an?
DbContext
mit zwei Konstruktoren:
public class DashboardDbContext : DbContext
{
public DashboardDbContext() : base("DefaultConnection") { }
public DashboardDbContext(DbConnection dbConnection, bool owns)
: base(dbConnection, owns) { }
}
SiteController
Konstrukteur:
private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
_repo = repo;
}
Repository:
DashboardDbContext _context;
public DashboardRepository(DashboardDbContext context)
{
_context = context;
}
UnityResolver
Code:
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);
Fehler beim WebApi-Aufruf:
System.InvalidOperationException: Beim Versuch, einen Controller vom Typ 'SiteController' zu erstellen, ist ein Fehler aufgetreten. Stellen Sie sicher, dass der Controller über einen parameterlosen öffentlichen Konstruktor verfügt.
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: Typ 'Dashboard.Web.Controllers.SiteController' hat keinen Standardkonstruktor.
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)
Das Tutorial war großartig und hat für mich gut funktioniert, bis ich den zweiten Konstruktor hinzugefügt habe.
quelle
SiteController
dies ein paramertloser Konstruktor sein muss, nichtDashboardDbContext
.SiteController
?DbContext
in das Repository?Antworten:
Was passiert ist, dass Sie von diesem Problem gebissen werden . Grundsätzlich haben Sie Ihre Controller nicht explizit in Ihrem Container registriert. Unity versucht, nicht registrierte konkrete Typen für Sie aufzulösen. Da es jedoch nicht aufgelöst werden kann (verursacht durch einen Fehler in Ihrer Konfiguration), wird null zurückgegeben. Es ist gezwungen, null zurückzugeben, da die Web-API dies aufgrund des
IDependencyResolver
Vertrags dazu zwingt . Da Unity null zurückgibt, versucht die Web-API, den Controller selbst zu erstellen. Da sie jedoch keinen Standardkonstruktor hat, wird die Ausnahme "Stellen Sie sicher, dass der Controller einen parameterlosen öffentlichen Konstruktor hat" ausgelöst. Diese Ausnahmemeldung ist irreführend und erklärt nicht die wahre Ursache.Sie hätten eine viel klarere Ausnahmemeldung gesehen, wenn Sie Ihre Controller explizit registriert hätten. Deshalb sollten Sie immer alle Root-Typen explizit registrieren.
Aber natürlich kommt der Konfigurationsfehler von Ihnen, wenn Sie den zweiten Konstruktor zu Ihrem hinzufügen
DbContext
. Unity versucht immer, den Konstruktor mit den meisten Argumenten auszuwählen, hat jedoch keine Ahnung, wie dieser bestimmte Konstruktor aufgelöst werden soll.Die eigentliche Ursache ist also, dass Sie versuchen, die automatischen Verkabelungsfunktionen von Unity zu verwenden, um das zu erstellen
DbContext
.DbContext
ist ein spezieller Typ, der nicht automatisch verkabelt werden sollte. Es handelt sich um einen Framework-Typ, und Sie sollten daher auf die Registrierung mithilfe eines Factory-Delegaten zurückgreifen :quelle
IDependencyResolver
sondern nur eine benutzerdefinierteIControllerActivator
.In meinem Fall lag dies an einer Ausnahme innerhalb des Konstruktors meiner injizierten Abhängigkeit (in Ihrem Beispiel - innerhalb des DashboardRepository-Konstruktors). Die Ausnahme wurde irgendwo in der MVC-Infrastruktur festgestellt. Ich habe dies gefunden, nachdem ich Protokolle an relevanten Stellen hinzugefügt habe.
quelle
Make sure that the controller has a parameterless public constructor.
aber es ist durchaus möglich, dass die Abhängigkeit eingerichtet ist, aber eine Ausnahme tief im Darm hat die Lösung verhindert.Ich hatte das gleiche Problem und habe es behoben, indem ich Änderungen an der Datei UnityConfig.cs vorgenommen habe. Um das Abhängigkeitsproblem in der Datei UnityConfig.cs zu beheben, müssen Sie Folgendes hinzufügen:
quelle
Manchmal ist es sehr schwierig, den Fehler zu erkennen, da Sie Ihre Schnittstelle in ContainerBootstraper.cs auflösen. In meinem Fall ist ein Fehler beim Auflösen der Implementierung der Schnittstelle aufgetreten, die ich dem API-Controller injiziert habe. Ich konnte den Fehler nicht finden, weil ich die Schnittstelle in meinem bootstraperContainer
container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
folgendermaßen aufgelöst habe : Dann habe ich die folgende Zeile in meinen Bootstrap-Container eingefügt:
container.RegisterType<MyController>();
Als ich das Projekt kompilierte, beschwerte sich der Compiler und stoppte in der obigen Zeile und zeigte den Fehler an .quelle
Ich hatte das gleiche Problem. Ich habe es zwei Tage lang gegoogelt. Endlich habe ich versehentlich bemerkt, dass das Problem der Zugriffsmodifikator des Konstruktors des Controllers war. Ich habe das
public
Schlüsselwort nicht hinter den Konstruktor des Controllers gestellt.Ich füge diese Erfahrung als eine andere Antwort hinzu, vielleicht hat jemand anderes einen ähnlichen Fehler gemacht.
quelle
Wenn Sie eine Schnittstelle in Ihrem Controller haben
Sie müssen sie im Dependency Injection-Container registrieren.
quelle
Ich habe diesen Fehler erhalten, als ich versehentlich eine Eigenschaft als einen bestimmten Objekttyp anstelle des in UnityContainer definierten Schnittstellentyps definiert habe.
Beispielsweise:
UnityContainer definieren:
SiteController (der falsche Weg - Repo-Typ beachten):
SiteController (der richtige Weg):
quelle
Wenn Sie UnityConfig.cs verwenden, um die Zuordnungen Ihres Typs wie unten beschrieben zu speichern .
Sie müssen das
**webApiConfig.cs**
über Container informierenquelle
In meinem Fall stellte sich Unity als roter Hering heraus. Mein Problem war das Ergebnis verschiedener Projekte, die auf verschiedene Versionen von .NET abzielten. Unity wurde richtig eingerichtet und alles wurde korrekt mit dem Container registriert. Alles gut zusammengestellt. Der Typ befand sich jedoch in einer Klassenbibliothek, und die Klassenbibliothek wurde auf .NET Framework 4.0 ausgerichtet. Das WebApi-Projekt mit Unity wurde als Ziel für .NET Framework 4.5 festgelegt. Das Ändern der Klassenbibliothek auf Ziel 4.5 hat das Problem für mich behoben.
Ich habe dies entdeckt, indem ich den DI-Konstruktor auskommentiert und einen Standardkonstruktor hinzugefügt habe. Ich habe die Controller-Methoden auskommentiert und sie NotImplementedException auslösen lassen. Ich bestätigte, dass ich den Controller erreichen konnte, und als ich meine NotImplementedException sah, wurde mir mitgeteilt, dass der Controller in Ordnung ist. Als Nächstes habe ich im Standardkonstruktor die Abhängigkeitskette manuell instanziiert, anstatt mich auf Unity zu verlassen. Es wurde immer noch kompiliert, aber als ich es ausführte, kam die Fehlermeldung zurück. Dies bestätigte für mich, dass ich den Fehler auch dann noch bekam, wenn Unity nicht im Bilde war. Schließlich begann ich am Ende der Kette und arbeitete mich nach oben, kommentierte jeweils eine Zeile aus und testete erneut, bis ich die Fehlermeldung nicht mehr erhielt. Dies wies mich in die Richtung der beleidigenden Klasse und von dort stellte ich fest, dass es zu einer einzigen Versammlung isoliert war.
quelle