Autofac - La portée de vie de la requête ne peut pas être créée car HttpContext n'est pas disponible - en raison du code asynchrone?
Petite Question: Même que ce problème sans réponse
Longue Question:
J'ai juste porté un peu de code d'un MVC 4 + Api Web solution qui a été à l'aide de Autofac dans ma nouvelle solution qui est également à l'aide de Autofac mais seulement avec l'Api Web 2 (pas de MVC 5.1 projet, juste une api web).
Dans ma solution précédente, j'ai eu MVC4 et Web Api, donc j'ai eu 2 programme d'Amorçage.cs fichiers, un pour chaque. J'ai copié sur le Web Api programme d'amorçage pour le nouveau projet.
Maintenant j'ai 2 autres projets de la nouvelle solution qui ont besoin de tirer une dépendance. Permet de considérer que je dois utiliser DependencyResolver.Current.GetService<T>()
malgré qu'il soit un anti-modèle.
Au début, ce n'était pas de travailler jusqu'à ce que j'ai mis le MVC Solveur de Dépendances pour le même conteneur:
GlobalConfiguration.Configuration.DependencyResolver =
new AutofacWebApiDependencyResolver(container);
//I had to pull in Autofac.Mvc and Mvc 5.1 integration but this line fixed it
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
La partie étrange est, le faire seul, il fixe dans l'UN de ces projets! Voici la situation:
Solution.Web project
Bootstrapper.cs that registers both dependency resolvers for web api and mvc.
Solution.ClassLib project
var userRepo = DependencyResolver.Current.GetService<IUserRepo>(); //Good! :)
Solution.WindowsWorkflow project
var userRepo = DependencyResolver.Current.GetService<IUserRepo>(); //Throws exception :(
L'exception est la suivante:
La demande durée de vie étendue ne peut pas être créé car le HttpContext n'est pas disponible.
Maintenant, avant de commencer à blâmer le flux de travail, il suffit de savoir j'ai eu exactement ce set up fonctionne très bien dans une autre solution, le flux de travail a été en mesure d'utiliser DependencyResolver l'amende juste. Je crois que cela a à voir avec l'aide d'une version plus récente de Autofac et le fait que le flux de travail s'exécute de façon asynchrone (tout comme la question que j'ai lié à concernant async code)
J'ai essayé de passer le code d'enregistrement à utiliser InstancePerLifetimeScope()
au lieu de InstancePerHttpRequest()
et essayer de créer un champ d'application:
using (var c= AutofacDependencyResolver.Current
.ApplicationContainer.BeginLifetimeScope("AutofacWebRequest"))
{
var userRepo = DependencyResolver.Current.GetServices<IUserRepo>();
}
Mais elle na pas changer l'exception. Briser le code de descendre encore plus bas voila exactement le coupable:
var adr = AutofacDependencyResolver.Current; //Throws that exception
Vraiment besoin pour obtenir passé ce passé trop de temps coincé. Récompense de réponse existant avec bounty en 2 jours
source d'informationauteur parliament
Vous devez vous connecter pour publier un commentaire.
Mise à JOUR Nov. 20, 2014: Dans les rejets de
Autofac.Mvc5
depuis que cette question a été libéré, la mise en œuvre deAutofacDependencyResolver.Current
a été mis à jour pour supprimer la nécessité d'uneHttpContext
. Si vous rencontrez ce problème et trouvé cette réponse, vous pouvez potentiellement résoudre facilement les choses par la mise à jour vers une version ultérieure deAutofac.Mvc5
. Cependant, je vais laisser l'original de la réplique intacte pour les gens de comprendre pourquoi la question de départ, le demandeur était d'avoir des problèmes.Original de la réplique suivante:
AutofacDependencyResolver.Current
implique unHttpContext
.Marche à travers le code,
AutofacDependencyResolver.Current
ressemble à ceci:Et, bien sûr, si la dépendance actuelle à l'égard de résolution est un
AutofacDependencyResolver
alors il va essayer de le faire d'une résolution...Qui obtient la durée de vie portée à partir d'un
RequestLifetimeScopeProvider
...Il a de travailler comme ça à l'appui des outils comme Aperçu dynamique wrap/proxy la résolution de dépendances afin d'instrument. C'est pourquoi vous ne pouvez pas les jeter
DependencyResolver.Current as AutofacDependencyResolver
.Peu près n'importe quoi à l'aide de la
Autofac.Integration.Mvc.AutofacDependencyResolver
nécessiteHttpContext
.C'est pourquoi vous continuez à recevoir ce message d'erreur. Il n'a pas d'importance si vous n'avez pas de dépendances qui sont enregistrés
InstancePerHttpRequest
-AutofacDependencyResolver
aura toujours besoin d'un contexte web.Je devine que l'autre application de flux de travail vous avez eu où ce n'était pas un problème a été d'une application MVC ou quelque chose où il y a toujours un contexte web.
Voici ce que je recommande:
Autofac.Integration.WebApi.AutofacWebApiDependencyResolver
.AutofacHostFactory.Container
et que l'hôte de l'usine de mise en œuvre pour résoudre les dépendances. (WCF est un peu bizarre avec ses singleton hôte potentiel, etc. donc, "par la demande" n'est pas tout à fait aussi simple.)CommonServiceLocator
mise en œuvre pour l'Autofac. Il ne crée pas la demande, la durée de vie, mais il peut résoudre certains problèmes.Si vous gardez ces choses et ne pas essayer d'utiliser les différents outils de résolution à l'extérieur de leurs habitats d'origine, comme c'était le cas, alors vous ne devriez pas rencontrer des problèmes.
Vous peut assez utiliser en toute sécurité
InstancePerApiRequest
etInstancePerHttpRequest
de façon interchangeable dans les inscriptions de service. Deux de ces extensions utilisent la même durée de vie étendue de la balise si la notion de web MVC demande et d'une API web demande peut être traitée de la même façon, même si le sous-jacent durée de vie étendue dans l'un des cas est basée surHttpContext
et l'autre est basé surIDependencyScope
. Donc, vous pourriez partager un module d'enregistrement dans les applications/application types et il doit faire la bonne chose.Si vous avez besoin de l'original de l'Autofac conteneur, magasin de votre propre référence. Plutôt que de supposer Autofac sera de retour que le conteneur en quelque sorte, vous pourriez avoir besoin de stocker une référence à votre conteneur de l'application si vous avez besoin pour obtenir plus tard pour quelque raison que ce soit.
Qui vous permettra d'économiser beaucoup d'ennuis sur la route.
Mes hypothèses:
IUserRepo
dépend de HttpContextSi mon hypothèse correcte, projet de Flux de travail n'a aucune idée sur
HttpContext.Current
.WindowsWorkflow projet fonctionne tout le temps (Si je comprends correctement, n'est pas réellement avec cette technologie). Où que MVC est basé sur les requêtes HTTP.
HttpContext.Current
est peuplé seulement quand il y a une demande. Si aucune demande n' - cette variable est null. Qu'advient-il si il n'y a pas de demande, mais l'instance de Flux de travail est en train d'essayer d'accéder àHttpContext
? Bon - référence nulle exception. Ou, dans votre cas, de la résolution des dépendances exception.Ce que vous devez faire:
User.Current
ouHttpContext.Current
. Et module Flux de travail (si nécessaire) avec tous les Flux de travail des implémentations spécifiques.IUserRepo
créer de mise en œuvre qui ne dépend pas de HttpContext. C'est probablement ce qui va poser le plus de problèmes à faire.J'ai fait quelque chose de similaire pour Quartz.Net exécution dans Azure. Voir mon billet de blog à ce sujet: http://tech.trailmax.info/2013/07/quartz-net-in-azure-with-autofac-smoothness/. Ce post ne sera pas vous aider directement, mais explique mon raisonnement pour le partage de l'autofac modules.
Mise à jour que par commentaire: WebApi clarifie beaucoup de choses ici. WebApi demande de ne pas passer par la même canalisation que votre MVC demandes. Et WebApi les contrôleurs n'ont pas accès à HttpContext. Voir cette réponse.
Maintenant, selon ce que vous faites dans votre wepApi contrôleur, vous souhaiterez peut-être modifier la
IUserRepo
mise en œuvre pour être en mesure de travailler avec les deux MVC et WebApi.Nous sommes actuellement dans une situation où nous avons des tests qui souffrent de "disparus httpcontext' de la question, mais ne peut pas encore utiliser les excellentes recommandations ci-dessus en raison de version contraintes.
La façon dont nous avons résolu c'était de créer une "maquette" http contexte dans notre configuration de test:
voir: Maquette HttpContext.Courant de Test de la Méthode Init