Zip Compressing ASP.NET Session without changing your code using a Session provider.
Scott Hanselman had a post last week to zip your Session state. a great idea I thought to be able to save memory on the computer. Yet I didn’t want to change all my source code to use another class to do so, a nightmare to track all the Sessions in every application, or worse when you don’t have access to that source code.
So last weekend I work on a Session State Provider that allows me to intercept every call to the Session State and compressed when set or unzip when retrieve.
The Session State provider will call my method by adding this to the web.config on your website:
<sessionState cookieless="true" regenerateExpiredSessionId="true" mode="Custom" customProvider="ZipSessionProvider"> <providers> <add name="ZipSessionProvider" type="ZipSession.ZipSessionProvider"/> </providers> </sessionState>
This tells the web application to send all Session request to my class ZipSessionProvider that wraps Scott Hanselman’s class. There are 2 methods that are important on the provider, to set the session and to retrieve. So users don’t have to change the code to use the Sessions on their web applications:
Session["Something"] = "Hello World";
Insert a Session object.
public override void SetAndReleaseItemExclusive (HttpContext context, String id, SessionStateStoreData item, object lockId, bool newItem) { for (int i = 0; i < item.Items.Count; i++) { string sKey = item.Items.Keys[i]; Zip.Session[id + sKey] = item.Items[i]; } }
The system calls the SetAndReleaseItemExclusive to set Session variables. As when you override the Session state, you’ll find you won’t get a Session initialize for you. That’s ok or better, as we’ll use the Cache object to store our session state, more control over that. The method above will store the sessionID as well with the Key for easy retrieve later on.
Retrieve a session object.
public override SessionStateStoreData GetItemExclusive (HttpContext context, String id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { actions = SessionStateActions.None; lockId = null; lockAge = TimeSpan.MaxValue; locked = true; SessionStateStoreData temp = new SessionStateStoreData( new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), 20 ); for (int i = 0; i < Zip.SessionItems.Count; i++) { if (Zip.SessionItems[i].ToString().Contains(id)) { string sKey = Zip.SessionItems[i].ToString().Replace(id, ""); temp.Items[sKey] = Zip.Session[Zip.SessionItems[i].ToString()]; } } return temp; }
Even if we call the SessionStateStoreData we need to provide all the objects and the correct name as well as filtered by Session id.
Modification on Scott’s code.
I had to make 2 modification on Scott’s code, not to fix errors, just to adjusted to my needs.
public class ZipCacheInternal { public object this[string index] { get { return GZipHelpers.DeCompress(HttpContext.Current.Cache[index] as byte[]); } set { HttpContext.Current.Cache[index] = GZipHelpers.Compress((string)value); SessionItems.Add(index); } } }
Instead of be a string indexer I changed it to be able to store any kind of object as well as I keep track of all session on an Array.
Testing the code.
Now we can run the code to test the application, a simple web form with 2 buttons, one to set and the other one to retrieve the session previously set.
protected void Page_Load(object sender, EventArgs e) { if (Page.IsPostBack == false) { Session["Something"] = "Hello World"; Response.Write("Test"); Label1.Text = ""; } } protected void Button1_Click(object sender, EventArgs e) { Label1.Text = Session["Something"].ToString(); } protected void Button2_Click(object sender, EventArgs e) { Session["Something"] = TextBox1.Text; }
Of course I provide you with all the source code and the test application for you to improve my code. There are still a few things I would like to add as well a few things that I didn’t implement in the provider. So expect a few bugs and issues.
Summary
This is the first cut to see how it behaves, I’ll be adding some of the functionality that Scott was talking on his great post. For once, check if compression that object will reduce the bytes, some objects are bigger when compressed.
Hope this helps
Cheers
Al
Posted from http://weblogs.asp.net/albertpascual



Comments
Pradeep Kumar Mishra said on 12.01.2008 at 3:13 AM
I liked your article very much. Will be putting a link to the article url on my webpage. Thanks