сервер состояния c # поддерживает сеанс между машинами
-
10-07-2019 - |
Вопрос
Я уверен, что допустил какую-то болезненно очевидную ошибку (ы), которую я просто не могу увидеть.Я надеюсь, что кто-нибудь из вас сможет наставить меня на путь истинный.
I мое управление сеансами работает отлично, за исключением того, что если пользователь на одной машине вводит данные, пользователь, который запускает сеанс на другой машине, также повторно получит информацию о сеансе с первой.Не так уж хорошо.:(
Я называю свои сеансы так:
UserInfo userinfo = UserInfo.Session;
Мой сессионный класс mgt использует это:
static UserInfo userInfo;
static public UserInfo Session
{
get
{
if (userInfo == null)
{
userInfo = new UserInfo();
userInfo.ResetSessionTime();
}
return userInfo;
}
}
Я считываю и записываю данные следующим образом.Я понимаю, что мог бы сериализовать весь класс, но, похоже, гораздо больше накладных расходов на сериализацию и десериализацию всего класса при каждом вызове класса, в отличие от простого захвата одного или двух элементов, которые мне нужны.
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); }
}
Спасибо за вашу помощь
Решение
1) Вы используете статические данные для своей UserInfo, что означает, что один экземпляр этого класса является общим для всех запросов, поступающих на ваш веб-сервер. Р>
2) Вы храните не только значения в сеансе (который не используется пользователями), но также и в переменной экземпляра, которая в этом случае БУДЕТ разделена между пользователями.
Таким образом, значение _latitude вызывает у вас эту проблему. Простое решение:
public class Userinfo
{
public Decimal Latitude
{
get { return System.Web.HttpContext.Current.Session["Latitude"]; }
set { System.Web.HttpContext.Current.Session["Latitude"] = value; }
}
}
Лучшая, более тестируемая версия:
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; }
}
}
Во втором случае в запросе вы просто создаете новый экземпляр HttpSessionStateWrapper (используя текущий сеанс) и передайте его экземпляру UserInfo. Когда вы тестируете, вы можете просто передать имитацию Wrapper. Р>
Независимо от того, что экземпляр UserInfo не должен быть общим для сеансов, он должен записывать и читать непосредственно из сеанса. Не пытайтесь преждевременно оптимизировать вещи, сохраняя локальные версии значений сеанса. Вы не экономите время и просто открываете себя для ошибок.
Другие советы
Это происходит потому, что вы храните информацию о своем пользователе в статическом поле.Статические экземпляры являются общими для всех запросов и существуют в течение всего срока службы вашего приложения.
Другими словами, все ваши пользователи получат один и тот же экземпляр userInfo из userInfo.Session.
Чтобы исправить это, вы могли бы:
- Сериализуйте весь класс в сеанс.Я не знаю, какие еще свойства у вас есть, но я бы предположил, что это не будет слишком большими накладными расходами.
- Создайте экземпляр userInfo для каждого запроса, чтобы пользователь всегда считывал данные из нового экземпляра, который, в свою очередь, обновит свои значения из сеанса.