J'ai suivi ce tutoriel qui a très 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 résoudre ce problème. Existe-t-il un moyen simple de le forcer à saisir le constructeur sans paramètre ou j'aborde cela de manière incorrecte?
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:
System.InvalidOperationException: une erreur s'est produite lors de la tentative de création d'un contrôleur de type «SiteController». Assurez-vous que le contrôleur a un constructeur public sans paramètre.
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: le type «Dashboard.Web.Controllers.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 didacticiel était génial et a bien fonctionné pour moi jusqu'à ce que j'ajoute le deuxième constructeur.
la source
SiteController
c'est ce qui doit avoir un constructeur sans paramètre, nonDashboardDbContext
.SiteController
?DbContext
dans le référentiel?Réponses:
Ce qui se passe, c'est que vous êtes mordu par ce problème . Fondamentalement, ce qui s'est passé, c'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 comme il ne peut pas le résoudre (causé par une erreur dans votre configuration), il renvoie null. Il est forcé de renvoyer null, car l'API Web l'oblige à le faire en raison du
IDependencyResolver
contrat. Puisque Unity renvoie null, l'API Web essaiera de créer le contrôleur lui-même, mais comme elle n'a pas de constructeur par défaut, elle lèvera l'exception «Assurez-vous que le contrôleur a un constructeur public sans paramètre». 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 contrôleurs explicitement, et c'est pourquoi vous devriez toujours enregistrer tous les types de racine explicitement.
Mais bien sûr, l'erreur de configuration vient de l'ajout du deuxième constructeur à votre
DbContext
. Unity essaie toujours de choisir le constructeur avec le plus d'arguments, mais il n'a aucune idée de comment résoudre ce constructeur particulier.La vraie cause est donc que vous essayez d'utiliser les capacités de câblage automatique d'Unity pour créer le fichier
DbContext
.DbContext
est un type spécial qui ne devrait pas être câblé automatiquement. C'est un type de framework et vous devriez donc revenir à son enregistrement à l'aide d'un délégué d'usine :la source
IDependencyResolver
mais utilisez uniquement une coutume à laIControllerActivator
place.Dans mon cas, c'était à cause d'une exception à l'intérieur du constructeur de ma dépendance injectée (dans votre exemple - à l'intérieur du constructeur DashboardRepository). L'exception a été interceptée quelque part dans l'infrastructure MVC. J'ai trouvé cela après avoir ajouté des journaux aux endroits pertinents.
la source
Make sure that the controller has a parameterless public constructor.
mais il est fort possible que la dépendance soit configurée mais une exception profondément dans les entrailles a empêché sa résolution.J'ai eu le même problème et je l'ai résolu en apportant des modifications dans le fichier UnityConfig.cs Afin de résoudre le problème de dépendance dans le fichier UnityConfig.cs, vous devez ajouter:
la source
Parfois, parce que vous résolvez votre interface dans ContainerBootstraper.cs, il est très difficile d'attraper l'erreur. Dans mon cas, une erreur s'est produite lors de la résolution de l'implémentation de l'interface que j'ai injectée dans le contrôleur api. Je n'ai pas pu trouver l'erreur car j'ai résolu l'interface dans mon bootstraperContainer comme ceci:
container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
alors j'ai ajouté la ligne suivante dans mon conteneur d'amorçage:
container.RegisterType<MyController>();
donc quand je compile le projet, le compilateur s'est plaint et s'est arrêté dans la ligne ci-dessus et a montré l'erreur .la source
J'ai eu le même problème. Je l'ai googlé 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
public
mot clé derrière le constructeur du contrôleur.J'ajoute cette expérience comme une autre réponse, peut-être que quelqu'un d'autre a fait une erreur similaire.
la source
Si vous avez une interface dans votre contrôleur
Vous devez les enregistrer dans le conteneur d'injection de dépendances.
la source
J'ai cette erreur lorsque j'ai accidentellement défini une propriété comme un type d'objet spécifique, au lieu du type d'interface que j'ai défini dans UnityContainer.
Par exemple:
Définition de UnityContainer:
SiteController (dans le mauvais sens - notez le type de dépôt):
SiteController (la bonne façon):
la source
Si vous utilisez UnityConfig.cs pour résister aux mappages de votre type comme ci-dessous.
Vous devez informer
**webApiConfig.cs**
Containerla source
Dans mon cas, Unity s'est avéré être un hareng rouge. Mon problème était le résultat de différents projets ciblant différentes versions de .NET. Unity a été configuré correctement et tout a été correctement enregistré avec le conteneur. Tout s'est bien compilé. Mais le type se trouvait dans une bibliothèque de classes et la bibliothèque de classes a été définie pour cibler .NET Framework 4.0. Le projet WebApi utilisant Unity a été défini pour cibler .NET Framework 4.5. Changer la bibliothèque de classes pour cibler également 4.5 a résolu le problème pour moi.
J'ai découvert cela en commentant le constructeur DI et en ajoutant un constructeur par défaut. J'ai commenté les méthodes du contrôleur et leur ai demandé de lancer NotImplementedException. J'ai confirmé que je pouvais atteindre le contrôleur, et voir mon NotImplementedException m'a dit qu'il instanciait correctement le contrôleur. Ensuite, dans le constructeur par défaut, j'ai instancié manuellement la chaîne de dépendances au lieu de compter sur Unity. Il était toujours compilé, mais quand je l'ai exécuté, le message d'erreur est revenu. Cela m'a confirmé que j'avais toujours l'erreur même lorsque Unity était hors de l'image. Enfin, j'ai commencé au bas de la chaîne et j'ai progressé en commentant une ligne à la fois et en retestant jusqu'à ce que je ne reçoive plus le message d'erreur. Cela m'a orienté dans la direction de la classe incriminée, et à partir de là, j'ai compris qu'elle était isolée à une seule assemblée.
la source