web-dev-qa-db-fra.com

Session null dans les constructeurs de contrôleur ASP.Net MVC

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.]

83
Chris Arnold

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.

72
Andrew W

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.

55
Mike Chamberlain

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.

10
Andrei Rînea

Vous pouvez remplacer la méthode Initialize pour définir votre session.

protected override void Initialize(RequestContext requestContext)
7
Funlover

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)); 
    });
}
2
VahidN

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"]);
            }

        }
0