哪个是在ASP.NET会话期间存储自定义“用户”对象的最佳位置?

时间:2010-07-06 07:58:56

标签: asp.net master-pages session-state derived-class

我有一个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)时会发生这种情况,然后后续请求可以获取值(不需要转到会话变量)。

3 个答案:

答案 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对象等)。