ASP.NET MVC中仍然可以使用Session变量,或者对于某些事情(比如购物车)有更好的替代方案吗?

37
我有一个需要在几个页面上访问购物车的情况。在产品页面上创建购物车并添加一些商品,在购物车结账页面上确认帐单地址,在购物车结账后进行最终检查,将购物车添加到数据库并进入付款流程。
我的问题是,传递购物车的最佳方式是什么?
我已经尝试了将购物车从页面传递到回发(postback)并保持所有值不变,但在某些页面上(如账单地址确认页面)这似乎很麻烦,我只想检查账单地址,而不想在页面上填充大量 HiddenFor() 来重新填充购物车。
我在产品到结账页面使用了 TempData[],然后想知道是否最好一直设置 TempData…
您可以使用会话变量吗?
由于某种原因,我读到说使用会话(Session)不是很好的做法,因此提出此问题。
感谢您的指导,如果需要,我可以提供一些代码/更多信息。

最佳答案来自@NightOwl888:“对于购物车,您绝对不应该使用会话状态”。 - Adeem
7个回答

58

在 ASP.NET MVC 中使用会话(sessions)是完全可以的,特别是在您的购物车场景中。

虽然使用会话存在一些缺点,但似乎并不适用于您的情况:

1)会话防止用户在多个浏览器标签页上正确浏览您的网站,一个标签页中所做的更改会反映在所有其他标签页中。 但是对于购物车来说,这正是您需要的。您不需要每个用户拥有几个购物车,对吧?

2)默认情况下,会话不会持久化,如果您正在操作一个 webfarm,您需要将会话保存在数据库中才能被每个节点访问到。 但是您似乎不太可能进行这种扩展,如果您需要进行扩展,会话就不是您最主要的问题。

3)会话需要用户浏览器提供额外的功能(通常是 cookies)。但是现代浏览器都支持 cookies,因此您只需担心非常特殊的浏览器。

与隐藏域相比,会话也具有一些优点:

1)开销更小。只传递一个小的会话 cookie 在你和客户端之间传递,而不是完整的隐藏域集合。

2)编程更简单。您不必确保将隐藏域包含在每个页面中。

3)安全性更高。客户端可以随意更改隐藏域的内容。您不能轻松地通过隐藏域传递敏感信息,需要进行加密处理。会话值存储在服务器上,因此客户端无法访问它们。


11

会话(Sessions)是可以的,但考虑采用亚马逊式系统,即使你没有登录也会分配给你一个识别cookie。这样他们就可以将您的购物篮与识别cookie键入数据库中进行存储。

结果是您避免了因会话超时/服务器应用程序域回收而丢失购物篮的可怕用户体验(使用SQLState会话存储可以减轻后者,我建议使用)。用户可以在几天后回来,他们的购物篮仍然在那里。除非这是一个安全/隐私问题,否则我认为它是更好的解决方案。


10

在ASP.NET MVC应用程序中使用会话(Session)是非常正常的。Steve Sanderson在他的书中提供了一个带有购物车的示例应用程序,其中使用了会话(Session)。代码可以在这里找到


2
+1 - 可以继续使用会话,但需要小心不要像在WebForms中那样过度使用。一个庞大的会话仍然不是一件好事。 - Michael Shimmins
我是指在必要的情况下使用。正如Zurty所解释的那样,我们不应该过度使用它。购物车是使用会话的完美场景之一。 - Muhammad Adeel Zahid

5
我会使用 Session,除非有避免使用它的理由。
例如,我有一个项目需要在后台重复调用 MVC 操作。该操作服务于一个文件,通过网络传输速度很慢。我曾经使用过 Session,但我很快发现了主要的负面影响:IIS 不会同时执行同一用户的调用,而是一个接一个地顺序执行。这对性能产生了巨大的影响,因此我使用了一种替代方法:将 HttpContext.User.Identity 设置为用户名,并将其用作从数据库获取内容的键。但你可能可以将其设置为一些随机的 GUID,用它来替代 Sessions。

4
对于启用了 Session 的 ASP.NET 页面和一般的 MVC 控制器,同一用户的 HTTP 请求由于会话锁定而被同步。然而,在 MVC 3 中,你可以通过使用 SessionState 属性来控制控制器的会话使用特性。例如,如果想要完全禁用控制器上的会话并允许异步调用(例如 AJAX 轮询或文件服务),则应使用 [SessionState(System.Web.SessionState.SessionStateBehavior.Disabled)]。更多信息请参见:http://tech-journals.com/jonow/2011/10/22/the-downsides-of-asp-net-session-state - James McCormack

4

对于购物车,你绝不能使用会话状态。一个良好的方法是使用匿名标识模块来管理cookie。你只需要在web.config中添加一行代码即可。

<system.web>
    <anonymousIdentification enabled="true" />
</system.web>

接下来,在每个请求中,您可以使用Request.AnonymousID属性(返回表示GUID的字符串)在数据库中查找购物车。

public ActionResult ShowCartDetails()
{
    var CartId = new Guid(Request.AnonymousID);

    // Lookup cart...

    return View();
}

这不仅比使用会话状态更高效,而且更简单。
参考:

2

我倾向于使用cookie,将我的购物车序列化为base64字符串,这似乎运作良好。


1
相较于会话变量,这种方法有哪些优势? - Keeno
1
优点:减少服务器存储负担,避免会话超时问题。 缺点:增加了HTTP流量的大小,需要更多的安全检查来防止恶意篡改cookie数据。还要记住,cookie中存储的数据大小是有限制的:http://myownplayground.atspace.com/cookietest.html - James McCormack
@Zootius所说的。我并不是在说你应该这样做,只是提供另一个选择。 - simonlchilds

0
在购物车系统中,添加到购物车的产品非常重要,因此我认为使用会话并不是一个好主意。使用 cookie 和数据库中的临时表是最好的想法之一。我们可以永久存储这些数据,也可以在一定时间后清除。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接