显然,典型的WebForms方法不起作用。如何跟踪MVC世界中的用户?
答案 0 :(得分:24)
Session的工作方式与Webforms的工作方式完全相同。如果要存储简单信息,请使用表单身份验证cookie。如果您想存储购物车的内容,可以选择Session。我写了一篇关于using Session with ASP.NET的博客文章:
让我们说我们想在Session中存储一个整数变量。我们将创建Session变量的包装器,使其看起来更好:
首先我们定义接口:
public interface ISessionWrapper
{
int SomeInteger { get; set; }
}
然后我们进行HttpContext实现:
public class HttpContextSessionWrapper : ISessionWrapper
{
private T GetFromSession<T>(string key)
{
return (T) HttpContext.Current.Session[key];
}
private void SetInSession(string key, object value)
{
HttpContext.Current.Session[key] = value;
}
public int SomeInteger
{
get { return GetFromSession<int>("SomeInteger"); }
set { SetInSession("SomeInteger", value); }
}
}
GetFromSession和SetInSession是辅助方法,可以更轻松地在Session中获取和设置数据。 SomeInteger属性使用这些方法。
然后我们定义我们的基本控制器(适用于ASP.NET MVC):
public class BaseController : Controller
{
public ISessionWrapper SessionWrapper { get; set; }
public BaseController()
{
SessionWrapper = new HttpContextSessionWrapper();
}
}
如果你想使用Session outside controller,你只需创建或注入新的HttpContextSessionWrapper()。
您可以在Controller测试中将SessionWrapper替换为ISessionWrapper mock,因此它不再依赖于HttpContext。 Session也更容易使用,因为您调用SessionWrapper.SomeInteger而不是调用(int)Session [“SomeInteger”]。它看起来更好,不是吗?
您可能会想到创建覆盖Session对象的静态类,并且不需要在BaseController中定义任何接口或初始化,但它会失去一些优点,特别是在测试和替换其他实现时。
答案 1 :(得分:2)
以下是我使用的代码,只是上述版本的一些“改进版”:
private T GetFromSessionStruct<T>(string key, T defaultValue = default(T)) where T : struct
{
object obj = HttpContext.Current.Session[key];
if (obj == null)
{
return defaultValue;
}
return (T)obj;
}
private T GetFromSession<T>(string key) where T : class
{
object obj = HttpContext.Current.Session[key];
return (T)obj;
}
private T GetFromSessionOrDefault<T>(string key, T defaultValue = null) where T : class
{
object obj = HttpContext.Current.Session[key];
if (obj == null)
{
return defaultValue ?? default(T);
}
return (T)obj;
}
private void SetInSession<T>(string key, T value)
{
if (value == null)
{
HttpContext.Current.Session.Remove(key);
}
else
{
HttpContext.Current.Session[key] = value;
}
}