Pergunta

Desejo armazenar o "estado" de algumas ações que o usuário está executando em uma série de diferentes formulários da web ASP.Net.Quais são minhas escolhas para o estado persistente e quais são os prós/contras de cada solução?

Tenho usado objetos Session e alguns métodos auxiliares para digitar fortemente os objetos:

    public static Account GetCurrentAccount(HttpSessionState session)
    {
        return (Account)session[ACCOUNT];
    }

    public static void SetCurrentAccount(Account obj, HttpSessionState session)
    {
        session[ACCOUNT] = obj;
    }

Várias fontes me disseram que "Sessão é má", então essa é realmente a causa raiz desta questão.Quero saber o que você acha das "melhores práticas" e por quê.

Foi útil?

Solução

Não há nada inerentemente mau no estado da sessão.

Há algumas coisas a ter em mente que podem morder você:

  1. Se o usuário pressionar o botão Voltar do navegador, você voltará para a página anterior, mas o estado da sessão não será revertido. Portanto, sua conta atual pode não ser o que estava originalmente na página.
  2. Os processos ASP.NET podem ser reciclados pelo IIS. Quando isso acontecer, você o próximo pedido iniciará um novo processo. Se você estiver usando no estado da sessão do processo, o padrão, ele desaparecerá :-(
  3. A sessão também pode limitar o mesmo resultado se o usuário não estiver ativo por algum tempo. Isso padrão é 20 minutos, para que um bom almoço o faça.
  4. O uso do estado de sessão fora do processo exige que todos os objetos armazenados no estado da sessão sejam serializáveis.
  5. Se o usuário abrir uma segunda janela do navegador, ele esperará ter um segundo aplicativo e distinto, mas o estado da sessão provavelmente será compartilhado entre dois. Portanto, a alteração da conta atual na janela de um navegador fará o mesmo no outro.

Outras dicas

Suas duas opções para armazenar temporariamente os dados do formulário são, primeiro, armazenar as informações de cada formulário em variáveis ​​de estado da sessão e, segundo, passar as informações do formulário usando parâmetros de URL.Usar cookies como uma possível terceira opção simplesmente não é viável pela simples razão de que muitos de seus visitantes provavelmente terão os cookies desativados (no entanto, isso não afeta os cookies de sessão).Além disso, presumo, pela natureza da sua pergunta, que você não deseja armazenar essas informações em uma tabela de banco de dados até que sejam totalmente confirmadas.

Usar variáveis ​​de sessão é a solução clássica para esse problema, mas apresenta algumas desvantagens.Entre eles estão (1) grandes quantidades de dados podem consumir a RAM do servidor se você estiver usando o gerenciamento de sessão inproc, (2) o compartilhamento de variáveis ​​de sessão entre vários servidores em um farm de servidores requer considerações adicionais e (3) um aplicativo projetado profissionalmente deve proteja-se contra a expiração da sessão (não apenas converta uma variável de sessão e use-a - se a sessão expirou, a conversão gerará um erro).No entanto, para a grande maioria das aplicações, as variáveis ​​de sessão são, sem dúvida, o caminho a percorrer.

A alternativa é passar as informações de cada formulário na URL.O principal problema com essa abordagem é que você terá que ser extremamente cuidadoso ao “transmitir” informações.Por exemplo, se você estiver coletando informações em quatro páginas, você precisará coletar informações na primeira e passá-las na URL para a segunda página, onde deverá armazená-las no estado de visualização dessa página.Então, ao chamar a terceira página, você coletará os dados do formulário da segunda página mais as variáveis ​​​​viewstate e codificará ambos na URL, etc.Se você tiver cinco ou mais páginas ou se o visitante estiver pulando pelo site, você terá uma verdadeira bagunça nas mãos.Tenha em mente também que todas as informações precisarão A) ser serializadas em uma string segura para URL e B) codificadas de forma a evitar hacks simples baseados em URL (por exemplo,se você colocar o preço em texto não criptografado e repassá-lo, alguém poderá alterar o preço).Observe que você pode reduzir alguns desses problemas criando uma espécie de "gerenciador de sessão" e fazendo com que ele gerencie as strings de URL para você, mas você ainda teria que ser extremamente sensível à possibilidade de que qualquer link pudesse destruir toda a sessão de alguém se não é gerenciado adequadamente.

No final, eu uso variáveis ​​de URL apenas para transmitir dados muito limitados de uma página para outra (por exemplo,o ID de um item conforme codificado em um link para esse item).

Suponhamos, então, que você realmente gerenciaria os dados de um usuário usando o recurso integrado de Sessões.Por que alguém lhe diria que “Sessão é má”?Bem, além das considerações sobre carga de memória, farm de servidores e expiração apresentadas acima, a principal crítica às variáveis ​​de sessão é que elas são, efetivamente, variáveis ​​não digitadas.

Felizmente, o uso prudente de variáveis ​​de sessão pode evitar problemas de memória (itens grandes devem ser mantidos no banco de dados de qualquer maneira) e se você estiver executando um site grande o suficiente para precisar de um farm de servidores, há muitos mecanismos disponíveis para compartilhar o estado integrado ao ASP. .NET (dica:você não usará armazenamento inproc).

Para evitar essencialmente todas as outras desvantagens da Sessão, recomendo implementar um objeto para armazenar os dados da sua sessão, bem como alguns recursos simples de gerenciamento de objetos da Sessão.Em seguida, transforme-os em um descendente da classe Page e use essa classe descendente Page para todas as suas páginas.É então uma questão simples acessar os dados da sua sessão por meio da classe de página como um conjunto de valores fortemente digitados.Observe que os campos do seu objeto fornecerão uma maneira de acessar cada uma de suas "variáveis ​​de sessão" de maneira fortemente digitada (por exemplo,um campo por variável).

Deixe-me saber se esta é uma tarefa simples para você ou se deseja algum código de exemplo!

Até onde sei, Session é a maneira pretendida de armazenar essas informações. Lembre -se de que o estado da sessão geralmente é armazenado no processo por padrão. Se você possui vários servidores da Web ou se houver uma reinicialização do IIS, você perde o estado da sessão. Isso pode ser corrigido usando um serviço de estado do ASP.NET ou mesmo um banco de dados SQL para armazenar sessões. Isso garante que as pessoas recuperem sua sessão, mesmo que sejam redirecionadas para um servidor da Web diferente ou em caso de reciclagem do processo do trabalhador.

Uma das razões para sua reputação sinistra é que desenvolvedores apressados ​​o usam excessivamente com literais de string no código da UI (em vez de uma classe auxiliar como a sua) como chaves de item, e acabam com um grande saco de estados promíscuos não testáveis.Algum tipo de wrapper é um requisito básico para uso de sessões não-malignas.

Quanto à "sessão de ser má" ... se você estivesse se desenvolvendo no ASP clássico, eu teria que concordar, mas asp.net/iis faz um trabalho muito melhor.

A verdadeira questão é qual é a melhor maneira de manter o estado. No nosso caso, quando se trata do usuário logado atual, armazenamos esse objeto em sessão, como somos constantemente Referindo -se a ele para o nome deles, endereço de e -mail, autorização e assim por diante.

Outro pequeno Tidbits De informações que não precisam de nenhuma persistência a longo prazo, usamos uma combinação de cookies e viewstate.

Quando você deseja armazenar informações que podem ser acessadas globalmente em seu aplicativo da web, uma maneira de fazer isso é o ThreadStatic atributo. Isso transforma um static membro de um Class em um membro compartilhado pelo encadeamento atual, mas não em outros threads. A vantagem de ThreadStatic é que você não precisa ter um contexto da web disponível. Por exemplo, se você tem um back -end que não faz referência System.Web, mas quero compartilhar informações lá também, você pode definir o usuário id no início de cada solicitação no ThreadStatic propriedade e referencie -a em sua dependência sem a necessidade de ter acesso ao Session objeto.

Porque é static Mas apenas para um único tópico, garantimos que outros visitantes simultâneos não recebam nossa sessão. Isso funciona, desde que você garanta que a propriedade seja redefinida para cada solicitação. Isso o torna um companheiro ideal para os cookies.

Eu acho que o uso do objeto de sessão é bom neste caso, mas você deve se lembrar que a sessão pode expirar se não houver atividade do navegador por muito tempo (HttpSessionState.Timeout A propriedade determina em quantos minutos o fornecedor do estado de sessão encerra a sessão), por isso é melhor verificar a existência de valor antes do retorno:

public static Account GetCurrentAccount(HttpSessionState session)
{
    if (Session[ACCOUNT]!=null)
        return (Account)Session[ACCOUNT];
    else
        throw new Exception("Can't get current account. Session expired.");
}

Informações de curto prazo, que só precisam viver até a próxima solicitação, também podem ser armazenadas no ViewState. Isso significa que os objetos são serializados e armazenados na página enviados ao navegador, que é então publicado de volta ao servidor em um evento de clique ou similar. Então o ViewState é decodificado e transformado em objetos novamente, pronto para serem recuperados.

As sessões não são maus, elas desempenham uma função importante no aplicativo ASP.NET, atendendo dados que devem ser compartilhados entre várias páginas durante a "sessão" de um usuário. Existem algumas sugestões, eu diria para usar o gerenciamento de sessões do SQL sempre que possível e certifique -se de que os objetos que você está usando na sua coleção de sessões sejam "serializáveis". As melhores práticas seriam usar o objeto de sessão quando você precisar compartilhar informações do estado nas páginas e não usá -lo quando não precisar. As informações não estarão disponíveis no lado do cliente, uma chave de sessão é mantida em um cookie, ou através da sequência de consultas, ou usando outros métodos, dependendo de como ela é configurada e, em seguida, os objetos da sessão estão disponíveis na tabela de banco de dados ( A menos que você use o Inproc, nesse caso, suas sessões terão a chance de ser impressionado durante uma recarga do site ou serão quase inúteis na maioria dos ambientes agrupados).

Acho que o "mal" vem do uso excessivo da sessão.Se você simplesmente colocar tudo e qualquer coisa nele (como usar variáveis ​​globais para tudo), você acabará tendo um desempenho ruim e uma bagunça.

Tudo o que você coloca no objeto de sessão permanece lá durante a duração da sessão, a menos que seja limpo. O mau gerenciamento da memória armazenado usando o Inproc e o estadista o forçará a escalar mais cedo do que o necessário. Armazene apenas um ID para a sessão/usuário na sessão e carregue o que é necessário no objeto de cache sob demanda usando uma classe auxiliar. Dessa forma, você pode ajustar sua vida de acordo com a frequência com que esses dados nos usavam. A próxima versão do ASP.NET pode ter um cache distribuído (boato).

Sessão como mal:Não está no ASP.NET, configurado corretamente.Sim, o ideal é ser o mais apátrida possível, mas a realidade é que não é possível chegar lá a partir daqui.Você pode, no entanto, fazer com que a sessão se comporte de maneira a diminuir seu impacto - principalmente sessões de StateServer ou de banco de dados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top