Wednesday, October 29, 2008

How to Redirect to Login Page after a Session Timeout

In ASP.Net 2.0 applications there's a special event handler called "Session_End" that exists in Global.asax. It is fired when the Session Timeout occurs.

I use this event handler to write key Session variables (all DataTables at the moment) out to a special holding area within the associated database. The next time the user logs in, these same Session variables are restored with the previous data. In this way the user is protected from losing valuable work if they step away from their computer for a moment.

I did some testing and was a little surprised to discover that when such a timeout occurs, the browser just stays on the page it was before. This is clearly a problem, both for security reasons (an unattended corporate app should log itself off) and because the Session variables were now all null. Eventually I heard from a bright developer from New England named Mike Banavige who succinctly explained the situation this way:

Session end does not occur in the context of an http request. It is simply a timeout that occurs on the server. Since there is no request involved in the timeout, there is nothing to redirect.

Put another way, the Session_End event is occurring strictly on the server - the client doesn't know a thing about it. Makes perfect sense - why didn't I think of that!

So what to do with the predicament of the web app remaining on the same page, even though the Session has timed out? Well, more research revealed the answer. Within the Page_Load event handler of my master page codefile, I added this:

Response.AddHeader("Refresh", Convert.ToString((Session.Timeout * 60) + 5));
if (Session.IsNewSession)

Since every web page in my app utilizes the master page, this Refresh meta tag is inserted into each of them. And because it's in the Page_Load event handler, it gets updated (moved forward) every time a postback occurs. With a typical 5 or 10 minute session timeout, it's highly unlikely that the user would be working on something that long without a postback occurring. It thus serves as an effective way to implement a Logout due to User Inactivity feature.

Monday, October 27, 2008

OnClientClick and Postback

I created a small grid that looks like this:
Intuitively, it makes no sense for the "Discard" button at the bottom to be enabled if none of the checkboxes above it are selected.

After building the JavaScript to handle this logic, I thought I had done everything correctly. But I noticed that everytime I pressed the "Toggle" LinkButton, a postback was performed. Considering that I had no server-side code wired up for this control, I was most confused. I did a little research and discovered that when using the OnClientClick property, you need to explicitly return false or a postback will occur.

Sunday, October 26, 2008

Visible = false vs. display:none

I learned a painful little lesson today which hopefully will benefit others.

Most every ASP.Net control has a Visible property, which can be set to either 'true' or 'false'. If you've ever set it to 'false' and look at how it's rendered, you'll see this HTML property: style="display:none"

But when you're using the AJAX Control Toolkit, the two ways of hiding a control are not always equal.

For example, when I use the ModalPopupExtender to display a dialog box, I frequently define the TargetControlID with a dummy button. Why? So that I can programmatically control when the dialog box is displayed. Here's a very straightfoward example:

The only reason that buttonDummy exists is because the ModalPopupExtender must have a TargetControlID defined. And since you don't want the user to see this dummy button, you need to hide it. But doing so by setting Visible="false" internally seems to mess up the logic of the ModalPopupExtender. When you're expecting the dialog box to display, the code runs but nothing happens.