Implementing a Session Timeout Page in ASP.NET
 
Published: 02 Apr 2008
Abstract
In this article, Steve walks through the steps required to implement a Session Logged Out page that users are automatically sent to in their browser when their ASP.NET session expires. He examines each step with the help of detailed explanation supported by relevant source code.
by Steven Smith
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 131082/ 91

Introduction

In many applications, an authenticated user's session expires after a set amount of time, after which the user must log back into the system to continue using the application. Often, the user may begin entering data into a large form, switch to some other more pressing task, then return to complete the form only to find that his session has expired and he has wasted his time. One way to alleviate this user interface annoyance is to automatically redirect the user to a "session expired" page once their session has expired. The user may still lose some work he was in the middle of on the page he was on, but that would have been lost anyway had he tried to submit it while no longer authenticated. At least with this solution, the user immediately knows his session has ended, and he can re-initiate it and continue his work without any loss of time.

Technique

The simplest way to implement a cross-browser session expiration page is to add a META tag to the HTML headers of any pages that require authentication and/or a valid session. The syntax for the META tag, when used for this purpose, is pretty simple. A typical tag would look like this:

<meta http-equiv='refresh' content='60;url=/SessionExpired.aspx' />

The first attribute, http-equiv, must be set to refresh. The META tag supports a number of other options, such as providing information about page authors, keywords, or descriptions, which are beyond the scope of this article (learn more about them here). The second attribute, content, includes two parts which must be separated by a semicolon. The first piece indicates the number of seconds the page should delay before refreshing its content. A page can be made to simply automatically refresh itself by simply adding this:

<meta http-equiv='refresh' content='60' />

However, to complete the requirement for the session expiration page, we need to send the user's browser to a new page, in this case /SessionExpired.aspx which is set with the url= string within the content attribute. It should be pretty obvious that this behavior is really stretching the intended purpose of the <meta> tag, which is why there are so many fields being overloaded into the content attribute. It would have made more sense to have a <refresh delay='60' refreshUrl='http://whatever.com' /> tag, but it is no simple task to add a new tag to the HTML specification and then to get it supported in 1.2 million different versions of user agents. So, plan on the existing overloaded use of the <meta> tag for the foreseeable future.

With just this bit of code, you can start hand-coding session expirations into your ASP.NET pages to your heart's content, but it is hardly a scalable solution. It also does not take advantage of ASP.NET's programmability model at all, and so I do not recommend it. The problem that remains is how to include this meta tag into the appropriate pages (the ones that require a session) without adding it to public pages, and how to set up the delay and destination URL so that they do not need to be hand-edited on every ASPX page. But before we show how to do that, let us design our session expired page, as shown in Figure 1.

Figure 1 - Session Expired Page

The code for this page is pretty trivial, but is included in Listings 1 and 2.

Listing 1 - Session Expired Page

<%@ Page Language="C#" AutoEventWireup="true" 
CodeBehind="SessionExpired.aspx.cs" 
Inherits="SessionExpirePage.SessionExpired"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Session Expired</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <h1>Session Expired</h1>
    <p>
    Your session has expired.  
    Please <a href="Default.aspx">return to the home page</a> 
    and log in again to continue accessing your account.</p>
    </div>
    </form>
</body>
</html>

Listing 2 - Session Expired Page CodeBehind

using System;
namespace SessionExpirePage
{
    public partial class SessionExpired : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Session.Abandon();
        }
    }
}

Of course the code in Listing 1 is extremely simple and you will want to update it to use your site's design, ideally with a Master Page. Note in Listing 2 the call to Session.Abandon(). This is important and ensures that if the client countdown and the server countdown are not quite in sync, the session is terminated when this page is loaded.

There are several ways we could go about including the session expiration META tag on a large number of secured pages. We could write it by hand - not a good idea. We could use an include file (yes, those still exist in ASP.NET) - even worse idea. We could write a custom control and include it by hand. Slightly better, but still requires touching a lot of ASPX files. We could create a base page class or extend one that is already in use. This is actually a promising technique that would work, but is not the one that I will demonstrate. You could easily implement it using a variation of my sample, though. Or you could use an ASP.NET master page. This is the simplest, most elegant solution, in my opinion, and is the one I will demonstrate.

In most applications I have worked with, it is typical to have a separate master page for the secure, admin portion of the site from the public facing area of the site. This technique works best in such situations. Essentially, the application's secure area will share a single master page file, which for this example will be called Secure.Master. Secure.Master will include some UI, but will also include a ContentPlaceHolder in the HTML <head> section that will be used to render the Session Expiration META tag. Then, in the Master page's codebehind, the actual META tag will be constructed from the Session.Timeout set in the site's web.config and the URL that should be used when the session expires (in this case set as a property of the master page, but ideally this would come from a custom configuration section in web.config). The complete code for the master page is shown in Listings 3 and 4.

Listing 3 - Secure.Master

<%@ Master Language="C#" AutoEventWireup="true" 
CodeBehind="Secure.master.cs" 
Inherits="SessionExpirePage.Secure" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server" id="PageHead">
    <title>Secure Page</title>
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h1>
            Your Account [SECURE]</h1>
        <asp:ContentPlaceHolder ID="Main" runat="server">
        </asp:ContentPlaceHolder>
        <p>
            Note: Your session will expire in
            <%=SessionLengthMinutes %>
            minute(s), <%=Session["name"] %> .
        </p>
    </div>
    </form>
</body>
</html>

Listing 4 - Secure.Master CodeBehind

using System;
using System.Web.UI;
 
namespace SessionExpirePage
{
    public partial class Secure : System.Web.UI.MasterPage
    {
        public int SessionLengthMinutes
        {
            get { return Session.Timeout; }
        }
        public string SessionExpireDestinationUrl
        {
            get { return "/SessionExpired.aspx"; }
        }
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.PageHead.Controls.Add(new LiteralControl(
                String.Format("<meta http-equiv='refresh' content='{0};url={1}'>", 
                SessionLengthMinutes*60, SessionExpireDestinationUrl)));
        }
    }
}

The important work is all done within the OnPreRender event handler, which adds the <meta> tag to the page using String.Format. One important thing to note about this approach is that it follows DRY (Don't Repeat Yourself) by keeping the actual session timeout period defined in only one place. If you were to hardcode your session timeouts in your META tags, and later the application's session timeout changed, you would need to update the META tags everywhere they were specified (and if you did not, you would not get a compiler error, just a site that did not work as expected). Setting the session timeout is easily done within web.config and completes this example. The relevant code is shown in Listing 5.

Listing 5 - Set Session Timeout in web.config

<system.web>
  <sessionState timeout="1" mode="InProc" />
</system.web>
Considerations

One thing to keep in mind with this approach is that it will start counting from the moment the page is first sent to the browser. If the user interacts with that page without loading a new page, such as adding data or even working with the server through AJAX callbacks or UpdatePanels, the session expiration page redirect will still occur when the session would have timed out after the initial page load. In practice, this is not an issue for most pages since if a user is going to work with the page they will do so soon after it first loads, and if they do not use it for some time, they will return to find the Session Expired page and will re-authenticate.  However, if your site makes heavy use of AJAX (or Silverlight or any other client-centric technology), you may need to consider another (more complex) approach, such as using an AJAX Timer for this purpose.

Downloads

Summary

Providing users with a clear indication that their session has expired within the browser, rather than waiting for them to hit the server, can greatly improve the user experience. This technique demonstrates a fairly simple and robust way to achieve this with a minimum of code and, more importantly, with minimal repetition of code. Adding this to an existing site that limits session length should take less than an hour, and your users will thank you.



User Comments

Title: Mr   
Name: Lunchbox
Date: 2012-09-20 5:30:43 PM
Comment:
This approach works perfectly for me, thanks, your examples is complete and helped a lot!
Title: Mr.   
Name: chandrabhan singh
Date: 2011-02-09 6:56:32 AM
Comment:
Hi,

I have a wired scenario in one of my ASP.net application.

I am using ASP.net membership with my custom "roleManager",

and having below tag in web.config to restrict any user not having role of "Keywords"(roles) to access "Keywords"(path) folder

location path="Keywords"

system.web

authorization

allow roles="Keywords"

deny users="*"

authorization

system.web

location

If any user with some other role allow to assess this URL (Keywords in this case) will be redirected to a custom- Access denied page.

Now things working fine but when I left my application with a inactivity of 30 min I am not able to visit the "Keywords", all the time I end up with the custom- Access denied page, if I close the browser, login again it start working fine.

Please help me in this case.

Thanks in advance
Title: Css breaks with header runat server   
Name: san
Date: 2010-10-27 6:58:05 AM
Comment:
I am facing one issue using your example. when on the master page, i give runat=server attribute to head tag, other css and javascript tags added in the same section fail to load. The css of the project breaks,and when i remove this attribute, it is loaded correctly.How to solve this problem?
Title: Mr.   
Name: Raja
Date: 2010-06-09 6:10:52 AM
Comment:
I am getting the following error when run this program.
Parser Error Message: Could not load type 'SessionExpirePage.SessionExpired'.
Title: Nice code   
Name: Mike
Date: 2010-03-24 10:37:05 AM
Comment:
Thanks for putting this together. Very simple and effective.
Title: Session Timed Out.   
Name: Mohandas
Date: 2010-03-05 4:53:16 AM
Comment:
Every Time i access my web page. Session times out. I dont know what is thereason but I used the same session many times in my page.
Title: Thank you   
Name: e
Date: 2009-08-19 4:57:48 PM
Comment:
Thanks alot. Well thought out. Virtually comprehensive
Title: Very good article   
Name: Manju
Date: 2009-06-17 8:55:36 AM
Comment:
currently i am searching for this imformation, thanks for ur article
Title: Good   
Name: Amit
Date: 2009-05-31 6:53:13 AM
Comment:
it a so good article but i was a code for a refersh a page in particular slot of time
Title: Good   
Name: champ
Date: 2009-04-17 11:44:28 AM
Comment:
its a good article but i wants a code for expire a page on refresf of my page after timeout
Title: not working properly   
Name: Ramesh
Date: 2009-04-17 11:32:16 AM
Comment:
Sir ,
i m a beginner to the asp.net,i was trying to use ur code but there is a problem when session gets expired its unable to display the SessionExpired.aspx,even my address bar is showing the url of that page but its not get display.

So please tell me what i should do to resolve this problem

Ramesh
Title: Excellent   
Name: Murthy
Date: 2009-04-14 8:02:50 AM
Comment:
Very excellent, Very useful code
Title: Nice article   
Name: Sam
Date: 2009-04-13 11:46:35 AM
Comment:
It's a nice piece of code. Thanks.
Is there a way to check wether the session has expired by then? For instance, I want to save something before the session timeout.
Title: hi   
Name: Majid
Date: 2009-03-17 9:18:54 PM
Comment:
That a very nice piece of coding it really helped, thnx.
Title: hi   
Name: maha
Date: 2009-03-02 3:54:26 AM
Comment:
Nice article.
Title: Great idea   
Name: Bino
Date: 2009-02-11 7:16:21 AM
Comment:
Great work...thanks for the trick
www.codepal.co.in
Title: Nice code   
Name: Charles
Date: 2008-10-01 8:37:31 AM
Comment:
This is a nice piece of code, I will give it a try. Don't mind negative worthless persons my friend, they're like flies (very useful).
Title: Comment on Considerations   
Name: sangam
Date: 2008-09-23 6:19:16 AM
Comment:
It's a great article. Thanks for this. The only thing i want to point out is that, as explained in the Page 3 Consideration section, it is not beneficial to have this system since the page a user is currently in expires as it would expire in the first load. The trend is that with user hit to server the session time out resets and it requires complete inactivity of user for the implemented expiry time.
Thanks. http://dotnetspidor.blogspot.com
Title: Hi   
Name: Nilesh
Date: 2008-08-13 3:34:04 AM
Comment:
Hi, can u give me code for session clear after browser close asp.net
Title: sessionexpired page culture language   
Name: Mamdouh
Date: 2008-06-01 7:35:12 AM
Comment:
again may my language or question was not clear. I have used this approach of meta tag to redirect users to sessionexpired page but i wanna set this page culture language to be read directly either from resource file or from cookie but i failed to do this. any help please?
Title: Check IsAuthenticated   
Name: Steve Smith
Date: 2008-04-25 8:18:20 AM
Comment:
@sessio- just check if they are logged in and only emit the meta refresh tag if they are.
Title: sessio   
Name: liju
Date: 2008-04-25 12:34:24 AM
Comment:
hey, i have 1 prob.my site contains pages, into which i can go before login as well as after login.so how can i implement redirect to an expire page.aspx on session time out.
thanks in advance
Title: Language resource file not read correctly   
Name: Mamdouh
Date: 2008-04-23 11:32:19 AM
Comment:
I have a bi-lingual application and i have used your approach and it works but it reverses the language. Could you tell me please how to read the language to display the page with specially that you know that the session is vanished. Note that i have used the cookies to store the language into it but the SesionExpired page still display in one language.
Title: Re: Master Page Still Worthwhile   
Name: Richard
Date: 2008-04-09 10:23:37 AM
Comment:
@Steve,

If you only want a module to apply to specific folders or pages, you can configure it within a location element in the web.config file:

http://msdn2.microsoft.com/en-us/library/b6x6shw7.aspx
Title: Master Page Still Worthwhile   
Name: Steve
Date: 2008-04-04 1:04:02 PM
Comment:
@Richard,
You still want to use the master page, rather than a generic module, unless the entire site requires authentication. Usually it doesn't, and you don't want users coming to your home page and being sent to a session expired or login page.
Title: Re: Refresh Meta Tag - not required   
Name: Richard
Date: 2008-04-04 12:18:53 PM
Comment:
Using Rick's suggestion, you don't even need a master page - you can add the header from an HttpModule instead.

private void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
if (null != context.Session)
{
context.Response.AddHeader("Refresh",
string.Format("{0};url={1}",
60 * context.Session.Timeout,
SessionExpireDestinationUrl));
}
}
Title: Re: Refresh Meta Tag - not required   
Name: Rick Strahl
Date: 2008-04-04 4:13:38 AM
Comment:
@Steve - Nice.

One thing though: you can actually skip the meta tag and use the Refresh HTTP header that it simulates which is a bit easier:

Response.AddHeader("Refresh","6;Page.aspx");

More detail here:
http://www.west-wind.com/WebLog/posts/6841.aspx
Title: Good Point   
Name: Steve Smith
Date: 2008-04-03 9:33:40 AM
Comment:
@Herman - That's a fair point; this solution pretty much assumes that interactions that are maintaining the session are also generating new pages. If that is not a valid assumption for the application (e.g. it does a lot of AJAX or Flash/Silverlight interaction), then this approach would need to be tweaked a bit. The simplest change at that point would be to use AJAX to call back on a timer to see if the session is active, and if not, redirect. Perhaps I'll write a follow-up to demonstrate this technique, but it's not nearly as simple as this one and this one will work in a huge number of cases that don't make heavy use of AJAX.
Title: Doesn't actually have anything to do with sessions   
Name: Herman
Date: 2008-04-03 7:57:30 AM
Comment:
You only provide a way to refresh a page. Wether the session has expired by then or not is something you don't even check.

Any AJAX or other activities like opening another tab for the same website postpone the session and your refresh counter will fail completely, telling the user the session has expired even though it is not.
Title: Worthless?   
Name: Steve Smith
Date: 2008-04-02 11:48:26 AM
Comment:
Anon - Thanks for your feedback, but clearly there are others who disagree, and not all that we publish is targeted at advanced developers. Sometimes simple things have value, too. I hope, for the most part, the content you find on this site is valuable to you, and if it isn't, that it is valuable to others. Take care.
Title: Worthless   
Name: Anon
Date: 2008-04-02 5:53:07 AM
Comment:
This post is completely worthless. ASP Alliance should take care of the newly posted articles.
Title: Great & Thx   
Name: Steven Kimpe
Date: 2008-04-02 5:46:29 AM
Comment:
A realy nice short piece of code! I've implemented the code straight away into one of our websites. Thx again!
Title: another way   
Name: Vahid
Date: 2008-04-02 4:47:10 AM
Comment:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
Response.AppendHeader("Refresh", ((Session.Timeout * 60) + 5).ToString() + "; Url=login.aspx");
}
Title: Good article!   
Name: Satheesh babu
Date: 2008-04-02 4:11:04 AM
Comment:
Nice article..It is quiet neat and simple!

Regards,
Satheesh
www.codedigest.com

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-26 10:47:22 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search