c # StateServer mantém sessão entre máquinas
-
10-07-2019 - |
Pergunta
Estou certo de que fiz algumas TOLICE dolorosamente óbvios (s) que eu simplesmente não consigo ver. Estou esperando um de vocês pode me definir reta.
I minha gerenciamento de sessão está funcionando perfeitamente, exceto que se um usuário em uma máquina insere dados, um usuário que inicia uma sessão em outra máquina também irá recuperar a informação de sessão a partir do primeiro. Não tão bom. : (
Eu chamo minhas sessões como esta:
UserInfo userinfo = UserInfo.Session;
Minha classe mgt sessão utiliza o seguinte:
static UserInfo userInfo;
static public UserInfo Session
{
get
{
if (userInfo == null)
{
userInfo = new UserInfo();
userInfo.ResetSessionTime();
}
return userInfo;
}
}
I ler e gravar os dados como este. Eu percebo que eu poderia serializar toda a classe, mas parece muito mais sobrecarga para serializar e desserializar uma classe inteira cada vez que a classe é chamada em oposição a apenas pegar um ou dois itens que eu preciso.
Decimal _latitude;
private String SessionValue(String sKey, String sValue, String sNewValue)
{
String sRetVal = "";
if (sNewValue == null)//not wanting to update anything
{
if (sValue == null)//there is no existing value
{
sRetVal = (String)System.Web.HttpContext.Current.Session[sKey];
}
else
{
sRetVal = sValue;
}
}
else
{
System.Web.HttpContext.Current.Session[sKey] = sNewValue;
sRetVal = sNewValue;
}
return sRetVal;
}
public Decimal Latitude
{
get { return SessionValue("Latitude", _latitude); }
set { _latitude = SessionValue("Latitude", _latitude, value); }
}
Obrigado por sua ajuda
Solução
1) Você está usando estática para o seu UserInfo, o que significa que uma única instância dessa classe é compartilhada entre todos os pedidos que chegam ao seu servidor web.
2) Você está não só armazenar valores na sessão (o que não é compartilhada entre os usuários), mas também em uma variável de instância, que neste caso será compartilhada entre os usuários.
Assim, o valor de _latitude está causando o problema. Uma solução simples é esta:
public class Userinfo
{
public Decimal Latitude
{
get { return System.Web.HttpContext.Current.Session["Latitude"]; }
set { System.Web.HttpContext.Current.Session["Latitude"] = value; }
}
}
A melhor versão mais testável seria:
public class UserInfo
{
private HttpSessionStateWrapper _session;
public UserInfo(HttpSessionStateWrapper session)
(
// throw if null etc
_session = session;
)
public Decimal Latitude
{
get { return _session["Latitude"]; }
set { _session["Latitude"] = value; }
}
}
Na segunda instância, dentro de um pedido que você acabou de construir uma nova instância do HttpSessionStateWrapper (usando o atual Session) e passá-lo para a instância UserInfo. Quando você testar, você pode simplesmente passar em um Wrapper simulada.
Não importa o que, a instância UserInfo não deve ser compartilhado entre sessões e deve escrever e ler directamente a partir da sessão. Não tente coisas otimizar prematuramente, mantendo versões locais de seus valores de sessão. Você não está salvando qualquer momento e você está apenas abrindo-se a bugs.
Outras dicas
Isso acontece porque você armazenar suas informações de usuário em um campo estático. casos estáticos são compartilhados entre todos os pedidos, e vive a vida inteira de sua aplicação.
Em outras palavras, todos os seus usuários receberão a mesma instância UserInfo de UserInfo.Session.
Para corrigir isso, você pode:
- Serialize toda a classe em sessão. Eu não sei que outras propriedades que você tem, mas eu acho que não seria muito de uma sobrecarga.
- Criar uma instância de UserInfo por solicitação, de modo que o usuário sempre lê a partir de uma nova instância, que por sua vez irá atualizar seus valores de sessão.