Zorg ervoor dat de controller een parameterloze openbare constructorfout heeft

Ik heb deze zelfstudiegevolgd die werkte prima, totdat ik mijn DbContextaanpaste om een ​​extra constructor te hebben. Ik heb nu problemen met de resolutie en weet niet zeker wat ik moet doen om dit op te lossen. Is er een gemakkelijke manier om het te forceren om de parameterloze constructor te pakken of benader ik dit verkeerd?

DbContextmet twee constructors:

public class DashboardDbContext : DbContext
{
    public DashboardDbContext() : base("DefaultConnection") { }
    public DashboardDbContext(DbConnection dbConnection, bool owns)
        : base(dbConnection, owns) { }
}

SiteController-constructor:

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);

Fout van WebApi-oproep:

System.InvalidOperationException: er is een fout opgetreden bij het maken van een controller van het type ‘SiteController’. Zorg ervoor dat de controller een parameterloze openbare constructor heeft.

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’ heeft geen standaardconstructor.

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)

De tutorial was geweldig en werkte goed voor mij totdat ik de tweede constructor toevoegde.


Antwoord 1, autoriteit 100%

Wat er gebeurt, is dat je wordt gebeten door dit probleem. Wat er in feite is gebeurd, is dat u uw controllers niet expliciet in uw container hebt geregistreerd. Unity probeert niet-geregistreerde betontypen voor u op te lossen, maar omdat het dit niet kan oplossen (veroorzaakt door een fout in uw configuratie), retourneert het null. Het wordt gedwongen null terug te geven, omdat Web API het dwingt dit te doen vanwege het IDependencyResolver-contract. Aangezien Unity null retourneert, zal Web API proberen de controller zelf te maken, maar aangezien deze geen standaardconstructor heeft, wordt de uitzondering “Zorg ervoor dat de controller een parameterloze openbare constructor heeft” gegenereerd. Dit uitzonderingsbericht is misleidend en geeft geen verklaring voor de echte oorzaak.

Je zou een veel duidelijker uitzonderingsbericht hebben gezien als je je controllers expliciet had geregistreerd, en daarom zou je altijd alle root-types expliciet moeten registreren.

Maar de configuratiefout komt natuurlijk van het toevoegen van de tweede constructor aan uw DbContext. Unity probeert altijd de constructor met de meeste argumenten te kiezen, maar heeft geen idee hoe deze specifieke constructor moet worden opgelost.

Dus de echte oorzaak is dat je de auto-wiring-mogelijkheden van Unity probeert te gebruiken om de DbContextte maken. DbContextis een speciaal type dat niet automatisch bedraad mag worden. Het is een raamwerktype en u moet daarom terugvallen op het registreren met een fabrieksafgevaardigde:

container.Register<DashboardDbContext>(
    new InjectionFactory(c => new DashboardDbContext())); 

Antwoord 2, autoriteit 37%

In mijn geval was het vanwege een uitzondering in de constructor van mijn geïnjecteerde afhankelijkheid (in jouw voorbeeld – in de DashboardRepository-constructor). De uitzondering zat ergens in de MVC-infrastructuur. Ik vond dit nadat ik logs op relevante plaatsen had toegevoegd.


Antwoord 3, autoriteit 5%

Ik had hetzelfde probleem en ik heb het opgelost door wijzigingen aan te brengen in het bestand UnityConfig.cs. Om het afhankelijkheidsprobleem in het bestand UnityConfig.cs op te lossen, moet u het volgende toevoegen:

public static void RegisterComponents()    
{
    var container = new UnityContainer();
    container.RegisterType<ITestService, TestService>();
    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}

Antwoord 4, autoriteit 4%

Ik had hetzelfde probleem. Ik heb er twee dagen op gegoogled. Eindelijk merkte ik per ongeluk dat het probleem de toegangsmodifier van de constructor van de controller was.
Ik heb het sleutelwoord publicniet achter de constructor van de controller geplaatst.

public class MyController : ApiController
    {
        private readonly IMyClass _myClass;
        public MyController(IMyClass myClass)
        {
            _myClass = myClass;
        }
    }

Ik voeg deze ervaring toe als een ander antwoord, misschien heeft iemand anders een soortgelijke fout gemaakt.


Antwoord 5, autoriteit 3%

Soms, omdat u uw interface in ContainerBootstraper.cs oplost, is het erg moeilijk om de fout op te sporen. In mijn geval was er een fout bij het oplossen van de implementatie van de interface die ik in de api-controller heb geïnjecteerd. Ik kon de fout niet vinden omdat ik de interface in mijn bootstraperContainer als volgt heb opgelost:
container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
dan heb ik de volgende regel in mijn bootstrap-container toegevoegd: container.RegisterType<MyController>();
dus toen ik het project compileerde, klaagde de compiler en stopte in de bovenstaande regel en toonde de fout.


Antwoord 6

Als u UnityConfig.csgebruikt om de toewijzingen van uw type te weerstaan, zoals hieronder.

public static void RegisterTypes(IUnityContainer container)
    {
     container.RegisterType<IProductRepository, ProductRepository>();
    }

U moet **webApiConfig.cs**over Container informeren

config.DependencyResolver = new Unity.AspNet.WebApi.UnityDependencyResolver(UnityConfig.Container);

Antwoord 7

Als je een interface in je controller hebt

public myController(IXInterface Xinstance){}

U moet ze registreren in de Dependency Injection-container.

container.Bind<IXInterface>().To<XClass>().InRequestScope();

Antwoord 8

Ik krijg deze fout wanneer ik per ongeluk een eigenschap heb gedefinieerd als een specifiek objecttype, in plaats van het interfacetype dat ik heb gedefinieerd in UnityContainer.

Bijvoorbeeld:

EenheidContainer definiëren:

var container = new UnityContainer();
container.RegisterInstance(typeof(IDashboardRepository), DashboardRepository);
config.DependencyResolver = new UnityResolver(container);

SiteController (op de verkeerde manier – let op repo-type):

private readonly DashboardRepository _repo;
public SiteController(DashboardRepository repo)
{
    _repo = repo;
}

SiteController (op de juiste manier):

private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
    _repo = repo;
}

Antwoord 9

In mijn geval bleek Unity een rode haring te zijn. Mijn probleem was het resultaat van verschillende projecten die gericht waren op verschillende versies van .NET. Unity was goed ingesteld en alles was correct geregistreerd bij de container. Alles prima gecompileerd. Maar het type bevond zich in een klassenbibliotheek en de klassenbibliotheek was ingesteld op .NET Framework 4.0. Het WebApi-project dat Unity gebruikt, is ingesteld op .NET Framework 4.5. Het veranderen van de klassenbibliotheek om ook 4.5 te targeten loste het probleem voor mij op.

Ik ontdekte dit door commentaar te geven op de DI-constructor en de standaardconstructor toe te voegen. Ik becommentarieerde de controllermethoden en liet ze NotImplementedException gooien. Ik bevestigde dat ik de controller kon bereiken en toen ik mijn NotImplementedException zag, vertelde ik me dat het de controller-boete aan het instantiëren was. Vervolgens heb ik in de standaardconstructor de afhankelijkheidsketen handmatig geïnstantieerd in plaats van te vertrouwen op Unity. Het compileerde nog steeds, maar toen ik het uitvoerde, kwam de foutmelding terug. Dit bevestigde voor mij dat ik nog steeds de fout kreeg, zelfs toen Unity uit beeld was. Ten slotte begon ik onderaan de keten en werkte ik me omhoog, waarbij ik regel voor regel commentaar gaf en opnieuw testte totdat ik de foutmelding niet meer kreeg. Dit wees me in de richting van de overtredende klas, en van daaruit kwam ik erachter dat het geïsoleerd was tot een enkele vergadering.

Other episodes