A number of things can cause session state to mysteriously disappear.
- Your sessionState timeout has expired
- You update your web.config or other file type that causes your AppDomain to recycle
- Your AppPool in IIS recycles
- You update your site with a lot of files, and ASP.NET proactively destroys your AppDomain to recompile and preserve memory.
If you are using IIS 7 or 7.5, here are a few things to look for:
- By default, IIS sets AppPools to turn themselves off after a period of inactivity.
- By default, IIS sets AppPools to recycle every 1740 minutes (obviously depending on your root configuration, but that’s the default)
- In IIS, check out the “Advanced Settings” of your AppPool. In there is a property called “Idle Time-out”. Set that to zero or to a higher number than the default (20).
- In IIS, check the “Recycling” settings of your AppPool. Here you can enable or disable your AppPool from recycling. The 2nd page of the wizard is a way to log to the Event Log each type of AppPool shut down.
If you are using IIS 6, the same settings apply (for the most part but with different ways of getting to them), however getting them to log the recycles is more of a pain. Here is a link to a way to get IIS 6 to log AppPool recycle events:
If you are updating files on your web app, you should expect all session to be lost. That’s just the nature of the beast. However, you might not expect it to happen multiple times. If you update 15 or more files (aspx, dll, etc), there is a likelyhood that you will have multiple restarts over a period of time as these pages are recompiled by users accessing the site. See these two links:
Setting the numCompilesBeforeAppRestart to a higher number (or manually bouncing your AppPool) will eliminate this issue.
You can always handle Application_SessionStart and Application_SessionEnd to be notified when a session is created or ended. The HttpSessionState class also has an IsNewSession property you can check on any page request to determine if a new session is created for the active user.
Finally, if it’s possible in your circumstance, I have used the SQL Server session mode with good success. It’s not recommended if you are storing a large amount of data in it (every request loads and saves the full amount of data from SQL Server) and it can be a pain if you are putting custom objects in it (as they have to be serializable), but it has helped me in a shared hosting scenario where I couldn’t configure my AppPool to not recycle couple hours. In my case, I stored limited information and it had no adverse performance effect. Add to this the fact that an existing user will reuse their SessionID by default and my users never noticed the fact that their in-memory Session was dropped by an AppPool recycle because all their state was stored in SQL Server.