So you want to store something in Session? Easy.
Session["MyString"] = "this is a string I'm storing in session."
Then, somewhere else in your application you do:
MyLabel.Text = (string)Session["MyString"];
Maybe "sloppy" is too strong a word. But it certainly isn't slick--for a number of reasons: casting, remembering keys, key typos, overwriting existing keys, etc.
An incrementally better solution might be to use an enumeration or constants for the keys. A step beyond that would be to put all of your Session-related information into a single class and store that in Session.
Let's bump it up a level. Let's take this to 11. Here's a much better way.
Start with a base class you can reuse in any of your ASP.NET applications.
using System; using System.Web; namespace MyNamespace { public class SessionInfo<Subclass> where Subclass : SessionInfo<Subclass>, new() { private static string Key { get { return typeof(SessionInfo<Subclass>).FullName; } } private static Subclass Value { get { return (Subclass) HttpContext.Current.Session[Key]; } set { HttpContext.Current.Session[Key] = value; } } public static Subclass Current { get { var instance = Value; if (instance == null) lock (typeof(Subclass)) // not ideal to lock on a type -- but it'll work { // standard lock double-check instance = Value; if (instance == null) Value = instance = new Subclass(); } return instance; } } } }
Now, create a class specific to your current application.
public class MySessionInfo : SessionInfo<MySessionInfo> { public string SomeString { get; set; } }
To use it in your application, simply do:
// set the value MySessionInfo.Current.SomeString = "this is a string I'm storing in session."; // get the value MyLabel.Text = MySessionInfo.Current.SomeString;
Of course, you can put more than just strings into your subclass. You can create separate subclasses for use in unrelated parts of your application, or you can create a single class (if the design calls for it) to store everything you'll need to have in Session. Perhaps something like:
public class MySessionInfo : SessionInfo<MySessionInfo> { public WebSiteMember WebSiteMember { get; set; } public ShoppingCart ShoppingCart { get; set; } public BrowseHistory BrowseHistory { get; set; } }
Just remember that if you'll be using anything other than in-process session state, you'll have to make your class serializable.
This solution does not work if you want to access the Session value in a declarative fashion as a Select Parameter for a Data Source.
ReplyDelete.. don't be sloppy.
DeleteI think the lock(typeof(Subclass)) should be replaced with lock(Session.SyncRoot).
ReplyDeleteThen you'll only be blocking that Session rather than any thread that happens to be doing anything with the Subclass type.
what if you need to store 2 instances of the same type? for instance, a start date and end date for a selection.
ReplyDeleteDan, not a problem. Just create a subclass with the two properties needed: StartDate and EndDate.
ReplyDeleteIsnt this over architecting
ReplyDeleteNice design but the code where it will be used will not be unit testable in pure isolation.
ReplyDelete