Como acessar variáveis ​​de sessão de qualquer classe no ASP.NET?

157

Eu criei um arquivo de classe na pasta App_Code no meu aplicativo. Eu tenho uma variável de sessão

Session["loginId"]

Eu quero acessar essas variáveis ​​de sessão na minha classe, mas quando estou escrevendo a seguinte linha, ela gera um erro

Session["loginId"]

Alguém pode me dizer como acessar variáveis ​​de sessão em uma classe criada na pasta app_code no ASP.NET 2.0 (C #)

Prashant
fonte

Respostas:

363

(Atualizado para ser completo)
Você pode acessar variáveis ​​de sessão de qualquer página ou controle usando Session["loginId"]e de qualquer classe (por exemplo, de dentro de uma biblioteca de classes), usandoSystem.Web.HttpContext.Current.Session["loginId"].

Mas leia a minha resposta original ...


Eu sempre uso uma classe de wrapper em torno da sessão do ASP.NET para simplificar o acesso às variáveis ​​da sessão:

public class MySession
{
    // private constructor
    private MySession()
    {
      Property1 = "default value";
    }

    // Gets the current session.
    public static MySession Current
    {
      get
      {
        MySession session =
          (MySession)HttpContext.Current.Session["__MySession__"];
        if (session == null)
        {
          session = new MySession();
          HttpContext.Current.Session["__MySession__"] = session;
        }
        return session;
      }
    }

    // **** add your session properties here, e.g like this:
    public string Property1 { get; set; }
    public DateTime MyDate { get; set; }
    public int LoginId { get; set; }
}

Essa classe armazena uma instância própria na sessão do ASP.NET e permite que você acesse as propriedades da sessão de maneira segura, a partir de qualquer classe, por exemplo:

int loginId = MySession.Current.LoginId;

string property1 = MySession.Current.Property1;
MySession.Current.Property1 = newValue;

DateTime myDate = MySession.Current.MyDate;
MySession.Current.MyDate = DateTime.Now;

Esta abordagem tem várias vantagens:

  • ele evita que você seja vítima de muitas transmissões de tipos
  • você não precisa usar chaves de sessão codificadas em todo o aplicativo (por exemplo, Session ["loginId"]
  • você pode documentar os itens da sua sessão adicionando comentários de documentos XML nas propriedades do MySession
  • você pode inicializar suas variáveis ​​de sessão com valores padrão (assegurando que eles não sejam nulos)
M4N
fonte
6
Não é necessário escrever nenhum código, use como mostrado na resposta. Por exemplo, "public int LoginId {get; set;}" -> isso é chamado de propriedade automática.
M4N
4
Se você estiver usando .net 3.x, poderá usar propriedades automáticas, como mostrado no meu código. Com .net 2.x / 1.x, isso não está disponível e você deve implementar o getter / setter de suas propriedades: private int _loginId; public int LoginId {get {return _loginId; } defina {_loginId = value; }}
M4N
2
Parece legal agora, acho que recebi a resposta do meu problema e estou sempre usando o seu caminho, é muito limpo e fácil manter todas as minhas variáveis ​​de sessão em um só lugar. Obrigado @ Martin, você é IMPRESSIONANTE.
Prashant
23
@ M4N, gostaria de expressar um pouco mais de gratidão do que um +1. Essa se tornou minha maneira favorita de lidar com a sessão / cache em meus projetos. Meu código, literalmente, está agradecendo.
Brandon Boone
4
@ Kristopher, enquanto a propriedade 'Current' é estática, a instância do MySession retornada não é ... então está tudo bem. Métodos e propriedades estáticas são seguros para uso dessa maneira.
Darren
104

Acesse a sessão através dos tópicos HttpContext: -

HttpContext.Current.Session["loginId"]
AnthonyWJones
fonte
Muito obrigado Anthony por este passo simples.
22412 Kings
Muito obrigado Anthony, + 1 para que
Owais Qureshi
Obrigado. Esqueceu o que o namespace foi :)
Anthony Horne
@AnthonyWJones eu usei o seu método, mas tenho um problema, você pode me explicar, onde estou errado ou qual é a maneira correta de usar, minha pergunta stackoverflow.com/questions/45254279/…
adnan
e se você deseja converter para HttpSessionStateBase: HttpSessionStateBase session = new HttpSessionStateWrapper (HttpContext.Current.Session); Re: stackoverflow.com/questions/5447611/…
sobelito 26/10/19
24

O problema com a solução sugerida é que ele pode interromper alguns recursos de desempenho incorporados no SessionState se você estiver usando um armazenamento de sessão fora de processo. ("State Server Mode" ou "SQL Server Mode"). Nos modos oop, os dados da sessão precisam ser serializados no final da solicitação de página e desserializados no início da solicitação de página, o que pode ser caro. Para melhorar o desempenho, o SessionState tenta desserializar apenas o necessário, desserializando apenas a variável quando é acessado pela primeira vez, e apenas re-serializa e substitui a variável que foi alterada. Se você possui muitas variáveis ​​de sessão e as coloca em uma única classe, basicamente tudo na sua sessão será desserializado em todas as solicitações de página que usam a sessão e tudo precisará ser serializado novamente, mesmo que apenas uma propriedade seja alterada porque a classe foi alterada. Apenas algo a considerar se você estiver usando um monte de sessão e um modo oop.

Ernie
fonte
4
+1 por trazer isso para cima. Se você não estiver usando o InProc for Session, Ernie estará 100% correto. De qualquer forma, o InProc é muito limitado, pois não suporta webfarms e será perdido se o aplicativo reiniciar. Observe que, pelo custo de desempenho, estamos considerando um prêmio de 20% no uso do modo State Server, e os custos de serialização são adicionados além disso. Como você pode imaginar, isso pode ficar caro. Você pode evitar parte da sobrecarga de serialização aderindo a tipos primitivos (por exemplo, int, string, char, byte, etc.). Objetos personalizados serão confrontados com serialização. Usuário cuidado.
Zack Jannsen
+1 bom ponto. Uma mudança que casaria com os dois conceitos seria que cada propriedade dessa classe "session" personalizada chamasse a própria sessão do asp.net em vez de um grande objeto na sessão. Tem que fazer a conversão de tipo que a abordagem da @ M4N evita, mas talvez valha a pena se você ler apenas algumas sessões de cada vez.
EOL
12

As respostas apresentadas antes das minhas fornecem soluções adequadas para o problema, no entanto, sinto que é importante entender por que esse erro ocorre:

A Sessionpropriedade do Pageretorna uma instância do tipo HttpSessionStaterelativa a essa solicitação específica. Page.Sessioné realmente equivalente a chamar Page.Context.Session.

O MSDN explica como isso é possível:

Como as páginas ASP.NET contêm uma referência padrão ao espaço para nome System.Web (que contém a HttpContextclasse), você pode fazer referência aos membros de HttpContextuma página .aspx sem a referência de classe totalmente qualificada HttpContext.

No entanto, quando você tenta acessar esta propriedade dentro de uma classe em App_Code, a propriedade não estará disponível para você, a menos que sua classe derive da Classe de Página.

Minha solução para esse cenário frequentemente encontrado é que nunca passo objetos de página para classes . Eu preferiria extrair os objetos necessários da página Session e passá-los para a classe na forma de uma coleção / matriz / lista de valor-nome, dependendo do caso.

Cerebrus
fonte
Isso é ótimo explicação, isso me ajudou +1 para que :)
Owais Qureshi
1

Eu tive o mesmo erro, porque estava tentando manipular variáveis ​​de sessão dentro de uma classe Session personalizada.

Eu tive que passar o contexto atual (system.web.httpcontext.current) para a classe e tudo deu certo.

MA

MunsterMan
fonte
1

No núcleo do asp.net, isso funciona de maneira diferente:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

    public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

Fonte: https://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/

Matty
fonte
0

Isso deve ser mais eficiente para o aplicativo e também para o desenvolvedor.

Adicione a seguinte classe ao seu projeto da web:

/// <summary>
/// This holds all of the session variables for the site.
/// </summary>
public class SessionCentralized
{
protected internal static void Save<T>(string sessionName, T value)
{
    HttpContext.Current.Session[sessionName] = value;
}

protected internal static T Get<T>(string sessionName)
{
    return (T)HttpContext.Current.Session[sessionName];
}

public static int? WhatEverSessionVariableYouWantToHold
{
    get
    {
        return Get<int?>(nameof(WhatEverSessionVariableYouWantToHold));
    }
    set
    {
        Save(nameof(WhatEverSessionVariableYouWantToHold), value);
    }
}

}

Aqui está a implementação:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Capitão América
fonte