views:

52

answers:

2

I have an ASP.NET application that needs to remember some info about a user (and what company they are from) across pages, within a session.

I imagine this is a requirement of just about any ASP.NET application of a certain size. I've used a few different approaches over the years.

In the past, I've passed around an id in querystring parameters like so:

site.com/page.aspx?usrid=1&companyid=2

and then instantiated the object on each page (from the database).

Another common way of doing it is storing my objects in session variables:

Session["User"] = currentUser;              // store at login
User currentUser = (User)Session["User"];   // retrieve on some other page

which saves a trip to the DB, but I worry about memory used if the User object is complex and the site has many concurrent users.

I have recently inherited an application that uses public properties on the master page, like this:

Master.theUser = currentUser;         // store at login
User currentUser = Master.theUser;    // retrieve on some other page

This saves the cast, and looks more readable to me I think, but I don't know if it's better or worse performance-wise. It also has some logic in the getter where if the private value is null, it tries to get it from the Session variable, though I'm not sure if that's never used (or used every get!?) or what.

My latest idea is to use my page class. I have a custom page class derived from the standard System.Web.UI.Page base class. It includes objects like CurrentUser as public properties. This seems to work OK. I like it even better.

But I really don't know what's going on under the covers. Can anyone give an opinion on which approach is better and why?

Alternative suggestions for doing this are also welcome.

Update: I've done some checking use trace.axd and Trace.Write and it looks like neither the masterpage version nor the custom page class version "remember" the values between pages. The "get" methods have a line of code that checks if the User property is null, and if so, reads it from the session variable. This happens when a page accesses the property (Master.User or the derived class's this.User) for the first time on a given page, then subsequent requests can get the value (without going to the session variable).

So thus far the best solution looks something like this:

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;
    }
}

}

Then on any webpage.aspx.cs, you can do something like this:

UsernameTextBox.Text = User.FullName;

any more improvements?

A: 

I agree with you latest idea. Have the common page base class expose a public property of type your user. The property should read/write from/to a session key. We also have another property called GoBackPage that stores the URL of the previous page in view-state of the current page.

    public string GoBackPage
    {
        get
        {
            return this.ViewState["__PrevPage"].ToString();
        }

        set
        {
            this.ViewState["__PrevPage"] = value;
        }
    }

You can still go beyond this and store only the UserId in view-state and expose a property in the common page-base class that will read the UserId from the view-state and return the User Object.

this. __curious_geek
Storing the UserId in ViewState won't persist it across pages. It will only be available in postbacks on that one page (even if it's in the base class).
dave thieben
I would not store user information in view state:1) Using ViewState increases the amount of data that has to be returned to you client.2) since view state is client side and insecure, you can encrypt view state but that would be a huge performance hit as well.Using session is the way to go!
Anthony
+1  A: 

Session was designed for exactly this purpose. It stores pertinent data for the lifetime of the "session" of the user, which I think is 20 minutes or the user closes the browser. If you are concerned about the size of your User object, you can just store the ID, and then retrieve the object from the DB, but you have to weigh the tradeoff of the DB roundtrip. I don't think it's usually concern with Session, however, because it's not sent to the client like ViewState is. You could also expose this session value with a property like in Curious Geek's example, but use the Session object instead of the ViewState object.

Setting the property on the Master page won't work because that is only a member of the currently instantiated class which gets garbage collected at the end of each request, so you won't have it on the next request.

Here's a summary of state management in ASP.NET: http://msdn.microsoft.com/en-us/library/75x4ha6s.aspx

dave thieben