web-dev-qa-db-fra.com

HttpContext.Current.Session est null lors du routage des demandes

Sans routage, HttpContext.Current.Session est présent, donc je sais que la StateServer fonctionne. Lorsque je route mes demandes, HttpContext.Current.Session est null dans la page routée. J'utilise .NET 3.5 sp1 sur IIS 7.0, sans les aperçus MVC. Il apparaît que AcquireRequestState n'est jamais déclenché lors de l'utilisation des itinéraires et que la variable de session n'est pas instanciée/remplie.

Lorsque j'essaie d'accéder aux variables de session, j'obtiens cette erreur:

base {System.Runtime.InteropServices.ExternalException} = {"Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the <configuration>.

Lors du débogage, j'obtiens également le message d'erreur selon lequel le HttpContext.Current.Session n'est pas accessible dans ce contexte.

-

Mon web.config ressemble à ceci:

<configuration>
  ...
  <system.web>
    <pages enableSessionState="true">
      <controls>
        ...
      </controls>
    </pages>
    ...
  </system.web>
  <sessionState cookieless="AutoDetect" mode="StateServer" timeout="22" />
  ...
</configuration>

Voici l'implémentation d'IRouteHandler:

public class WebPageRouteHandler : IRouteHandler, IRequiresSessionState
{
    public string m_VirtualPath { get; private set; }
    public bool m_CheckPhysicalUrlAccess { get; set; }

    public WebPageRouteHandler(string virtualPath) : this(virtualPath, false)
    {
    }
    public WebPageRouteHandler(string virtualPath, bool checkPhysicalUrlAccess)
    {
        m_VirtualPath = virtualPath;
        m_CheckPhysicalUrlAccess = checkPhysicalUrlAccess;
    }

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        if (m_CheckPhysicalUrlAccess
            && !UrlAuthorizationModule.CheckUrlAccessForPrincipal(
                   m_VirtualPath,
                   requestContext.HttpContext.User,
                   requestContext.HttpContext.Request.HttpMethod))
        {
            throw new SecurityException();
        }

        string var = String.Empty;
        foreach (var value in requestContext.RouteData.Values)
        {
            requestContext.HttpContext.Items[value.Key] = value.Value;
        }

        Page page = BuildManager.CreateInstanceFromVirtualPath(
                        m_VirtualPath, 
                        typeof(Page)) as Page;// IHttpHandler;

        if (page != null)
        {
            return page;
        }
        return page;
    }
}

J'ai aussi essayé de mettre EnableSessionState="True" en haut des pages aspx mais toujours rien.

Des idées? Devrais-je écrire une autre HttpRequestHandler qui implémente IRequiresSessionState?

Merci.

42
Loki

Je l'ai. Assez stupide, en fait. Cela a fonctionné après que j'ai enlevé et ajouté le SessionStateModule comme ceci:

<configuration>
  ...
  <system.webServer>
    ...
    <modules>
      <remove name="Session" />
      <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
      ...
    </modules>
  </system.webServer>
</configuration>

Le simple fait de l'ajouter ne fonctionnera pas car "Session" aurait déjà dû être défini dans le machine.config.

Maintenant, je me demande si c'est la chose habituelle à faire. Cela ne semble sûrement pas, puisqu'il semble si grossier ...

52
Loki

Ajoutez simplement l'attribut runAllManagedModulesForAllRequests="true" à system.webServer\modules dans web.config.

Cet attribut est activé par défaut dans les projets MVC et Dynamic Data.

23
gandjustas

runAllManagedModulesForAllRequests=true est en réalité une très mauvaise solution. Cela a augmenté le temps de chargement de mon application de 200%. La meilleure solution consiste à supprimer et à ajouter manuellement l'objet de session et à éviter tous les attributs d'exécuter tous les modules gérés. 

14
Frankie Rodriguez

Aucune de ces solutions n'a fonctionné pour moi. J'ai ajouté la méthode suivante dans global.asax.cs alors la session n'était pas nulle:

protected void Application_PostAuthorizeRequest()
{
    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
3
Viqas

Bon travail! J'ai eu exactement le même problème. Ajouter et supprimer le module Session a parfaitement fonctionné pour moi aussi. Il n’a toutefois pas été rapporté par HttpContext.Current.User, j’ai donc essayé votre petit tour avec le module FormsAuth et, bien sûr, cela a fonctionné.

<remove name="FormsAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"/>
3
Mike

Ce que @Bogdan Maxim a dit. Vous pouvez également utiliser InProc si vous n'utilisez pas de serveur d'état de session externe.

<sessionState mode="InProc" timeout="20" cookieless="AutoDetect" />

Regardez ici pour plus d’informations sur la directive SessionState.

2
tvanfosson

une meilleure solution est 

runAllManagedModulesForAllRequests est une chose astucieuse à faire en respectant le retrait et la réinsertion du module de session.

alk.

alk.

1
Alkampfer

Je pense que cette partie du code modifie le contexte.

 Page page = BuildManager.CreateInstanceFromVirtualPath(
                        m_VirtualPath, 
                        typeof(Page)) as Page;// IHttpHandler;

De plus, cette partie du code est inutile:

 if (page != null)
 {
     return page;
 }
 return page;

Il retournera toujours la page, qu'elle soit nulle ou non.

0
mohammedn

Il semble que vous ayez oublié d'ajouter votre adresse de serveur d'état dans le fichier config .

 <sessionstate mode="StateServer" timeout="20" server="127.0.0.1" port="42424" />
0
Bogdan Maxim

La section de configuration semble bonne car elle fonctionne lorsque les pages sont accessibles normalement. J'ai essayé les autres configurations suggérées mais le problème est toujours là. 

Je doute que le problème réside dans le fournisseur de session, car il fonctionne sans routage.

0
Loki

Il me manquait une référence à System.web.mvc dll dans l'adaptateur de session et son ajout corrigeait le problème.

J'espère que cela aidera quelqu'un d'autre à traverser le même scénario.

0
Mandeep Janjua