#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
}
Здесь следует учесть несколько моментов:
- Всякий раз, когда веб-приложение или веб-сервер перезапускается, ваши сеансы в процессе будут потеряны. Это означает, что вам нужно сохранить ваш сеанс в базе данных в соответствующий момент.
- Вы можете использовать хранилище сеансов вне процесса (база данных или другой сервер) — в таком случае вы должны пометить свой класс корзины покупок как сериализуемый. Внепроцессные сеансы приводят к снижению производительности. Таким образом, вы уже сохраняете сеанс в базе данных, поэтому, 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
}