Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Why you shouldn't use InProc Session State in ASP.NET


:P
On this page:

I see a lot of questions regarding Session state in ASP.NET and invariably the majority of problems are related to the volatility of InProc Session state.

 

InProc Session state in ASP.NET works using an internal memory based list object. Everytime something gets added to the state it gets added to the Session state of this list. Because it is memory based it is fully dependent on the lifetime of the AppDomain that your Web application runs in.

 

You might think, no big deal – my app is stable and it doesn’t restart. But are you sure of that? Seriously, in IIS 6 and with ASP.NET there are lots of things that can restart your current application without you explicitly knowing about it.

 

web.config

The most common scenario is settings in Web.Config. Any change made in web.config causes the AppDomain to unload and the Session state with it. If you change an AppSettings value (if you use that) or if you change a flag like DebugMode for a temporary debug to find that online bug that just won’t repro in your test environment – you will blow away the AppDomain and Session state with it.

 

IIS 6 Application Pool cycling

IIS 6 also includes a number of health checking services. In fact, most ISPs I work with have their IIS 6 Application Pools (which are the host containers in which ISAPI and ASP.NET applications run) set to recycle once a day. Usually these will be at odd hours in the morning but still. If you’re one of the nightowls who likes to buy underwater goggles at 3am in the morning you might just get zinged. I'd be pissed if I spend 10 minutes shopping for items and am in the middle of the checkout process and your session dies just before you click the ‘Do it, do it, do it’ button, and you have to ‘do it’ all over again...

 

West Wind Web Monitoring and Integrity checks

In my own applications that I run I have a West Wind Web Monitoring service that monitors (using our own West Wind Web Monitor software) the 20 or so apps that are running on my server for failures both in the raw HTTP state as well as to the content they are returning. These are varied applications, some ASP.NET, some Fox Web Connection applications and even a couple of ASP apps. My monitor checks all of these and if it detects a failure for more than two check cycles it tries to restart the Web Server. This doesn’t happen very frequently, but even once a month is one too many if Session state is lost as a result of it!

 

Code Updates

Finally, when you update code on your ASP.NET Codebehind assembly (ie. your Web Project’s main assembly)  on the live site, the AppDomain also gets cycled as well! Yup… AppDomains load assemblies dynamically, but once loaded they can never be unloaded, so when the assembly is replaced on the server Asp.NET detects the change and unloads the entire AppDomain. You can change pages without a recycle (because page classes are dynamically compiled and named), but the main precompiled assembly has fixed names for the classes and since you can't load the same class ontop of the existing one the AppDomain must be unloaded.

 

You can try this out with this C# CodeBehind code:

 

public class ApplicationPoolsAndThreads : System.Web.UI.Page

{

      protected System.Web.UI.HtmlControls.HtmlForm Form1;

 

      protected string ApplicationId = "";

      protected int ThreadId = 0;

      protected string DomainId = "";

      protected string ThreadInfo = "";

 

      private void Page_Load(object sender, System.EventArgs e)

      {

            // Put user code to initialize the page here

            this.ApplicationId = ((HowAspNetWorks.Global)

                        HttpContext.Current.ApplicationInstance).ApplicationId ;

            this.ThreadId = AppDomain.GetCurrentThreadId();

 

            this.DomainId = AppDomain.CurrentDomain.FriendlyName;

 

            this.ThreadInfo = "ThreadPool Thread: " + System.Threading.Thread.CurrentThread.IsThreadPoolThread.ToString() +

                                          "<br>Thread Apartment: " + System.Threading.Thread.CurrentThread.ApartmentState.ToString();

 

            bool IsThreadPoolThread = System.Threading.Thread.CurrentThread.IsThreadPoolThread;

 

            // *** Simulate a slow request so we can see multiple

            //     requests side by side.

            System.Threading.Thread.Sleep(3000);

      }

}

 

Add a page that embdeds the field values:

 

<table border="1" cellpadding="5" style="WIDTH: 480px" align="center">

      <tr>

            <td style="WIDTH: 121px"><strong>Application Id: </strong>

            </td>

            <td>

                  <%= this.ApplicationId %>

            </td>

      </tr>

      <tr>

            <td style="WIDTH: 121px"><strong>Thread Id:</strong>

            </td>

            <td>

                  <%= this.ThreadId %>

            </td>

      </tr>

      <tr>

            <td style="WIDTH: 121px"><strong>Domain Id:</strong>

            </td>

            <td>

                  <%= this.DomainId %>

            </td>

      </tr>

      <tr>

            <td style="WIDTH: 121px"><strong>Thread Info:</strong>

            </td>

            <td>

                  <%= this.ThreadInfo %>

            </td>

      </tr>

</table>

 

Run this code (without the debugger attached) a few times and notice the Domain Id stays steady. If you hit from multiple locations you can see multiple threads active etc.

 

Now go make a change in the project so it forces a recompile, and recompile the project and make sure the assembly is updated. Watch the Domain Id, then refresh and you’ll see that once the DLL is updated the AppDomain has been replaced with a new one and your InProc Session state is gone.

 

This particular issue will be addressed in ASP.NET 2.0 with the loony compilation scheme that compiles every page into its own uniquely named assembly rather than one huge codebehind assembly. Not sure if that’s a good or bad thing as it opens up a number of other issues.

 

Can you get away with it? I don’t think so

Anyway, I don’t think that any application that relies on Session state can reasonably ignore all of these points. Yet many people try to run with InProc anyway, either out of ignorance because it is after all the default or because they feel it’s worth the extra performance.

 

InProc state is definitely considerably faster than either the state server or SQL Server State storage. No doubt about it that in process memory usage is faster than anything that has to cross process and possibly machine boundaries (both state and Sql state often run on a separate machine but neither has to).

 

However, I think that it’s really no contest. If you’re using Session state I would assume that the state is fairly vital to your application otherwise you’d stick the information into Cookie or other client carried statebag. So assuming your app relies on session state to keep it running right, how much is that extra performance of InProc Session state worth to you? Enough to piss off even a small number of customers who loose their shopping cart or other tracking mechanism?

 

The alternatives are the ASP.NET Session Server which provides an IP network interface that’s fairly efficient if run on the local machine, and SQL Server State which writes the session state into a SQL Server table which is the slowest of all approaches but also the most reliable and most useful if you need to take statistics on your session interface. You can read more about the mechanisms in this earlier WebLog entry.

 

 

Another alternative is to not rely so much on Session state in the first place. In many of my older applications I didn’t use any Session state at all, instead the application has a current user table that tracks the necessary information in a similar manner. It requires a database too, so in the big scheme of things this is as slow as state too, but in my experience much of the information that ends up in the state is information that the application needs to capture anyway either for logging or often times for the flow of the application. So the round trip to the database would happen anyway. Finding a way to standardize how the data gets persisted into this internal state table (using a business object front end perhaps) can give you the same functionality of Sesison without using a Session mechanism at all…

 

Ultimately it all depends on your application, but for me there’s never been an occasion where InProc session was appropriate as there were always issues that eventually would cause problems for the user in the front end if the Session died.


The Voices of Reason


 

stefan demetz
April 21, 2005

# re: Why you shouldn't use InProc Session State in ASP.NET

in 2.0 you'll be able to write your own SessionProvider

Gabe
April 21, 2005

# re: Why you shouldn't use InProc Session State in ASP.NET

In whole I agree, two points to keep in mind...

1.) If you don't use InProc, any objects you try to store in the session state must be serializable. Many custom business objects do not fall into this category. Independent datatables are another example.

2.) The session server service has been known to be flacky from time to time. Random failures or no-responses, etc. Not surve if SP1 fixed this or not.

Rick Strahl
April 21, 2005

# re: Why you shouldn't use InProc Session State in ASP.NET

Gabe, yes, but you should be using Serializable objects anyway in case at some point you do need to move to an external store (such as if you end up with a Web Farm).

As to the State Service I Blogged that a while back. It seems .NET 1.1 SP1 has fixed the flakiness of the state server.

http://west-wind.com/weblog/posts/1127.aspx

# Re: Why you shouldn't use InProc Session State in ASP.NET

Although if you're storing REALLY important user-specific stuff (such as a shopping cart) you should be using a stable, permanent database object so it will survive not only hard reboots but also session timeouts.

-----------------------------------

Scott Mitchell
mitchell@4guysfromrolla.com
http://ScottOnWriting.NET

Rick Strahl
April 22, 2005

# re: Why you shouldn't use InProc Session State in ASP.NET

Hi Scott, I find in my own work that I don't store much valuable data in the session anyway. Usually it's just an ID, plus a few transactional details that the user has gathered along the way. Items and such for a shopping cart end up in a table. However, the ID's (Temporary Invoice, Customer PK, Customer AddressPk) etc. is held in Session.

In the past (prior to a stateservice in Fox or classic ASP) I used to store all that in tables precisely because of the volatility even though it was much less of an issue than with ASP.NET InProc sessions today. Basically there'd be one User record in the database that captured all this stuff and served the same purpose as Session does now. There was a single Cookie that served as an ID and the ID pointed to this user record. One way or another a state mechanism is needed :-} It's just that using a Session for this is much easier and usually more efficient as well.

But I agree anything that has any value whatsoever and is not transient should always go into a database ASAP.

Bob Archer
April 25, 2005

# re: Why you shouldn't use InProc Session State in ASP.NET

I would recommend a hybrid of session state. In your typed session class (you do have a typed session class right?) you should leverage your personalization provider.

If the session variable is null, then you pull the value from your personalization provider, which is usually persisting data to a SQL Table. Also, everytime a session variable is set, you also persist this setting.

Another plus here is that you can control how a custom type is serialized rather than using the build in serialization which at times can have alot of overhead.

Now you can use the most performant InProc sessions while also backing them up with your database. You only need to go to the database if the session variable is empty or being set/changed.

Of course, on a web farm this could be problematic cause the same user could have sessions on two servers so it won't notice changes. Sticky IP's on your load balancer solves this problem fairly well.

I personally think this is better than storing all sessions to a SQL server using the build in methods.

In 1.x you will have to roll your own personalization storage class but in 2.0 you can use the new personalization stuff that comes in ASP.Net.

BOb

Rick Strahl
April 26, 2005

# re: Why you shouldn't use InProc Session State in ASP.NET

Bob, this isn't really about personalization only. I don't see how what you're doing would be any more efficient than what the Session providers do today.

As I mentioned in many applications storing captured data with a user record that is persistent is a good idea anyway and in that case it's often possible to write any 'operational' data along with the user specific data and wrap all that into a single database access request.

However, the real advantage of a generic Session is that it is so convenient because it is essentially not bound to your application. It's an operational piece.

Using SQL for storing session data is by far the slowest mechanism and for state service I personally wouldn't use that. If I would go the SQL route I'd just as soon build the logic directly into the app...

Bob Archer
April 30, 2005

# re: Why you shouldn't use InProc Session State in ASP.NET

>I don't see how what you're doing would be any more efficient than what the Session providers do today.

Cause you only go to the db when you need to. Other than that you use InProc session data which is by far the most performant session state mechanism. As opposed to going to/from db for everything which also adds serialization overhead all the time.

For example, lets say you need something from Session...

If (Session("Item") == Null)
{
string value = MySession.GetUserValue("Item",UserID)
}
else
{
string value = Session("Item")
}

return value;

So, in the above the value is retrieved from the InProc session, which is the most performant. If the item isnt' in the session due to a time out perhaps then it is retrieved from the user personal info.

Basically, I great a Get/Set for each session item in a session class that does the above.

This also has the benefit of giving you strongly typed session items and itellisense so when you type:

MySession. you get a list of all the public properties. Granted you have to know what you are putting into a session ahead of time, but I think that is only good design.


Rick Strahl's Web Log
September 29, 2006

# ASP.NET State Service disabled again by Automatic Updates - Rick Strahl's Web Log

It seems every month when update times comes around I have to remember to re-enable the ASP.NET State Service which the updates seem to not-so conveniently reset to Manual.

Rick Strahl
October 05, 2006

# ASP.NET Cache and Session State Storage - Rick Strahl

The underlying storage mechanism for Cache and Session objects are pretty important in understanding some limitations you need to look out for.

ce
August 07, 2007

# re: Why you shouldn't use InProc Session State in ASP.NET

Bob,

Where do you get UserID? How is it persisted?

as in
... MySession.GetUserValue("Item",UserID)

Thanks!

mayank
September 01, 2009

# re:my session variable is still alive

i have some trouble in my code. accor i hold a value in session variable on button click event an another button redirect the another page where a label associated with that page to display the value of session data. so when i store the session variable after that recycle the iis (iisreset) than when i m clicking the button to rendering the another page label still showing the value that was holded in session variable object.


why it's happening

ricky
August 15, 2010

# re: Why you shouldn't use InProc Session State in ASP.NET

Hi Guys,
I've developed an application that uses plink. Its a window based application and now im trying to create the same application but in ASP.NET. The problem is I get an error when i try to put the instance of my class to a session. Please help me gurus...plsssssssssssssssssssssss

heres the part of my program.

Dim objSSH As classSSH
objSSH = New classSSH

Dim sHostName As String
Dim sUserName As String
Dim sPassword As String
sHostName = drpHostName.SelectedValue.Trim
sUserName = txtUserName.Text
sPassword = txtPassword.Text

Dim sStatusLogin As String
sStatusLogin = objSSH.sPuttyLogin(sHostName, "D:\plink.exe", Me.txtPassword.Text, Me.txtUserName.Text)
Session("ssh") = objSSH 'This is the line where error starts

the error is: Unable to serialize the session state. In 'StateServer' and 'SQLServer'
mode, ASP.NET will serialize the session state objects, and as a result
non-serializable objects or MarshalByRef objects are not permitted. The same
restriction applies if similar serialization is done by the custom session
state store in 'Custom' mode.

Rick Strahl
August 15, 2010

# re: Why you shouldn't use InProc Session State in ASP.NET

@RICKY - your object isn't serializable if you use non-InProc session state. Inproc session state uses references to reference Session state variables. StateServer or SQL Server session state uses an external store and requires serialization. Make sure any of yoir own objects (and all child objects) are marked serializable. if you have third party classes that aren't marked serializable there's no much you can do other than serializing those objects yourself (ie. copy properties you care about and resetting them on each hit).

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024