Pourquoi la session est-elle nulle dans les constructeurs de contrôleurs? Vous pouvez y accéder à partir des méthodes Action. Vraisemblablement, étant donné que l'infrastructure de routage MVC est responsable de la création d'un contrôleur, elle n'a tout simplement pas (ré) instancié la session à ce stade.
Est-ce que quelqu'un sait si c'est par conception et, si oui, pourquoi?
[J'ai réussi à contourner le problème en utilisant un modèle de chargement paresseux.]
Andrei a raison - il est null car, lorsqu'il est exécuté sous le framework ASP.NET MVC, le HttpContext (et par conséquent le HttpContext.Session) n'est pas défini lorsque la classe du contrôleur est construite comme prévu, mais elle est définie ("injectée") ultérieurement. par la classe ControllerBuilder. Si vous souhaitez mieux comprendre le cycle de vie, vous pouvez soit extraire le framework ASP.NET MVC (le source est disponible), soit consulter: cette page
Si vous devez accéder à la session, une solution consiste à remplacer la méthode "OnActionExecuting" et à y accéder, car elle sera disponible à ce moment-là.
Cependant, comme le suggère Andrei, si votre code est dépendant de la session, il pourrait éventuellement être difficile d’écrire des tests unitaires. Par conséquent, vous pouvez envisager de placer la session dans une classe d’aide qui pourra ensuite être remplacée par une classe différente. version Web lors de l'exécution de tests unitaires, découplez donc votre contrôleur du Web.
En plus des autres réponses ici, alors que Controller.Session
n'est pas renseigné dans le constructeur, vous pouvez toujours accéder à la session via:
System.Web.HttpContext.Current.Session
avec la mise en garde standard que cela réduit potentiellement la testabilité de votre contrôleur.
La session est injectée plus tard dans le cycle de vie. Pourquoi avez-vous besoin de la session dans le constructeur? Si vous en avez besoin pour TDD, vous devez envelopper la session dans un objet modulable.
Vous pouvez remplacer la méthode Initialize pour définir votre session.
protected override void Initialize(RequestContext requestContext)
Si vous utilisez un conteneur IoC, essayez d'injecter et d'utiliser l'objet HttpSessionStateBase
au lieu de l'objet Session
:
private static Container defaultContainer()
{
return new Container(ioc =>
{
// session manager setup
ioc.For<HttpSessionStateBase>()
.Use(ctx => new HttpSessionStateWrapper(HttpContext.Current.Session));
});
}
Cette réponse pourrait être utile pour certaines personnes
Si nous substituons la méthode Initialize, nous devons initialiser la classe de base avec le contexte de la requête: base.Initialize (requestContext);
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
if (web == null && Session != null && Session["APPLIANCE_URL"] != null)
{
web = new WebServices((String)Session["APPLIANCE_URL"]);
}
}