To follow on from what others have said. I tend to have two layers:
The core layer. This is within a DLL that is added to nearly all web app projects. In this I have a SessionVars class which does the grunt work for Session state getters/setters. It contains code like the following:
public class SessionVar
{
static HttpSessionState Session
{
get
{
if (HttpContext.Current == null)
throw new ApplicationException("No Http Context, No Session to Get!");
return HttpContext.Current.Session;
}
}
public static T Get<T>(string key)
{
if (Session[key] == null)
return default(T);
else
return (T)Session[key];
}
public static void Set<T>(string key, T value)
{
Session[key] = value;
}
}
Note the generics for getting any type.
I then also add Getters/Setters for specific types, especially string since I often prefer to work with string.Empty rather than null for variables presented to Users.
e.g:
public static string GetString(string key)
{
string s = Get<string>(key);
return s == null ? string.Empty : s;
}
public static void SetString(string key, string value)
{
Set<string>(key, value);
}
And so on...
I then create wrappers to abstract that away and bring it up to the application model. For example, if we have customer details:
public class CustomerInfo
{
public string Name
{
get
{
return SessionVar.GetString("CustomerInfo_Name");
}
set
{
SessionVar.SetString("CustomerInfo_Name", value);
}
}
}
You get the idea right? :)
NOTE: Just had a thought when adding a comment to the accepted answer. Always ensure objects are serializable when storing them in Session when using a state server. It can be all too easy to try and save an object using the generics when on web farm and it go boom. I deploy on a web farm at work so added checks to my code in the core layer to see if the object is serializable, another benefit of encapsulating the Session Getters and Setters :)