我有一个ASP.NET应用程序需要在会话中跨页面记住有关用户(以及他们来自哪家公司)的一些信息。
我认为这是几乎任何特定大小的ASP.NET应用程序的要求。多年来我使用了一些不同的方法。
过去,我在querystring参数中传递了一个id,如下所示:
site.com/page.aspx?usrid=1&companyid=2
然后在每个页面上实例化对象(来自数据库)。
另一种常见的方法是将我的对象存储在会话变量中:
Session["User"] = currentUser; // store at login
User currentUser = (User)Session["User"]; // retrieve on some other page
可以保存到数据库的行程,但是如果User对象很复杂且站点有很多并发用户,我担心会使用内存。
我最近继承了一个在母版页上使用公共属性的应用程序,如下所示:
Master.theUser = currentUser; // store at login
User currentUser = Master.theUser; // retrieve on some other page
这可以节省演员阵容,我认为看起来更具可读性,但我不知道它是否更好或更差。它在getter中也有一些逻辑,如果私有值为null,它会尝试从Session变量中获取它,虽然我不确定它是否从未使用过(或者使用每个获取!? )或者是什么。
我最近的想法是使用我的页面类。我有一个从标准System.Web.UI.Page基类派生的自定义页面类。它包括像CurrentUser这样的对象作为公共属性。这似乎工作正常。我更喜欢它。
但我真的不知道幕后发生了什么。任何人都可以就哪种方法更好以及为什么提出意见?
欢迎这样做的替代建议。
更新 我已经完成了一些使用trace.axd和Trace.Write的检查,看起来主页版本和自定义页面类版本都没有“记住”页面之间的值。 “get”方法有一行代码检查User属性是否为null,如果是,则从会话变量中读取它。当页面在给定页面上第一次访问属性(Master.User或派生类的this.User)时会发生这种情况,然后后续请求可以获取值(不需要转到会话变量)。
答案 0 :(得分:1)
会话就是为了这个目的而设计的。它存储用户“会话”生命周期的相关数据,我认为是20分钟或用户关闭浏览器。如果您担心User对象的大小,您可以只存储ID,然后从DB中检索对象,但您必须权衡数据库往返的权衡。但是,我不认为它通常与Session有关,因为它不像ViewState那样发送给客户端。您还可以使用Curious Geek示例中的属性公开此会话值,但使用Session对象而不是ViewState对象。
在Master页面上设置属性将不起作用,因为它只是当前实例化类的一个成员,它在每个请求结束时收集垃圾,因此您不会在下一个请求中使用它。
以下是ASP.NET中的状态管理摘要: http://msdn.microsoft.com/en-us/library/75x4ha6s.aspx
答案 1 :(得分:0)
我同意你latest
的想法。让公共页面基类公开您的user
类型的公共属性。该属性应该从/向会话密钥读/写。我们还有另一个名为GoBackPage的属性,它将前一页的URL存储在当前页面的视图状态中。
public string GoBackPage
{
get
{
return this.ViewState["__PrevPage"].ToString();
}
set
{
this.ViewState["__PrevPage"] = value;
}
}
你仍然可以超越这个并且只存储处于视图状态的UserId ,并在公共页面基类中公开一个属性,该属性将从视图状态读取UserId并返回用户对象
答案 2 :(得分:0)
到目前为止,最好的解决方案看起来像这样:
public class MyPage : System.Web.UI.Page
{
private User user;
public User User
{
get
{
if (user == null)
{
user = (User)HttpContext.Current.Session["CurrentUser"]; //check if session[CurrentUser] is null here and log them out if so?
}
return user;
}
set
{
user = value;
HttpContext.Current.Session["CurrentUser"] = value;
}
}
}
然后在任何webpage.aspx.cs上,您可以执行以下操作:
UsernameTextBox.Text = User.FullName;
它会在您第一次使用会话时点击会话,但对特定页面响应的后续使用会更快。
各种类和代码隐藏中的代码现在看起来很简洁,因为每次使用它时,我都不需要从Session中读取和转换我的User对象(以及Company对象等)。