Assurez-vous que le contrôleur a une erreur de constructeur public sans paramètres

j'ai suivi ce tutorial qui a bien fonctionné, jusqu'à ce que je modifie mon DbContext pour avoir un constructeur supplémentaire. J'ai maintenant des problèmes avec la résolution et je ne sais pas quoi faire pour y remédier. Y a-t-il un moyen facile de le forcer à saisir le constructeur parameterless ou je m'y prends mal?

DbContext avec deux constructeurs:

public class DashboardDbContext : DbContext
{
    public DashboardDbContext() : base("DefaultConnection") { }

    public DashboardDbContext(DbConnection dbConnection, bool owns)
        : base(dbConnection, owns) { }
}

SiteController constructeur:

private readonly IDashboardRepository _repo;

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

dépôt:

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

erreur de L'appel WebApi:

système.InvalidOperationException: une erreur s'est produite lors de la création d'un contrôleur de type 'SiteController'. Assurez-vous que le contrôleur dispose d'un constructeur public sans paramètres.

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 De Tableau De Bord.Web.Contrôleur.SiteController " n'a pas de constructeur par défaut.

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)

le tutoriel était génial et a bien fonctionné pour moi jusqu'à ce que j'ajoute le deuxième constructeur.

82
demandé sur Steven 2014-06-17 04:41:21

5 réponses

ce qui se passe, c'est que vous êtes mordu par ce problème . Fondamentalement, ce qui s'est passé est que vous n'avez pas enregistré vos contrôleurs explicitement dans votre conteneur. Unity essaie de résoudre les types concrets non enregistrés pour vous, mais parce qu'il ne peut pas le résoudre (causé par une erreur dans votre configuration), il retourne null. Il est forcé de retourner null, parce que L'API Web le force à le faire en raison du contrat IDependencyResolver . Puisque Unity renvoie null, L'API Web va essayer de créer le controller lui-même, mais comme il n'a pas de constructeur par défaut, il lancera l'exception "assurez-vous que le controller a un constructeur public sans paramètres". Ce message d'exception est trompeur et n'explique pas la vraie cause.

vous auriez vu un message d'exception beaucoup plus clair si vous aviez enregistré vos controllers explicitement, et c'est pourquoi vous devriez toujours enregistrer tous les types de racine explicitement.

mais bien sûr, le l'erreur de configuration provient de l'ajout du second constructeur à votre DbContext . L'unité essaie toujours de choisir le constructeur avec la plupart des arguments, mais il n'a aucune idée de comment résoudre ce constructeur.

donc la vraie cause est que vous essayez d'utiliser les capacités d'auto-câblage de Unity pour créer le DbContext . DbContext est un type spécial qui ne devrait pas être auto-câblé. Il s'agit d'un type de cadre et vous devriez donc retomber à l'enregistrer en utilisant un délégué d'usine :

container.Register<DashboardDbContext>(
    new InjectionFactory(c => new DashboardDbContext())); 
103
répondu Steven 2014-08-11 11:30:36

dans mon cas, c'était à cause de l'exception à l'intérieur du constructeur de ma dépendance injectée (dans votre exemple - dans dashboardrepository constructor). L'exception a été prise quelque part dans L'infrastructure de MVC. J'ai trouvé ça après avoir ajouté des logs dans des endroits pertinents.

35
répondu Illidan 2015-08-25 03:56:49

j'ai eu le même problème et je l'ai résolu en faisant des changements dans L'UnityConfig.fichier cs afin de résoudre le problème de dépendance dans UnityConfig.vous devez ajouter:

public static void RegisterComponents()    
{
    var container = new UnityContainer();
    container.RegisterType<ITestService, TestService>();
    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
5
répondu user1407955 2017-08-26 19:31:55

parfois parce que vous résolvez votre interface dans ContainerBootstraper.cs c'est très difficile de rattraper l'erreur. Dans mon cas, il y avait une erreur dans la résolution de l'implémentation de l'interface que j'ai injecté au contrôleur api. Je n'ai pas pu trouver l'erreur parce que j'ai résolu l'interface dans mon bootstraperContainer comme ceci: container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());

puis j'ai ajouté la ligne suivante dans mon bootstrap container: container.RegisterType<MyController>(); donc quand je compilerai le projet , le compilateur se plaint et s'arrêta au-dessus de la ligne et a montré l'erreur.

4
répondu Amir978 2016-06-03 04:59:13

j'ai eu le même problème. J'ai cherché sur Google pendant deux jours. Enfin, j'ai accidentellement remarqué que le problème était le modificateur d'accès du constructeur du Contrôleur. Je n'ai pas mis le mot clé public derrière le constructeur du contrôleur.

public class MyController : ApiController
    {
        private readonly IMyClass _myClass;

        public MyController(IMyClass myClass)
        {
            _myClass = myClass;
        }
    }

j'ajoute cette expérience comme une autre réponse peut-être quelqu'un d'autre a fait une telle erreur.

0
répondu Bobs 2018-05-05 10:34:23