L'unité du Cio n'a pas d'injection de dépendance dans l'API Web de Contrôleur
Je suis très nouveau à l'aide de l'Unité, mais mon problème est qu'à chaque fois que j'appelle mon service web, j'obtiens une exception indiquant que
"Assurez-vous que le contrôleur a un sans paramètre constructeur public"
J'ai suivi plusieurs tutoriels et je reçois toujours le même problème.
Dans le Registre de la fonction de mon WebApiConfig classe, j'ai
var container = new UnityContainer();
container.RegisterType<IValidator, Validator>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
Voici mon UnityResolver classe
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.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();
}
}
Je n'ai pas enregistré des contrôleurs, comme chaque tutoriel prétend que je n'ai pas besoin de le faire. Voici mon contrôleur
public class Controller: ApiController
{
private IValidator _validator;
public Controller(IValidator validator)
{
this._validator = validator;
}
[HttpPost]
public void ReceiveIPN()
{
}
}
Quelqu'un a une idée de ce que j'ai peut être fait une erreur? Merci!
EDIT 1: c'est la "mise en œuvre" de la classe Validator. C'est assez vide, parce que je ne voulais pas introduire un bug ici jusqu'à ce que j'ai résolu la question de l'Unité.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public class Validator: IValidator
{
public bool ValidateIPN(string body)
{
throw new NotImplementedException();
}
}
EDIT 2: Voici l'intégralité de la réponse d'erreur que j'obtiens lorsque je tente d'appeler l'api web de l'itinéraire à l'aide de Fiddler
{"message":"Une erreur s'est produite.","exceptionMessage":"Une erreur
s'est produite lors de la tentative de créer un contrôleur de type "Contrôleur". Faire
assurez-vous que le contrôleur a un sans paramètre public
constructeur.","exceptionType":"le Système de.InvalidOperationException","stackTrace":"
au
Système.Web.Http.Répartiteur.DefaultHttpControllerActivator.Créer(HttpRequestMessage
demande, HttpControllerDescriptor controllerDescriptor, Type
controllerType) à
Système.Web.Http.Les contrôleurs.HttpControllerDescriptor.CreateController(HttpRequestMessage
demande)
Système.Web.Http.Répartiteur.HttpControllerDispatcher.d__1.MoveNext()","innerException":{"message":"Un
erreur s'est produite.","exceptionMessage":"Type de Projet".Contrôleur'
par défaut n'
constructeur","exceptionType":"le Système de.ArgumentException","stackTrace":"
au Système.Linq.Les Expressions.De l'Expression.Nouvelle(Type) à
Système.Web.Http.Interne.TypeActivator.Créer[TBase](Type
type d'instance) à
Système.Web.Http.Répartiteur.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage
demande de, Type controllerType, Func`1& activator) à
Système.Web.Http.Répartiteur.DefaultHttpControllerActivator.Créer(HttpRequestMessage
demande, HttpControllerDescriptor controllerDescriptor, Type
controllerType)"}}
- Vous devez vous inscrire votre contrôleur avec l'Unité dont je ne vois pas que tu fais. Si vous faites cela, ou si cela ne fonctionne toujours pas, le total de deviner, mais essayez de donner un nom à votre contrôleur de quelque chose d'autre que contrôleur. Parfois, la réflexion sur un nom de classe qui partage le même nom que quelque chose dans le cadre a de bizarre effets secondaires.
- les contrôleurs n'ont pas à être enregistrés. \@Amis: pouvez-vous montrer comment votre programme de validation ressemble? Est-il aussi prendre en une dépendance?
- Je ne suis pas l'enregistrement du contrôleur et le contrôleur n'est pas en fait le nom du Contrôleur. J'ai changé le nom avant de poster ici. @JeroenVannevel je peux poster le Validateur, mais c'est en fait vide lol. Je n'ai pas définir un constructeur explicite sur elle, et n'a qu'une seule méthode qui jette un pas en œuvre d'exception. J'ai assez bien arrêtée à ce point
- Fonctionne lorsque vous retirez la dépendance dans le constructeur du contrôleur?
- Oui, c'est fait
- Alors le problème doit être situé dans le validateur. Vous pouvez poster à la mise en œuvre du programme de validation?
- Ah droite.
- J'ai ajouté le validateur "mise en œuvre". C'est assez vide cependant. Merci de prendre le temps
- J'ai regardé la plupart des choses je pense que, généralement, la cause de cela. Pouvez-vous partager l'exacte stacktrace? Peut-être que contient aucune indication.
- J'ai mis à jour la question de la trace.
- L'erreur semble être clair. Assurez-vous que votre contrôleur de classe a d'une valeur par défaut (sans paramètre) constructeur. Essayer cela et voir ce qui se passe.
- Bien que cela fonctionne, il ne résout pas mon problème. Si j'ajoute un constructeur sans paramètre, c'est le constructeur qui finit par être utilisés, et mon programme de validation de la dépendance n'est pas injecté dans mon Contrôleur. Le point de l'ensemble de mon utilisation de l'Unité est d'être en mesure d'injecter de mes dépendances, pour l'unité des fins de test.
- selon cette réponse vous pouvez obtenir une vue plus détaillée de message d'exception si vous explicitement enregistrer vos contrôleurs. Si cela ne donne rien si, jetez votre solution dans un fichier zip et de le télécharger quelque part afin que je puisse prendre un coup d'oeil autour localement (ou le mettre sur github).
- Désolé, j'ai complètement mal lu votre question et vous avez entièrement raison. Mon mauvais. Basé sur ce modèle codeproject.com/Articles/797132/... vous pouvez avoir besoin de faire cela dans un personnalisé
DefaultControllerFactory
mais je ne peux pas dire à coup sûr. Encore une fois, toutes mes excuses pour ne pas comprendre la question correctement. - Avez-vous assurez-vous que votre
WebApiConfig.Register
méthode est invoquée? - Il ne ressemble pas explicitement l'enregistrement de mon contrôleur changé le message d'exception. Aussi, j'ai vraiment ne peut pas partager l'ensemble du projet pour des raisons juridiques, autant que j'aimerais (pour obtenir ce compris lol). Désolé à ce sujet, et je vous remercie de toute l'aide que vous m'avez donnée jusqu'à présent.
- Pas de soucis :-). J'ai regardé dans le DefaultControllerFactory, mais il semble que ce n'est pas l'approche idéale (au moins, pas plus). Si je ne peux pas comprendre la DependencyResolver approche, je vais certainement regarder à cela.
- Oui je l'ai fait. J'ai mis un point de rupture, et il est toujours touché quand j'ai lancer le projet et de l'appel du service web.
- Peut-être un coup de feu dans l'obscurité, mais essayez de changer votre nom de contrôleur de
Controller
à quelque chose commeMyController
. - Je vous suggère de créer un exemple minimal qui reproduit le problème. Si vous pouvez faire cela, alors vous pouvez le partager avec nous, si vous ne pouvez pas faire cela, alors vous pouvez construire progressivement votre projet et vous remarquerez que finalement, là où les choses se décomposer.
- J'ai changé le nom du contrôleur de nombreuses fois et il ne semble pas être la question. Merci bien 🙂
- Va faire. Je vais poster dès que j'ai d'autres indices. Merci encore.
- Se pourrait-il que
RegisterType<IValidator, Validator>
se référant àSystem.Web.WebPages.IValidator
? OuValidator
se référant àSystem.Web.WebPages.Validator
? Ou les deux? - ce n'est pas en passant à la ctor, il pose seulement la durée de vie.
- Question stupide, mais êtes-vous sûr que vous appelez votre
WebApiConfig.Register
méthode de Global.asax? - J'ai réussi à comprendre ce qui se passait et a posté la solution comme une réponse. Merci pour l'aide
Vous devez vous connecter pour publier un commentaire.
Donc, après des heures de cogner ma tête contre un mur, j'ai trouvé que ce n'était pas de travail parce que j'avais un OWIN/Katana de Démarrage.cs de la classe dans mon projet. Maintenant, je ne sais pas exactement ce qui se passe ici, pour plus d'information serait génial.
En gros, depuis que j'ai été en utilisant OWIN/Katana, j'ai eu un Démarrage.cs fichier créé un nouveau HttpConfiguration objet et configuré, semblable à la façon dont c'est fait dans le WebApiConfig.cs de la classe.
Il semble que le code qui s'exécute en premier par le biais de la WebApiConfig Registre de la fonction, PUIS remplace que HttpConfiguration objet à celui généré dans le Démarrage.cs fichier. J'ai dû passer mon conteneur de configuration des trucs ici dans l'ordre pour que cela fonctionne.
Désolé que je n'ai pas le OWIN trucs avant. C'est assez nouveau pour moi et je ne savais pas que c'était pertinent. J'espère que cela sauve quelqu'un d'autre que la douleur que je viens de vivre.
public static void Register(HttpConfiguration config) { var container = new UnityContainer(); // replace... /* GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); */ // with this: config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); }
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); System.Web.Mvc.DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
Votre Unité de conteneur est probablement éliminés parce que c'est seulement défini dans le cadre de votre
WebApiConfig.Register()
méthode. Si vous définissez votre conteneur en tant que membre de la Global, qui maintiendra votre conteneur autour de la durée de vie de l'application, il devrait fonctionner.Edit: aussi n'oubliez pas de jeter le récipient sur Application_End.
Exemple:
Je sais que c'est un vieux post, mais depuis que je viens de tomber sur le même problème, la solution était tout simplement de passer de l'objet de configuration de l'Unité d'enregistrement de la fonction et de l'utilisation de la DependencyResolver à partir de cette instance:
EDIT: Juste de noter que l'on a accepté la réponse est exactement cela... Désolé pour le spam 😉