NEWS

Wednesday, December 28, 2011

Preventing Session Timeouts in C# ASP .NET


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.

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.
   
   
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:

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


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();
            }
        }

VB.Net:

 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


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");
                  }
            }


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.
   
     
   

   
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.

Reference:http://www.primaryobjects.com/cms/article86.aspx



12 comments:

  1. Heya! I know this is sort of off-topic however I had to ask.

    Does building a well-established blog like yours require a lot of work?
    I am completely new to writing a blog but I do write
    in my journal daily. I'd like to start a blog so I can easily share my experience and views online. Please let me know if you have any kind of suggestions or tips for new aspiring blog owners. Appreciate it!
    Also visit my website - click through the following website page

    ReplyDelete
  2. Pretty! This was a really wonderful post. Thank you for supplying these details.
    Take a look at my page :: clinoptilolite zeolite

    ReplyDelete
  3. You are so interesting! I don't believe I've read anything like that
    before. So good to discover another person with
    genuine thoughts on this subject. Seriously.. many thanks for starting
    this up. This web site is one thing that's needed on the web, someone with a bit of originality!

    Look into my web site; online casino
    My webpage: canadian online casino

    ReplyDelete
  4. You actually make it seem so easy with your presentation but I
    find this matter to be really something that I think I
    would never understand. It seems too complex and very broad for me.

    I'm looking forward for your next post, I'll try to get the hang
    of it!

    my website - Kenny Nordlund

    ReplyDelete
  5. Really when someone doesn't be aware of then its up to other users that they will assist, so here it takes place.

    Here is my website; Spazio-kovan

    ReplyDelete
  6. Greetings! Very useful advice within this post! It is the little changes that will make the
    most important changes. Many thanks for sharing!


    Also visit my blog post ... Arabic Books

    ReplyDelete
  7. Thanks so muсh foг this. I'm a writer coming from Drewvale, Australia and what you've ѕaiԁ hеre
    οn blogger.com cοuldn't be written much better. Going through this information reminds me of my past roomie, Nicole. He constantly kept preaching about this. I will definitely send these ideas to him. I'm ceгtаin hе will haνe a goоd tіme
    гeading thiѕ. I aρprеciate
    yοu for shаring this.

    My ωeb site ... disillusionize

    ReplyDelete
  8. Hello! I'm at work browsing your blog from my new iphone 4! Just wanted to say I love reading through your blog and look forward to all your posts! Carry on the great work!

    Visit my webpage :: nude girl

    ReplyDelete
  9. I'm curious to find out what blog system you are utilizing?
    I'm experiencing some small security problems with my latest blog
    and I'd like to find something more risk-free. Do you have any recommendations?


    Heere is my site ... ohrd.co.kr

    ReplyDelete