Como persistir ou restaurar informações do Session do ASP.NET quando o pool reinicia automaticamente?
* Coloco aqui porque foi muito complicado de encontrar esta informação, e sou partidário de haver sempre informação simples e direta à disposição.
Duas dicas sobre o objeto Session do ASP.NET.
Em algumas situações a aplicação é reiniciada (pool application), a partir do IIS. Tais situações são em geral quaisquer que mudem parâmetros e que o IIS subentenda que precisa reler configurações para que a aplicação fique correta. Isto é necessário para que o ASP.NET funcione neste modelo de "altere e funciona".
As alterações mais comuns que disparam o restart são: excluir pastas, alterar a lixeira, alterar o global.asax ou o web.config.
No meu caso, desde muito tempo eu criava uma pasta para imagens a partir do aplicativo. Como o usuário e a senha estavam gravados criptografados em Session, o pool era reiniciado, perdia as informações e voltava ao login, e não havia meios de descobrir o porque.
* Dica: criando um arquivo global.asax no seu projeto, você terá como capturar os eventos do aplicativo e do session. Já ajuda bastante.
Desta forma, como não há nem meios, nem motivo para tentar mudar o modo de trabalho do ASP, o meio mais simples é salvar vinculado ao IP e ao ID do session a informação de usuário e senha (em httpcontext.cookies, na hora do logon ok), e recuperar no evento do session_Start do global.asax.
Para que isto funcione, basta que o seu web.config possua a seguinte diretiva:
<sessionState regenerateExpiredSessionId="true"/>
Desta forma o ID da sessão é restaurado entre chamadas de um mesmo browser cliente.
* Global.asax precisa estar na pasta raiz do aplicativo ("/").
Exemplo de como gravar a informação:
Na tela de Logon:
'salva a informação para ser reutilizada caso o pool seja reiniciado
Dim vTemp As HttpCookie = Nothing
vTemp = New HttpCookie("PERFIL-" & Me.Session.SessionID, Me.Session("Perfil"))
vTemp.Expires = DateAdd(DateInterval.Hour, 24, Now)
HttpContext.Current.Response.Cookies.Add(vTemp)
vTemp = New HttpCookie("SENHA-" & Me.Session.SessionID, Me.Session("Senha"))
vTemp.Expires = DateAdd(DateInterval.Hour, 24, Now)
HttpContext.Current.Response.Cookies.Add(vTemp)
Exemplo de como restaurar a informação:
Em Global.asax
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
' Fires when the session is started
'quando vai iniciar a sessão, entre restart e coisa do gênero, força a restaurar a informação para reuso
Dim vTemp As HttpCookie = Nothing
vTemp = HttpContext.Current.Request.Cookies("PERFIL-" & Me.Session.SessionID)
If Not vTemp Is Nothing Then
Me.Session("Perfil") = vTemp.Value
vTemp = HttpContext.Current.Request.Cookies("SENHA-" & Me.Session.SessionID)
If Not vTemp Is Nothing Then
Me.Session("Senha") = vTemp.Value
End If
End If
End Sub
* Dica: não é possível remover cookies diretamente, pois eles estão no cliente e não no servidor. A técnica recomendada pela Microsoft consiste em setar o valor do cookie para "" e então mudar o Expire (data de expiração) para uma data anterior a hoje. Assim ao carregar o próprio browser remover o cookie expirado.