Introdução
Em um ambiente sem estado como um aplicativo Web, compreender o conceito de estado de sessão não tem significado real. No entanto, o gerenciamento eficaz do estado é um recurso obrigatório para a maioria das aplicações Web. O Microsoft ASP.NET, assim como muitos outros ambientes de programação do lado do servidor, fornecem uma camada de abstração que permite que os aplicativos armazenem dados persistentes por usuário e por aplicativo.
É importante observar que o estado da sessão de um aplicativo Web são os dados que o aplicativo armazena em cache e recupera em diferentes solicitações. Uma sessão representa todas as solicitações enviadas pelo usuário enquanto conectado ao site, e o estado da sessão é a coleção de dados persistentes gerados e consumidos pelo usuário durante a sessão. O estado de cada sessão é independente um do outro e deixa de existir quando a sessão do usuário termina.
O estado da sessão não tem correspondência com nenhuma das entidades lógicas que compõem o protocolo e a especificação HTTP. As sessões são uma camada de abstração construída por ambientes de desenvolvimento do lado do servidor, como ASP tradicional e ASP.NET. A forma como o ASP.NET exibe o estado da sessão e como o estado da sessão é implementado internamente depende da infraestrutura da plataforma. Portanto, o ASP tradicional e o ASP.NET implementam o estado da sessão de maneiras completamente diferentes, e mais melhorias e aprimoramentos são esperados na próxima versão do ASP.NET.
Este artigo discute como implementar o estado da sessão no ASP.NET 1.1 e como otimizar o gerenciamento do estado da sessão em aplicativos Web gerenciados.
Visão geral do estado da sessão ASP.NET
O estado da sessão não faz parte da infraestrutura HTTP. Ou seja, deve haver um componente estrutural que vincule o estado da sessão a cada solicitação recebida. O ambiente de execução (ASP tradicional ou ASP.NET) pode aceitar palavras-chave como Session e utilizá-las para indicar o bloco de dados armazenado no servidor. Para resolver chamadas com êxito para um objeto Session, o ambiente de tempo de execução deve adicionar o estado da sessão ao contexto de chamada da solicitação que está sendo processada. A forma como isso é feito varia entre plataformas, mas é fundamental para aplicações web com estado.
No ASP tradicional, o estado da sessão é implementado como objetos COM de thread livre contidos na biblioteca asp.dll. (Você está curioso? O CLSID deste objeto é na verdade D97A6DA0-A865-11cf-83AF-00A0C90C2BD8.) Este objeto armazena dados organizados como uma coleção de pares nome/valor. O espaço reservado “nome” representa a chave usada para recuperar as informações, enquanto o espaço reservado “valor” representa o que está armazenado no estado da sessão. Os pares nome/valor são agrupados por ID de sessão para que cada usuário veja apenas os pares nome/valor que ele criou.
No ASP.NET, a interface de programação para o estado da sessão é quase a mesma do ASP tradicional. Mas as suas implementações básicas são completamente diferentes. A primeira é mais flexível, escalável e tem capacidades de programação mais fortes do que a segunda. Antes de nos aprofundarmos no estado da sessão do ASP.NET, vamos revisar brevemente alguns dos recursos estruturais da infraestrutura de sessão do ASP.NET.
No ASP.NET, qualquer solicitação HTTP recebida é canalizada através do módulo HTTP. Cada módulo pode filtrar e modificar a grande quantidade de informações transportadas pela solicitação. A informação associada a cada solicitação é chamada de “contexto de chamada”, que é representado pelo objeto HttpContext na programação. Não devemos pensar no contexto da solicitação como outro contêiner de informações de estado, embora a coleção de itens que ele fornece seja apenas um contêiner de dados. O objeto HttpContext difere de todos os outros objetos de estado (por exemplo, Sessão, Aplicativo e Cache) porque tem um tempo de vida limitado além do tempo necessário para tratar a solicitação. Quando uma solicitação passa por uma série de módulos HTTP registrados, seu objeto HttpContext conterá uma referência ao objeto de estado. Quando a solicitação pode finalmente ser processada, o contexto de chamada associado é vinculado à sessão específica (Sessão) e aos objetos de estado global (Aplicativo e Cache).
O módulo HTTP responsável por definir o estado da sessão de cada usuário é SessionStateModule. A estrutura deste módulo é projetada com base na interface IHttpModule, que fornece um grande número de serviços relacionados ao estado de sessão para aplicativos ASP.NET. Inclui a geração de IDs de sessão, gerenciamento de sessão sem cookies, recuperação de dados de sessão de provedores de estado externos e vinculação de dados ao contexto de chamada da solicitação.
O módulo HTTP não armazena dados de sessão internamente. O estado da sessão é sempre salvo em um componente externo denominado "provedor de estado". O provedor de estado encapsula completamente os dados do estado da sessão e se comunica com outras partes por meio dos métodos da interface IStateClientManager. O módulo HTTP do estado da sessão chama métodos nesta interface para ler e salvar o estado da sessão. O ASP.NET 1.1 oferece suporte a três provedores de estado diferentes, conforme mostrado na Tabela 1.
Tabela 1: Status Cliente Provedor
Descrição do Provedor
Os valores da sessão InProc permanecem objetos ativos na memória do processo de trabalho ASP.NET (aspnet_wp.exe ou w3wp.exe no Microsoft® Windows Server® 2003). Esta é a opção padrão.
Os valores da sessão StateServer são serializados e armazenados na memória em um processo separado (aspnet_state.exe). O processo também pode ser executado em outros computadores.
Os valores da sessão SQLServer são serializados e armazenados em tabelas do Microsoft® SQL Server®. As instâncias do SQL Server podem ser executadas local ou remotamente.
O módulo HTTP do estado da sessão lê o provedor de estado atualmente selecionado na seção <sessionState> do arquivo web.config.
<sessionState mode="InProc | StateServer | SQLServer />;
Dependendo do valor do atributo mode, o estado da sessão será recuperado e armazenado em diferentes processos por meio de diferentes etapas. Por padrão, o estado da sessão é armazenado no local Processo de trabalho do ASP.NET. Em casos especiais, ele é armazenado em um slot dedicado do objeto Cache do ASP.NET (o estado da sessão não acessível de forma programática também pode ser armazenado externamente, mesmo em um processo remoto (por exemplo, em um Windows). Serviço NT denominado aspnet_state.exe). A terceira opção é armazenar o estado da sessão em uma tabela de banco de dados dedicada gerenciada pelo SQL Server 2000.
O módulo HTTP desserializa o valor da sessão no início da solicitação, tornando-os objetos de dicionário. (na verdade, objetos do tipo HttpSessionState) são então acessados programaticamente por meio da propriedade Session exposta pelas classes (por exemplo, HttpContext e Page). A ligação dura até que a solicitação seja concluída com êxito, todos os valores de status são serializados de volta. ao provedor de status e disponível para outras solicitações
A Figura 1 ilustra a comunicação entre a página ASP.NET solicitada e os valores da sessão. O código usado por cada página está relacionado ao atributo Session na classe da página. o mesmo que o ASP tradicional.
Figura 1: Arquitetura do estado da sessão no ASP.NET 1.1
O valor físico do estado da sessão é bloqueado pelo tempo necessário para concluir a solicitação. Este bloqueio é gerenciado internamente pelo módulo HTTP e é usado para sincronizar o acesso ao estado da sessão.
O módulo de estado da sessão instancia o provedor de estado do aplicativo e o inicializa com informações lidas do arquivo web.config. A seguir, cada provedor continuará suas próprias operações de inicialização. Dependendo do tipo de provedor, suas operações de inicialização irão variar bastante. Por exemplo, o gerenciador de estado do SQL Server abrirá uma conexão com um determinado banco de dados, enquanto o gerenciador fora de processo verificará a porta TCP especificada. Por outro lado, o gerenciador de estado InProc armazenará uma referência à função de retorno de chamada. Esta ação é executada quando um elemento é removido do cache e é usado para acionar o evento Session_OnEnd da aplicação.
Acesso síncrono ao estado da sessão
O que acontece quando uma página Web faz uma chamada muito simples e intuitiva à propriedade Session? Muitas operações são executadas em segundo plano, conforme mostrado no código complicado a seguir:
int siteCount = Convert.ToInt32(Session["Counter"]);
O código acima realmente acessa o valor da sessão criado pelo módulo HTTP na memória local. lê dados de um provedor estatal específico (veja a Figura 1). O que acontece se outras páginas também tentarem acessar o estado da sessão de forma síncrona? Nesse caso, a solicitação atual pode parar de processar dados inconsistentes ou obsoletos. Para evitar isso, o módulo de estado da sessão implementará um mecanismo de bloqueio de leitor/gravador e enfileirará o acesso aos valores de estado. As páginas com permissões de gravação no estado da sessão manterão o bloqueio de gravação dessa sessão até que a solicitação termine.
Uma página pode solicitar permissão de gravação para o estado da sessão definindo a propriedade EnableSessionState da diretiva @Page como verdadeira. (Esta é a configuração padrão). No entanto, uma página também pode ter acesso somente leitura ao estado da sessão, por exemplo, quando a propriedade EnableSessionState está definida como ReadOnly. Neste caso, o módulo manterá o bloqueio do leitor para aquela sessão até que a solicitação daquela página termine. Como resultado, ocorrerão leituras simultâneas.
Se uma solicitação de página definir um bloqueio de leitor, outras solicitações simultâneas na mesma sessão não poderão atualizar o estado da sessão, mas pelo menos poderão ler. Ou seja, se uma solicitação somente leitura estiver sendo processada para uma sessão, a solicitação somente leitura pendente terá prioridade mais alta do que uma solicitação que exija acesso total. Se uma solicitação de página definir um bloqueio de gravação para o estado da sessão, todas as outras páginas serão bloqueadas, independentemente de desejarem ler ou gravar conteúdo. Por exemplo, se dois quadros tentarem escrever na Sessão ao mesmo tempo, um quadro deverá esperar até que o outro termine antes de poder escrever.
Comparando provedores de estado
Por padrão, os aplicativos ASP.NET armazenam o estado da sessão na memória de um processo de trabalho, especificamente em um slot dedicado do objeto Cache. Quando o modo InProc é selecionado, o estado da sessão é armazenado em slots no objeto Cache. Este slot está marcado como privado e não pode ser acessado programaticamente. Em outras palavras, se você enumerar todos os itens no cache de dados do ASP.NET, nenhum objeto semelhante ao estado da sessão fornecido será retornado. Os objetos de cache fornecem dois tipos de slots: slots privados e slots públicos. Os programadores podem adicionar e manipular slots públicos, mas os slots privados só podem ser usados pelo sistema (especificamente, classes definidas na system.web part).
O estado de cada sessão ativa ocupa um slot dedicado no cache. O slot é nomeado com base no ID da sessão e seu valor é uma instância de uma classe interna não declarada chamada SessionStateItem. O provedor de estado InProc obtém o ID da sessão e recupera o elemento correspondente no cache. O conteúdo do objeto SessionStateItem é então inserido no objeto de dicionário HttpSessionState e acessado pelo aplicativo por meio da propriedade Session. Observe que há um bug no ASP.NET 1.0 que torna os slots privados do objeto Cache enumeráveis programaticamente. Se você executar o código a seguir no ASP.NET 1.0, poderá enumerar os itens correspondentes aos objetos contidos em cada estado de sessão atualmente ativo.
foreach (elemento de entrada de dicionário no cache)
{
Response.Write(elem.Key + ": " + elem.Value.ToString());
}
Este bug foi resolvido no ASP.NET 1.1 e quando você enumera o conteúdo em cache, nenhum slot do sistema será listado mais.
InProc é provavelmente a opção de acesso mais rápida, de longe. Mas tenha em mente que quanto mais dados armazenados em uma sessão, mais memória o servidor web consome, aumentando potencialmente o risco de degradação do desempenho. Se você planeja usar qualquer solução fora do processo, considere cuidadosamente os possíveis efeitos da serialização e desserialização. A solução fora do processo usa um serviço do Windows NT (aspnet_state.exe) ou uma tabela do SQL Server para armazenar valores de sessão. Portanto, o estado da sessão permanece fora do processo de trabalho do ASP.NET e são necessárias camadas adicionais de código para serializar e desserializar entre o estado da sessão e o meio de armazenamento real. Isso acontece sempre que uma solicitação é processada e deve ser otimizada ao mais alto nível.
Como os dados da sessão precisam ser copiados do repositório externo para o dicionário da sessão local, a solicitação resulta em degradação de desempenho que varia de 15% (fora do processo) a 25% (SQL Server). Note-se que embora esta seja apenas uma estimativa aproximada, deverá estar próxima do impacto mínimo e o impacto máximo será muito superior a este. Na verdade, esta estimativa não leva totalmente em conta a complexidade dos tipos realmente salvos no estado da sessão.
No cenário de armazenamento fora do processo, o estado da sessão sobrevive por mais tempo, tornando o aplicativo mais poderoso porque protege contra falhas do Microsoft® Internet Information Services (IIS) e do ASP.NET. Ao separar o estado da sessão dos aplicativos, você também pode estender mais facilmente os aplicativos existentes para arquiteturas Web Farm e Web Garden. Além disso, o estado da sessão é armazenado em um processo externo, eliminando essencialmente o risco de perda periódica de dados devido a loops de processo.
Veja como usar os serviços do Windows NT. Conforme mencionado acima, o serviço NT é um processo denominado aspnet_state.exe, geralmente localizado na pasta C:WINNTMicrosoft.NETFrameworkv1.1.4322.
O diretório real depende da versão do Microsoft® .NET Framework que você está executando. Antes de usar o servidor de estado, você deve garantir que o serviço esteja pronto e em execução no computador local ou remoto usado como dispositivo de armazenamento de sessão. O serviço de estado faz parte e é instalado com o ASP.NET, portanto, você não precisa executar um instalador adicional. Por padrão, o serviço de status não está em execução e precisa ser iniciado manualmente. O aplicativo ASP.NET tentará estabelecer uma conexão com o servidor de estado imediatamente após ser carregado. Portanto, o serviço deve estar pronto e em execução, caso contrário uma exceção HTTP será lançada. A imagem a seguir mostra a caixa de diálogo de propriedades do serviço.
Figura 2: Caixa de diálogo Propriedades do servidor de estado do ASP.NET
Os aplicativos ASP.NET precisam especificar o endereço TCP/IP do computador onde o serviço de estado da sessão está localizado. As configurações a seguir devem ser inseridas no arquivo web.config do aplicativo.
<configuração>;
<sistema.web>;
<sessãoEstado
mode="EstadoServidor"
stateConnectionString="tcpip=expoware:42424" />;
</system.web>;
</configuration>;
O atributo stateConnectionString contém o endereço IP do computador e a porta usada para troca de dados. O endereço padrão do computador é 127.0.0.1 (localhost) e a porta padrão é 42424. Você também pode indicar o computador pelo nome. Usar um computador local ou remoto é totalmente transparente para o código. Observe que caracteres não ASCII não podem ser usados no nome e o número da porta é obrigatório.
Se você usar o armazenamento de sessão fora do processo, o estado da sessão ainda existirá e estará disponível para uso futuro, independentemente do que acontecer com o processo de trabalho do ASP.NET. Se o serviço for interrompido, os dados serão retidos e recuperados automaticamente quando o serviço for restaurado. Entretanto, se o serviço do provedor de status parar ou falhar, os dados serão perdidos. Se você deseja que seu aplicativo seja poderoso, use o modo SQLServer em vez do modo StateServer.
<configuração>;
<sistema.web>;
<sessãoEstado
modo = "SQLServer"
sqlConnectionString="servidor=127.0.0.1;uid=<id do usuário>;;pwd=<senha>;;"
</system.web>;
</configuration>;
Você pode especificar a string de conexão através do atributo sqlConnectionString. Observe que a sequência de atributos deve conter o ID do usuário, a senha e o nome do servidor. Ele não pode conter tags como Banco de Dados e Catálogo Inicial porque o padrão dessas informações é um nome fixo. IDs de usuário e senhas podem ser substituídas por configurações de segurança integradas.
Como criar um banco de dados? O ASP.NET fornece dois pares de scripts para configurar o ambiente do banco de dados. O primeiro par de scripts é denominado InstallSqlState.sql e UninstallSqlState.sql e está localizado na mesma pasta que o serviço Session State NT. Eles criam um banco de dados chamado ASPState e vários procedimentos armazenados. No entanto, os dados são armazenados no banco de dados TempDB da área de armazenamento temporário do SQL Server. Isso significa que se o computador SQL Server for reiniciado, os dados da sessão serão perdidos.
Para contornar essa limitação, use um segundo par de scripts. O segundo par de scripts é denominado InstallPersistSqlState.sql e UninstallPersistSqlState.sql. Neste caso, o banco de dados ASPState é criado, mas as tabelas são criadas no mesmo banco de dados e também são persistentes. Ao instalar o suporte do SQL Server para sessões, também é criado um trabalho para excluir sessões expiradas no banco de dados de estado da sessão. A tarefa é denominada ASPState_Job_DeleteExpiredSessions e está sempre em execução. Observe que para que este trabalho funcione corretamente, o serviço SQLServerAgent precisa estar em execução.
Não importa o modo escolhido, a forma como as operações do estado da sessão são codificadas não muda. Você sempre pode trabalhar na propriedade Session e ler e escrever valores normalmente. Todas as diferenças de comportamento são tratadas em um nível inferior de abstração. A serialização de estado é talvez a diferença mais importante entre os modos de sessão.
Serialização e desserialização de estado
Ao usar o modo em processo, os objetos são armazenados no estado de sessão como instâncias ativas de suas respectivas classes. Se nenhuma serialização e desserialização reais ocorrerem, significa que você pode realmente armazenar qualquer objeto criado na Sessão (incluindo objetos que não podem ser serializados e objetos COM), e acessá-los não será muito caro. Se você escolher um provedor estatal fora do processo, a história é outra.
Em uma arquitetura fora de processo, os valores da sessão são copiados da mídia de armazenamento local (banco de dados AppDomain externo) para a memória do AppDomain que trata a solicitação. Uma camada de serialização/desserialização é necessária para realizar esta tarefa e representa um dos principais custos dos provedores de estado fora de processo. O principal impacto que esta situação tem no seu código é que apenas objetos serializáveis podem ser armazenados no dicionário de sessão.
O ASP.NET usa dois métodos para serializar e desserializar dados, dependendo do tipo de dados envolvidos. Para tipos básicos, o ASP.NET usa um serializador interno otimizado; para outros tipos, incluindo objetos e classes definidas pelo usuário, o ASP.NET usa o formatador binário .NET. Os tipos básicos incluem strings, datas e horas, valores booleanos, bytes, caracteres e todos os tipos numéricos. Para esses tipos, usar um serializador personalizado é mais rápido do que usar o formatador binário .NET comum padrão.
O serializador otimizado não é divulgado ou documentado publicamente. É apenas um leitor/gravador binário e usa uma arquitetura de armazenamento simples, mas eficaz. O serializador usa a classe BinaryWriter para escrever uma representação de bytes do tipo e, em seguida, grava uma representação de bytes do valor correspondente a esse tipo. Ao ler bytes serializados, a classe primeiro extrai um byte, detecta o tipo de dados a ser lido e, em seguida, chama o método ReadXxx específico do tipo na classe BinaryReader.
Observe que o tamanho dos tipos booleanos e numéricos é bem conhecido, mas não para strings. No fluxo de dados subjacente, a string é sempre prefixada com um comprimento fixo (um código inteiro de 7 bits escrito por vez), e o leitor usa esse fato para determinar o tamanho correto da string. O valor da data é salvo escrevendo apenas o número total de tokens que compõem a data. Portanto, para serializar a sessão, a data deverá ser do tipo Int64.
Você pode usar a classe BinaryFormatter para executar operações de serialização em objetos mais complexos (bem como em objetos personalizados), desde que a classe que os contém esteja marcada como serializável. Todos os tipos não básicos são identificados pelo mesmo ID de tipo e armazenados no mesmo fluxo de dados que os tipos básicos. No geral, as operações de serialização podem resultar em uma degradação de desempenho de 15% a 25%. Observe, entretanto, que esta é uma estimativa aproximada baseada na suposição de que tipos básicos são usados. Quanto mais complexos forem os tipos usados, maior será a sobrecarga.
O armazenamento eficiente de dados de sessão é difícil de implementar sem o uso extensivo de tipos primitivos. Portanto, pelo menos em teoria, usar três slots de sessão para salvar três propriedades de string diferentes de um objeto é melhor do que serializar o objeto inteiro. Mas e se o objeto que você deseja serializar contiver 100 propriedades? Você quer usar 100 slots ou apenas um slot? Em muitos casos, uma abordagem melhor é converter um tipo complexo em vários tipos mais simples. Esta abordagem é baseada em conversores de tipo. Um "conversor de tipo" é um serializador leve que retorna as principais propriedades de um tipo como uma coleção de strings. Conversores de tipo são classes externas vinculadas a uma classe base usando atributos. Cabe ao gravador decidir quais propriedades serão salvas e como. Os conversores de tipo também são úteis para armazenamento ViewState e representam um método mais eficiente de armazenamento de sessão do que formatadores binários.
Ciclo de vida da sessão
Um ponto importante sobre o gerenciamento de sessões do ASP.NET é que o ciclo de vida do objeto de estado da sessão começa somente quando o primeiro item é adicionado ao dicionário na memória. Uma sessão ASP.NET é considerada iniciada somente após a execução do trecho de código a seguir.
Session["MySlot"] = "Alguns dados";
O dicionário Session geralmente contém o tipo Object. Para ler os dados de trás para frente, o valor retornado precisa ser convertido para um tipo mais específico.
string data = (string) Session["MySlot"];
Quando a página salva dados na Sessão, o valor será carregado na classe de dicionário especialmente criada contida na classe HttpSessionState. O conteúdo do dicionário é carregado no provedor de estado quando a solicitação atualmente processada é concluída. Se o estado da sessão estiver vazio porque os dados não foram colocados no dicionário programaticamente, os dados não serão serializados no meio de armazenamento e, mais importante, não serão servidos no ASP.NET Cache, SQL Server ou NT State Services Create um slot para rastrear a sessão atual. Isto ocorre por motivos de desempenho, mas tem um impacto importante em como os IDs de sessão são tratados: um novo ID de sessão será gerado para cada solicitação até que alguns dados sejam armazenados no dicionário de sessão.
Quando é necessário conectar o estado da sessão com uma solicitação que está sendo processada, o módulo HTTP recupera o ID da sessão (se não for a solicitação inicial) e procura-o no provedor de estado configurado. Se nenhum dado for retornado, o módulo HTTP gera um novo ID de sessão para a solicitação. Isso pode ser facilmente testado com a seguinte página:
<%@ Page Language="C#" Trace="true" %>;
</html>;
<corpo>;
<form runat="servidor">;
<asp:button runat="servidor" text="Click" />;
</formulário>;
</corpo>;
</html>;
Sempre que você clicar no botão e retornar à página, um novo ID de sessão será gerado e as informações de rastreamento serão registradas.
Figura 3: Em uma aplicação que não armazena dados em um dicionário de sessão, um novo ID de sessão é gerado para cada solicitação.
E o evento Session_OnStart? O evento também será gerado para cada solicitação? Se seu aplicativo definir um manipulador Session_OnStart, o estado da sessão será sempre salvo, mesmo que o estado da sessão esteja vazio. Portanto, o ID da sessão é sempre constante para todas as solicitações após a primeira solicitação. Use o manipulador Session_OnStart somente quando for absolutamente necessário.
Se uma sessão expirar ou for abandonada, seu ID de sessão não será alterado na próxima vez que o aplicativo sem estado for acessado. Ele foi projetado para que o ID da sessão persista até o final da sessão do navegador, mesmo que o estado da sessão expire. Ou seja, o mesmo ID de sessão é sempre usado para representar múltiplas sessões, desde que a instância do navegador seja a mesma.
O evento Session_OnEnd marca o fim de uma sessão e é usado para executar qualquer código de limpeza necessário para encerrar a sessão. Observe, entretanto, que esse evento só tem suporte no modo InProc, ou seja, somente quando os dados da sessão são armazenados em um processo de trabalho do ASP.NET. Para que o evento Session_OnEnd seja gerado, primeiro deve existir um estado de sessão, o que significa que alguns dados devem ser armazenados no estado de sessão e pelo menos uma solicitação deve ser concluída.
No modo InProc, o estado da sessão adicionado ao cache como itens recebe uma política de tempo de expiração variável. Expiração variável significa que se um item não for utilizado dentro de um determinado período de tempo, ele será excluído. O tempo de expiração de quaisquer solicitações processadas durante este período será redefinido. O intervalo do item de estado da sessão é definido como o tempo limite da sessão. A técnica usada para redefinir o tempo de expiração do estado da sessão é muito simples e intuitiva: o módulo HTTP da sessão simplesmente lê os itens do estado da sessão armazenados no cache do ASP.NET. Se a estrutura interna do objeto ASP.NET Cache for conhecida, o módulo realizará cálculos para redefinir o tempo de expiração da variável. Portanto, quando o item armazenado em cache expirar, a sessão expirou.
Os itens expirados serão removidos automaticamente do cache. O módulo de sessão de estado também representa uma função de retorno de chamada de exclusão como parte da política de tempo de expiração para este projeto. O cache chamará automaticamente a função delete, que então gerará o evento Session_OnEnd. Se um aplicativo realizar o gerenciamento de sessão por meio de um componente fora do processo, o evento final nunca será gerado.
Sessões sem cookies
Cada sessão ASP.NET ativa é identificada usando uma string de 120 bits que consiste apenas nos caracteres permitidos pela URL. O ID da sessão é gerado usando um provedor criptográfico gerador de números aleatórios (RNG). O provedor de serviços retorna uma sequência de 15 números gerados aleatoriamente (15 bytes x 8 bits = 120 bits). A matriz de números aleatórios é então mapeada para caracteres de URL válidos e retornada como uma string.
A string do ID da sessão é enviada ao navegador e retornada ao aplicativo do servidor de duas maneiras: usando um cookie (como no ASP tradicional) ou uma URL modificada. Por padrão, o módulo de estado da sessão criará um cookie HTTP no lado do cliente, mas uma URL modificada que incorpore a string do ID da sessão pode ser usada (especialmente para navegadores que não suportam cookies). O método usado depende das definições de configuração armazenadas no arquivo web.config do aplicativo. Para definir as configurações da sessão, você pode usar a seção <sessionState> e o atributo Cookieless.
<sessionState cookieless="true|false" />;
Por padrão, o atributo Cookieless é falso, indicando que cookies são usados. Na verdade, um cookie é apenas um arquivo de texto colocado no disco rígido do cliente por uma página da Web. No ASP.NET, um cookie é representado por uma instância da classe HttpCookie. Normalmente, um cookie contém um nome, um conjunto de valores e um prazo de validade. Quando o atributo Cookieless é definido como falso, o módulo de estado da sessão criará um cookie chamado ASP.NET_SessionId e armazenará o ID da sessão nele. O pseudocódigo a seguir mostra o processo de criação de um cookie:
HttpCookie sessionCookie;
sessionCookie = new HttpCookie("ASP.NET_SessionId", sessionID);
sessionCookie.Path = "/";
O tempo de expiração do cookie de sessão é muito curto e o tempo de expiração é atualizado após cada solicitação ser bem-sucedida. O atributo Expires do cookie indica o tempo de expiração do cookie no cliente. Se o cookie de sessão não for definido explicitamente, o padrão da propriedade Expires será DateTime.MinValue, que é a menor unidade de tempo permitida pelo .NET Framework.
Para desabilitar cookies de sessão, defina o atributo Cookieless como true no arquivo de configuração da seguinte forma:
<configuration>;
<sistema.web>;
<sessionState Cookieless="true" />;
</system.web>;
</configuration>;
Neste ponto, suponha que você solicite a página na seguinte URL:
http://www.contoso.com/sample.aspxO
conteúdo real exibido na barra de endereço do navegador será diferente e agora contém o ID da sessão. , conforme mostrado a seguir:
http://www.contoso.com/(5ylg0455mrvws1uz5mmaau45)/sample.aspx
Ao instanciar o módulo HTTP de estado de sessão, o módulo verifica o valor do atributo Cookieless. Se verdadeiro, redireciona a solicitação (HTTP 302) para uma URL virtual modificada contendo o ID da sessão imediatamente anterior ao nome da página. Quando a solicitação for processada novamente, o ID da sessão será incluído na solicitação. Se for feita uma solicitação para iniciar uma nova sessão, o módulo HTTP gera um novo ID de sessão e então redireciona a solicitação. Se a solicitação for postada de volta, o ID da sessão já existe porque os postbacks usam URLs relativos.
A desvantagem de usar sessões sem cookies é que o estado da sessão será perdido se uma URL absoluta for chamada. Ao usar cookies, você pode limpar a barra de endereço, ir para outro aplicativo e depois retornar ao aplicativo anterior e recuperar o mesmo valor de sessão. Se você fizer isso enquanto os cookies de sessão estiverem desativados, os dados da sessão serão perdidos. Por exemplo, o código a seguir interromperá a sessão:
<a runat="server" href="/code/page.aspx">
;Click</a>;
altere manualmente o ID da sessão adicionado ao URL. Você pode chamar o método ApplyAppPathModifier na classe HttpResponse.
<a runat="servidor"
href=<% =Response.ApplyAppPathModifier("/code/page.aspx")%>; >;Click</a>;
O método ApplyAppPathModifier usará uma string representando o URL e retornará o URL absoluto incorporando as informações da sessão. Esta técnica é particularmente útil quando, por exemplo, você precisa redirecionar de uma página HTTP para uma página HTTPS.
Resumo
O estado da sessão foi originalmente introduzido no ASP tradicional como uma API baseada em dicionário que permitia aos desenvolvedores armazenar dados personalizados durante uma sessão. No ASP.NET, o estado da sessão oferece suporte a dois recursos principais: armazenamento e transferência de ID de sessão sem cookies e provedores de estado onde os dados da sessão são realmente armazenados. Para implementar esses dois novos recursos, o ASP.NET aproveita o módulo HTTP para controlar a ligação entre o estado da sessão e o contexto da solicitação que está sendo processada.
No ASP tradicional, usar o estado da sessão significa usar cookies. Este não é mais o caso no ASP.NET, pois uma arquitetura sem cookies pode ser usada. Com o poder do módulo HTTP, o URL solicitado pode ser decomposto para conter o ID da sessão e então redirecionado. Em seguida, o módulo HTTP extrai o ID da sessão da URL e o utiliza para recuperar qualquer estado armazenado.
O estado físico de uma sessão pode ser armazenado em três locais: memória em processo, memória fora de processo e tabelas do SQL Server. Os dados devem ser serializados/desserializados antes de poderem ser usados pelo aplicativo. O módulo HTTP copia o valor da sessão do provedor para a memória do aplicativo no início da solicitação. Após a conclusão da solicitação, o status modificado é retornado ao provedor. Essa comunicação de dados terá graus variados de efeitos adversos no desempenho, mas aumentará bastante a confiabilidade e a estabilidade e fará suporte para arquiteturas da fazenda e do jardim da web mais fáceis de implementar.