Session null dans les constructeurs ASP.Net MVC Controller

Pourquoi la session est-elle nulle dans les constructeurs des contrôleurs? Il est possible d’y accéder à partir de méthodes d’action. Vraisemblablement, l’infrastructure de routage MVC étant responsable de la mise à jour d’un contrôleur, elle n’a tout simplement pas (re) instancié la session à ce moment.

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 nul car lorsqu’il est exécuté sous le framework ASP.NET MVC, le HttpContext (et donc le HttpContext.Session) n’est pas défini lorsque la classe du contrôleur est construite comme prévu, mais plus tard (“injecté”) par la classe ControllerBuilder. Si vous souhaitez mieux comprendre le cycle de vie, vous pouvez soit extraire le framework ASP.NET MVC (la source est disponible), soit vous référer à: cette page

Si vous devez accéder à la session, vous pouvez 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 dépend de la session, il pourrait être difficile d’écrire des tests unitaires. Vous pourriez peut-être envisager de placer la session dans une classe d’aide pouvant être remplacée par une autre, non version Web lors de l’exécution de tests unitaires, découplant ainsi 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 l’avertissement standard, 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 de toute façon? Si vous en avez besoin pour TDD, vous devez envelopper la session dans un object modifiable.

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’object HttpSessionStateBase au lieu de l’object Session :

 private static Container defaultContainer() {    return new Container(ioc =>    {        // session manager setup        ioc.For()           .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 demande: base.Initialize (requestContext);

 protected override void Initialize(RequestContext requestContext) { base.Initialize(requestContext); if (web == null && Session != null && Session["APPLIANCE_URL"] != null) { web = new WebServices((Ssortingng)Session["APPLIANCE_URL"]); } }