home | articles | site map | contacts
about us
consulting
client login
support
contacts



  Preventing Session Timeouts in C# ASP .NET
Primary Objects C# .NET RSS Feed More C# ASP .NET
Articles by Primary Objects
enter email address
 

Introduction

C# ASP .NET has a setting in the web.config file which allows selecting the desired session timeout. When the session timeout value expires, the currently logged in user's session is deleted and the user is directed back to the login page. The default timeout value usually hovers around 20 minutes for ASP .NET's session timeout. While this is the expected behavior, often clients may require the session timeout to be increased dramatically or even avoid any timeout at all while the user is logged in.

This article describes a solution for web applications which require a session to never timeout or for those who have a session timeout occurring before the value set in the web.config. The solution is invisible and seamless and has been tested in Internet Explorer, Firefox, and Safari.

 
Preventing C# ASP .NET Session Timeouts

Why Would a Client Want No Session Timeout?

A typical scenerio where a user may want to remain permanently logged in until specifically logging out could include a phone technical support operator. The operator logs into a web application to begin taking calls and modifying data. A phone call could last over an hour, with the operator modifying data in between on a single page, and a session timeout at this point could result in a loss of data for the operator. To resolve this, the client may specify to increase the session timeout to several hours. Certainly, the operator would finish a call within a few hours before a page refresh.

Sliding Expiration is Key

It's important to note a key property about session in ASP .NET web applications and IIS, regarding sliding expiration. If sliding expiration is enabled (which it is by default in Visual Studio), the moment a postback occurs within your C# ASP .NET web application, the session timeout counter is refreshed. This means that as long as the user is navigating pages or utilizing controls which issue a postback, the session will remain active. The session timeout problem occurs, such as in the example above, when a user remains on a single page for too long, such as a data-entry page, before clicking the save button.

Increasing the Session Timeout Doesn't Always Work

At first glance, increasing the session timeout value in C# ASP .NET's web.config file should resolve the issue. You would assume that by changing the timeout value to 60 minutes in the line below, that a user would remain logged into a web application session for a full 60 minutes.

    <authentication mode="Forms">
      <forms name="MyAuth" timeout="60" protection="All" loginUrl="~/Web/Login.aspx" slidingExpiration="true" />
    </authentication>

    <sessionState mode="InProc" cookieless="false" timeout="60" />

However, there are actually two problems with this. The first problem is that setting the timeout value to anything greater than 1 hour will result in excessive memory being held on the server, as IIS holds all session memory for the duration of the session. Imagine a timeout value of 5 hours on a high traffic site, holding all session data for thousands of user sessions. The second problem may come upon testing the application, where often the web application will timeout after only 15 minutes. What exactly is happening? While the problem may actually be a value configured in IIS for the session timeout or connection timeout properties (which in the case of shared hosting, you may not even have access to), it becomes apparent we need to take control of the session timeout into our own hands.

Asking the User to Refresh

Offhand, the most obvious solution would be to ask the user to refresh their web browser at least every 15 minutes if they plan to remain on a single page that long. This is a poor solution for obvious reasons. However, what if we could come up with a method to automatically refresh the page behind the scenes, effectively creating a postback.

The Solution - Meta Refresh and Postback

To resolve this issue, we'll need to automatically refresh a web page in the application in order to create a postback. This can be done with a meta-refresh tag. Of course, to keep the web page from refreshing constantly, we'll place the refresh inside a tiny IFRAME. The IFRAME itself, will run on the server and change a querystring parameter to avoid any browser caching of the page. This ensures the page is always loaded upon refresh.

Start by adding the following tag to your master page:

<IFRAME ID="KeepAliveFrame" src="KeepSessionAlive.aspx" frameBorder="0" width="0" height="0" runat="server"></IFRAME>

Next, create a new page named KeepSessionAlive.aspx. In the head section of the page, add the following lines:

<meta id="MetaRefresh" http-equiv="refresh" content="21600;url=KeepSessionAlive.aspx" runat="server" />

<script language="javascript">
   window.status = "<%=WindowStatusText%>";
</script>

The key to this line is the content value. By default, we set the value to 21600 seconds, which is equal to 6 hours. However, we will be setting the value ourselves in the Page_Load of the web application for this page, so this default value can be ignored.

Add the following code to the Page_Load of KeepSessionAlive.aspx.cs:

        protected string WindowStatusText = "";

        protected void Page_Load(object sender, EventArgs e)
        {
            if (User.Identity.IsAuthenticated)
            {
                // Refresh this page 60 seconds before session timeout, effectively resetting the session timeout counter.
                MetaRefresh.Attributes["content"] = Convert.ToString((Session.Timeout * 60) - 60) + ";url=KeepSessionAlive.aspx?q=" + DateTime.Now.Ticks;

                WindowStatusText = "Last refresh " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString();
            }
        }

It's important to note that we include a random querystring parameter on the end of the target url to refresh to. Without this parameter, many web browsers would cache KeepSessionAlive.aspx and never send us the full postback. The random parameter keeps the web browser issuing a full postback, which keeps our session alive. The auto-refresh will actually occur 1 minute before the session is due to expire.

The final important step is to change your web.config session timeout value to be a value less than that of IIS's possible timeout values. If your value is greater than IIS's, your auto-refresh will never occur since IIS would have already reset your session state before the refresh timer activates. Choosing a value such as 10 minutes appears to work well. Remember, even though the session timeout value is 10 minutes, your auto-refresh method combined with sliding expiration, will keep the session alive. Alternate solutions include setting the web.config timeout values to 20 or 30 minutes and setting the meta-refresh value to 5 minutes.

    <authentication mode="Forms">
      <forms name="MyAuth" timeout="10" protection="All" loginUrl="~/Web/Login.aspx" slidingExpiration="true" />
    </authentication>

    <sessionState mode="InProc" cookieless="false" timeout="10" />

Testing the Results and Advantages

After making the changes as shown above, log into your web application to establish a session and try sitting on the same page for 20 minutes or longer. You should be able to verify that the session remains alive and active, long after 10 minutes, without being booted back to the login page.

This method actually has two added advantages over the standard web.config session timeout value. The first advantage is that you can keep a session permanently active - as long as the user's web browser is open, the session will not be logged out. The second advantage is that as soon as the user closes the web browser, a session timeout will occur after only 10 minutes, quickly freeing up the server memory (rather than holding onto the session memory for 20,30,60 minutes or longer before cleanup).

Don't Forget About Security

It's important to note there are security implications to keeping a user's session permanently active on a single page (until the web browser is closed). Particularlly, if the user walks away from his desk, there is a chance for an attacker to jump right into the web application and gain access. Without a session timeout, the web page would remain open. However, if the PC has its own locked-PC timeout (ie. screensaver), it may help alleviate this issue. In either case, security should always be considered when making session timeout changes.

 

Conclusion

Session timeouts in C# ASP .NET can be unpredictable and often rely not only on the web.config session timeout value, but also on various timeout values within IIS, the server, and the cookie. By taking advantage of the sliding expiration feature of ASP .NET, we can control the session timeout to our specific needs, providing a seamless experience for the user and preventing session timeouts completely in a memory efficent manner.

About the Author

This article was written by Kory Becker, founder and chief developer of Primary Objects, a software and web application development company. You can contact Primary Objects regarding your software development needs at http://www.primaryobjects.com

  Post comment >
        
DateUserComment
2/14/2008Wellwisher _fcksavedurl in IFRAME tag? What's it about? ;)
src is quite enough...


1/16/2009MiNiX Great! Thank you very much for this very useful hint!



1/18/2009diseOne Thank you!! This was useful and I'm now using it for a couple of my applications.


1/22/2009Ankita Great idea!!!

1/28/2009Ameen Mirza Beautiful and great article solved many problems

2/16/2009hi5 I am looking to increase the session timeout for a particular user.

it can be done in codebehind using
user.isinrole("SomeRolel")
{
Session.timeout=5
}

Thanks

Can you please let me know what can be tha disadvantage witht his??


3/24/2009Jack it is really useful for my project. All pages need to force expiry in 60 minutes, except two pages need to extend (never expired).
because that two page is using for worker entry call log and there is global configration set session timeout=60, I believe this aricle is the way that I am looking for.
Thank you very much!


4/2/2009Prabu Still i am getting the Session Time out. after 20 mins the
session was expired. i need session values 1 to 2 hrs. Help me


4/2/2009K Try making the refresh happen sooner, by using division instead of subtracting 60:

MetaRefresh.Attributes["content"] = Convert.ToString((Session.Timeout * 60) / 2) + ";url=KeepSessionAlive.aspx?q=" + DateTime.Now.Ticks;


5/26/2009arun kumar Good one, Thanks

6/16/2009Dhanya Good one.But i am finding a problem while using the same.
The font size of the page after refresh has increased


8/25/2009Pranav asdasdasd

9/10/2009K If you're using KeepSessionAlive.aspx in a site with sub-folders, you'll need to add the following to your Global.asax.cs file in order to make sure the page can always be found:

            protected void Application_BeginRequest(object sender, EventArgs e)
            {
                  // If the request is for KeepSessionAlive.aspx and it's coming from a sub-folder (such as /sub/admin/KeepSessionAlive.aspx, not /KeepSessionAlive.aspx) then redirect to proper location.
                  if (Request.Url.LocalPath.IndexOf("/KeepSessionAlive.aspx") > 0)
                  {
                        Response.Redirect("~/KeepSessionAlive.aspx");
                  }
            }


9/12/2009Midax Tks.. very good idea...

10/19/2009ghhj fgygh

11/5/2009Spacehamster The previous developer of the application that I'm working on used the "Prompt user to refresh" strategy.
I've succssfully implemented your solution, and I find it's much more elegant and subtle.
I think the client is going to be very happy with this approach, as it requires no intervention on their part.

Thanks!


11/12/2009Brotherman Very nice thinking outside the box.   Easy to run, very efficient utilization of server resources.

11/16/2009Srini Thanks for your solution.Works like a breeze!!!!

12/10/2009needhelp... hi, error encounter while i tried to apply tis useful tool.

anyone can help me to look at it?
my testing app:

http://www.compass2u.com/KeepSessionAlive.zip

pls reply to ahman1208@yahoo.com if u wish to...

hundred thx to all of u...


12/16/2009piter hi. i using it with port 8000
example:
http://www.test:8000/webtest/test.aspx
Session Timeouts

remove port 8000
http://www.test/webtest/test.aspx
run true

what ?


12/30/2009Samir great idea - thanks for this.

12/30/2009A.Y Very nice and eye opener! Thank you.

12/30/2009A.Y Here is code in VB:

            If User.Identity.IsAuthenticated Then
                  ' Refresh this page 60 seconds before session timeout, effectively resetting the session timeout counter.
                  MetaRefresh.Attributes("content") = (Convert.ToString((Session.Timeout * 60) - 60) & ";url=KeepSessionAlive.aspx?q=") & DateTime.Now.Ticks.ToString

                  WindowStatusText = ("Last refresh " & DateTime.Now.ToShortDateString() & " ") + DateTime.Now.ToShortTimeString()
            End If



3/3/2010oraclevoid Thanks! this will really solve our issue!! ^^V,,

Profile
Learn more about Primary Objects and our goals ..  More
12/22/2009
Primary Objects releases Linquify for .NET developers, LINQ to SQL library .. More
10/05/09
Primary Objects develops Prospect Tracking Portal for university .. More
Home | About Us | Services | Client Login | Job Opportunities | Contact Us
Copyright © Primary Objects 2009
Privacy Policy
Follow us on Twitter