我有一个MVC4站点,需要在用户登录时(并且仅在用户登录时)维护一些信息。例如,一旦用户登录,我就会得到一个用户令牌'返回,允许我访问几个异地服务。
我尝试了两种不同的方法。第一种是使用访问用户会话的公共静态类。但是,在阅读静态类之后,我对使用它们犹豫不决。根据我读到的内容,静态类只应该用于只读对象,而我并没有这样使用它。虽然网站站点似乎在用户数量有限的情况下运行良好(目前已经有10个)。
(如果有人想向我解释为什么在MVC4中这是一个坏主意,请告诉我和/或链接到一篇文章)
public class SessionAccessorClasses
{
public const string SessionAccessorSessionVariablesString = "_SessionAccessorSessionVariables";
public static SessionAccessorModel SessionVariables
{
get { return System.Web.HttpContext.Current.Session != null ? (SessionAccessorModel)System.Web.HttpContext.Current.Session[SessionAccessorSessionVariablesString] : null; }
set { System.Web.HttpContext.Current.Session.Add(SessionAccessorSessionVariablesString, value); }
}
}
我的第二种(当前)方法是使用Session变量并使用全局可用类访问它们。
public class SessionAccessorClasses
{
private const string SessionAccessorSessionVariablesString = "_SessionAccessorSessionVariables";
public SessionAccessorModel GetSessionVariables()
{
return System.Web.HttpContext.Current.Session != null ? (SessionAccessorModel)System.Web.HttpContext.Current.Session[SessionAccessorSessionVariablesString] : null;
}
public void SetSessionVariables(SessionAccessorModel value)
{
System.Web.HttpContext.Current.Session.Add(SessionAccessorSessionVariablesString, value);
}
public void ClearSessionVariables()
{
System.Web.HttpContext.Current.Session.Remove(SessionAccessorSessionVariablesString);
}
}
这样做很好,但是我称之为好,因为我不完全理解为什么公共静态类是如此糟糕,因为我现在必须在几乎开始时实例化我的新类每个函数,并在每个函数的末尾调用Set / Update函数;哪个感觉不对劲。
首先,由于我原来的静态类正在访问用户会话,它真的那么糟糕吗?
第二,我的第二课是更合适的做事方式吗?你能建议改进吗?
第三,如果没有别的,你能否给我这样做的积极/消极方面?
答案 0 :(得分:1)
您想使用Session in ASP.net。它是为您描述的目的而创建的。
ASP.NET会话状态使您能够在用户在Web应用程序中导航ASP.NET页面时存储和检索用户的值。 HTTP是无状态协议。这意味着Web服务器将页面的每个HTTP请求视为独立请求。服务器不保留先前请求期间使用的变量值的知识。 ASP.NET会话状态在有限时间窗口内将来自同一浏览器的请求标识为会话,并提供了在该会话期间持久保存变量值的方法。默认情况下,为所有ASP.NET应用程序启用ASP.NET会话状态。
我是强类型可重用会话变量的粉丝,因此我编写了以下扩展来存储您想要创建的任何变量,而无需经常记住magic strings。
public static class SessionExtensions
{
public static bool TryGetValue<T>(this HttpSessionStateBase session, out T value)
where T : class
{
var name = typeof(T).FullName;
value = session[name] as T;
var result = value != null;
return result;
}
public static void SetValue<T>(this HttpSessionStateBase session, T value)
{
var name = typeof(T).FullName;
session[name] = value;
}
public static void RemoveValue<T>(this HttpSessionStateBase session)
{
var name = typeof(T).FullName;
session[name] = null;
}
public static bool ValueExists(this HttpSessionStateBase session, Type objectType)
{
var name = objectType.FullName;
var result = session[name] != null;
return result;
}
}
所以,如果你有一个班级:
public MyClass
{
public int MyInt { get; set; }
}
您可以通过以下方式存储它:
Session.SetValue(MyClass);
需要在用户登录时(并且仅在用户登录时)维护一些信息。
可以通过几种方法更新这些方法以满足此要求。这是一种方式:
public static bool TryGetAuthenticatedValue<T>(this HttpSessionStateBase session,
out T value)
where T : class
{
value = null;
if (HttpContext.Current.User != null
&& HttpContext.Current.User.Identity != null
&& HttpContext.Current.User.IsAuthenticated)
{
var name = typeof(T).FullName;
value = session[name] as T;
}
var result = value != null;
return result;
}
我还建议你在会话中存储的任何类都是可序列化的。也就是说它有一个无参数构造函数并标记为[Serializable]
。