Хранение пользовательских объектов в сеансах

#c# #asp.net #session

#c# #asp.net #сеанс

Вопрос:

Каков общий способ хранения пользовательских объектов в сеансах?

Я планирую сохранить свою корзину в сеансе во всем веб-приложении. Когда этот пользователь выйдет из системы, сеанс будет очищен.

 Class ShoppingCart
{
    private List<CartItem> Items = new List<CartItem>();

    public ShoppingCart()
    {
        this.Items = new List<CartItem>();
        if (HttpCurrent.Current["Cart"]!=null])
        {
            this.Items = ShoppingCart.loadCart(HttpCurrent.Current["User"]);
        }
    }
}
  

Когда пользователь входит в систему, я помещаю корзину в сеанс, например:

 Session["Cart"] = new ShoppingCart();
  

Но должен ли я писать Session["Cart"] на каждой странице? Нет ли более простого способа сделать это? Также как насчет сеанса гостевой корзины? Где я должен это объявить?

Я хочу, чтобы каждый сеанс пользователя сохранялся в уникальном сеансе, чтобы не было путаницы между гостевым сеансом и сеансом участника.

Ответ №1:

ASP.NET сеанс соответствует сеансу браузера — он не зависит от того, аутентифицирован пользователь (вошел в систему) или нет. Таким образом, у вас не должно возникнуть никаких проблем в отношении сеансов гостя / участника. Я бы посоветовал вам предоставить текущую корзину покупок через статическое свойство accessor — например

 Class ShoppingCart {

    public static ShoppingCart Current
    {
      get 
      {
         var cart = HttpContext.Current.Session["Cart"] as ShoppingCart;
         if (null == cart)
         {
            cart = new ShoppingCart();
            HttpContext.Current.Session["Cart"] = cart;
         }
         return cart;
      }
    }

... // rest of the code

}
  

Здесь следует учесть несколько моментов:

  1. Всякий раз, когда веб-приложение или веб-сервер перезапускается, ваши сеансы в процессе будут потеряны. Это означает, что вам нужно сохранить ваш сеанс в базе данных в соответствующий момент.
  2. Вы можете использовать хранилище сеансов вне процесса (база данных или другой сервер) — в таком случае вы должны пометить свой класс корзины покупок как сериализуемый. Внепроцессные сеансы приводят к снижению производительности. Таким образом, вы уже сохраняете сеанс в базе данных, поэтому, IMO, вам следует использовать сеансы in-proc, убедившись, что грязные сеансы записываются в базу данных как можно скорее.

Комментарии:

1. Вы бы порекомендовали мне сохранить сеанс в базе данных сразу после добавления / удаления товара из корзины?

2. @user478636, это будет зависеть от бизнес-требований. Нормально ли, если пользователь потерял изменения в корзине покупок в случае перезапуска веб-сервера? если да, то вы можете использовать подход, при котором вы будете периодически сохранять корзину покупок, скажем, при выходе из системы и т.д. Если нет, то вы должны сохранять корзину при каждом изменении, что, по-моему, действительно безопасный и лучший вариант.

3. Я знаю, что это устарело, но я только что столкнулся с этим и у меня возник вопрос. Я программист-защитник, и поскольку Session["Cart"] потенциально может быть сохранено где-то еще чем-то, что не является ShoppingCart , было бы безопасно обернуть это вокруг try {} catch() {} ? В try{}catch(){} я устанавливаю значение сеанса на пустое ShoppingCart , а также устанавливаю возвращаемое значение.

4. @RoLYroLLs, оператор c # ‘as’ вернет null, если объект другого типа — так что попробуйте .. поймать, чтобы поймать этот сценарий, не обязательно.

Ответ №2:

Добавьте его на главную страницу или вы могли бы добавить статическое свойство к вашему объекту ShoppingCart

 public static ShoppingCart GetCurrent
{
    get
    {
        if(HTTPContext.Current.Session["CurrentCart"] == null)
        {
            HTTPContext.Current.Session["CurrentCart"] = new ShoppingCart();
        }
        return HTTPContext.Current.Session["CurrentCart"] as ShoppingCart;
    }
}
  

Ответ №3:

Определение универсального метода расширения в статическом классе:

 public static T GetSession<T>(string key) =>  HttpContext.Current?.Session?[key] != null ? (T)HttpContext.Current.Session[key] : default(T);
  

пример использования
неявный

 var myCart = GetSession<ShoppingCart>("myKey");
  

вывод

 ShoppingCart myCart2 = GetSession("myKey");
  

проверьте, существует ли

 if(myCart != default(ShoppingCart)){
    // do stuff
}