views:

142

answers:

2

hi,

I have to do the following, when a class is instantiated I need to store that instance by user . Since I'm working in asp.net, I was wondering if I should use some of the ways asp.net provides to persist data between user requests. (Cache cant be because the data needs to be persistent and application state cant be because it needs to be specific to an user) or if I should look a way to store that info inside the class. And it needs to be persisted until I programatically say so

+1  A: 

You have to put it into the Session object, which is automatically managed for you.

ammoQ
#I never used the Session object by calling it from inside a class, can it be done? I'm getting "Session name is not defined"#Should I worry about this? "the Session object is one of the less efficient ways of storing user data, since it is held in memory for some time even after the user has stopped using the application."
Pablo
by the way, the data needs to be persisted until I programatically say so
Pablo
+6  A: 

Session is the perfect place to store specific user data.

Let's assume for this answer, your class that needs to be persisted across a user session is called UserInfo. The first thing is to make sure it is marked as Serializable, so that it can be stored in Session:

/// <summary>
/// My custom class stored per user in Session. Marked as Serializable.
/// </summary>
[Serializable()]
public class UserInfo
{
    public string SimpleProperty
    { get; set;}
}

From code-behind or classes within the ASP.NET application's App_Code folder, you can call session directly:

//creating the user info as needed:
UserInfo currentUserInfo = new UserInfo();

//storing the user info instance:    
Session["UserInfo"] = currentUserInfo;

//getting the user info as needed:
UserInfo currentUserInfo = (UserInfo)Session["UserInfo"];

If in a class library / external assembly that is part of the application, referenced by the ASP.NET website /application, you can access session via HttpContext.Current.Session. Your code otherwise would be very similar:

//creating the user info as needed:
UserInfo currentUserInfo = new UserInfo();

//storing the user info:    
HttpContext.Current.Session["UserInfo"] = currentUserInfo;

//getting the user info as needed:
UserInfo currentUserInfo = (UserInfo)HttpContext.Current.Session["UserInfo"];

When coding your class library, it's recommended to ensure HttpContext.Current is not null prior to trying to access it and Session, as under certain circumstances it could be null.

All of the above should meet your needs. Session by design is scoped at the user/session level so you can use the same Session key in your code. No other special requirements are needed to protect the class instance from other users/sessions. The Cache object you mentioned is not the right way to go, as it is application wide, and would require you to implement your own user-level scope to ensure UserInfo instances aren't accidentally shared across different sessions.

One last suggestion - you could even create a static utility/helper class which would access this information as needed, so that your code would not continually have to deal with the Session object. Quick example:

public static class UserInfoManager
{
    /// <summary>
    /// Gets or sets the session-scoped user info when needed.
    /// </summary>
    public static UserInfo UserInformation
    {
        get
        {
            if(HttpContext.Current != null)
                return (UserInfo)HttpContext.Current.Session["UserInfo"];

            return null;
        }
        set
        {
            HttpContext.Current.Session["UserInfo"] = value;
        }
    }
}

Using the above static class, you can now easily access the instance of the class, using UserInfoManager.UserInformation, etc.

I hope this helps.

EDIT:

One further suggestion. In our applications when we have to store a class instance per user like you do, we create a base Page class, which allows direct access to the class instance via a property. This may also help you keep things well refined:

/// <summary>
/// Base page class, which all pages in our site will inherit from
/// </summary>
public class MyBasePage : System.Web.UI.Page
{
    /// <summary>
    /// Gets or sets the session-scoped user info when needed.
    /// </summary>
    protected UserInfo UserInformation
    {
        get
        {
            if(HttpContext.Current != null)
                return (UserInfo)HttpContext.Current.Session["UserInfo"];

            return null;
        }
        set
        {
            HttpContext.Current.Session["UserInfo"] = value;
        }
    }
}

Then in each code-behind in the asp.net website or web application:

/// <summary>
/// Code-behind class for a page in my site
/// </summary>
public partial class SomePage : MyBasePage 
{
    public void Page_Load(object sender, EventArgs e)
    {
        //access the user info as needed
        this.UserInformation.SimplyProperty = "something";
    }
}

As you can see, very little code is needed now to be able to access the class instance.

KP
TY. It looks like you are going to get the 100 rep. But Im going to wait and see if someone else reply and let the votes decide who gets it :)
Pablo
NP. Sounds fair to me..
KP