由于 Web 的无状态特性,会话也是一种非常有用的方法,可以通过序列化对象并将它们存储在会话中来跨请求持久化对象。
一个完美的用例可能是,如果您需要在整个应用程序中访问常规信息,以便在每个请求上保存额外的数据库调用,这些数据可以存储在一个对象中并在每个请求上反序列化,如下所示:
我们的可重用、可序列化对象:
[Serializable]
public class UserProfileSessionData
{
public int UserId { get; set; }
public string EmailAddress { get; set; }
public string FullName { get; set; }
}
用例:
public class LoginController : Controller {
[HttpPost]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
var profileData = new UserProfileSessionData {
UserId = model.UserId,
EmailAddress = model.EmailAddress,
FullName = model.FullName
}
this.Session["UserProfile"] = profileData;
}
}
public ActionResult LoggedInStatusMessage()
{
var profileData = this.Session["UserProfile"] as UserProfileSessionData;
/* From here you could output profileData.FullName to a view and
save yourself unnecessary database calls */
}
}
一旦这个对象被序列化,我们就可以在所有控制器中使用它,而无需再次创建它或查询数据库以获取其中包含的数据。
使用依赖注入注入会话对象
在一个理想的世界中,你会'program to an interface, not implementation'并使用你选择的控制反转容器将你的可序列化会话对象注入你的控制器,就像这样(这个例子使用了我最熟悉的结构映射) .
public class WebsiteRegistry : Registry
{
public WebsiteRegistry()
{
this.For<IUserProfileSessionData>().HybridHttpOrThreadLocalScoped().Use(() => GetUserProfileFromSession());
}
public static IUserProfileSessionData GetUserProfileFromSession()
{
var session = HttpContext.Current.Session;
if (session["UserProfile"] != null)
{
return session["UserProfile"] as IUserProfileSessionData;
}
/* Create new empty session object */
session["UserProfile"] = new UserProfileSessionData();
return session["UserProfile"] as IUserProfileSessionData;
}
}
然后您将在您的 Global.asax.cs 文件中注册它。
对于不熟悉注入会话对象的人,您可以找到关于主题here 的更深入的博客文章。
一句警告:
值得注意的是,会话应保持在最低限度,大型会话可能会开始导致性能问题。
还建议不要在其中存储任何敏感数据(密码等)。