views:

51

answers:

3

Hi

I am using asp.net mvc, C# and jquery. My site is uses ajax heavily. This has lead to a problem and I am not sure how to fix it( well fix it better than my current solution).

Scenario.

  1. User logins into my site - cookie set, server has timeout of 30mins
  2. User walks away for 30 mins
  3. User comes back and clicks on one my ajax enabled jquery tabs
  4. Request sent to server
  5. Server goes nope user timed out send them back to signin page.
  6. since it is a an ajax request the redirect gets rendered in the tab. It look ugly(an entire page rendered in a tab), user is probably extremely confused at this point.

Problem

  1. As far as the server and ajax is concerned the ajax request is valid and success response is sent back. So I can't go check for an error as the request was successful just not the right data coming back.

Solution 1

  1. User logins into site.
  2. Jquery ajax request made to find out users timeout
  3. timeout is 60 seconds less than server timeout
  4. Once timeout on javascript side is hit. Jquery dialog box comes up and tell them their session expired and forces them to be redirect to sign in pack.
    • A user can't click on anything as the dialog box blocks that. If some users firebug or something they can remove it but then server timeout will still be effect and they will get the ugly version(don't care then).
  5. If a user makes an ajax request the timeout on the server side is reset as well as the one on the client side.

Problems

  1. User could walk away and another person could come and the timeout message could be up but they still could have a potential of 45 seconds of trying to make a new request and reset the timeout. This is very low and not too worried about it.

  2. Sometimes I have observed is it just times out( the client side) and I don't know why. I never can recreate the problem( seems to happen to other people but not when I am testing). So I am guessing something did not hit write or something else went wrong.

So number 2 is really the big reason why I would want to find another solution.

Solution 2 (speculation).

I was thinking maybe if I can make my own response header or something so if the server times out then I can send some 303 redirect or something in that nature that I could check for then do a jquery redirect based on that.

However I am not sure where to do that in my C# code or if I can do something like that.

+2  A: 

I don't see why your authentication handler (action filter) can't handle this by returning 403 (forbidden) which AJAX handler will then process by setting window.location to /login.

queen3
That's exactly what the authentication handler does, problem is that this is intercepted by the ASP.NET engine and redirected to the login page => all that jQuery sees is a 200 status code to the login page.
Darin Dimitrov
So Darin do you know away around this? Can I get it to keep with he 403 or 303 or something non 200?
chobo2
That's why I said "your authentication handler/filter". Create your own AuthorizeAttribute and override OnAuthorization to return ForbiddenResult. This is ASP.NET MVC, you can do whatever you want. I actually use the technique that I describe.
queen3
+1  A: 

I basically do solution 1, except that (1) I've encapsulated it into a plugin and (2) I inject the session timeout in the page when it renders. You can see details on my blog, http://farm-fresh-code.blogspot.com, in this article. One addition is that, when the client-side times out, it automatically invokes the logout action to actually terminate the session.

tvanfosson
+1  A: 

You could always add a custom HTTP header in your LogOn action which could be intercepted by AJAX calls and act accordingly:

public ActionResult LogOn()
{
    Response.AddHeader("X-LOGON", "LogOn");
    return View();
}

And in the success callback check for the presence of this header:

$.ajax({
    url: '/home/someaction',
    success: function (data, textStatus, XMLHttpRequest) {
        if (XMLHttpRequest.getResponseHeader('X-LOGON') === 'LogOn') {
            // the LogOn page is being displayed 
            // probably timeout or unaithorized => act accordingly
        }
    }
});
Darin Dimitrov
Might be better in a global ajax handler -- that way you don't have to check for it everywhere. The thing that I don't like about this is that the user might spend a fair amount of time doing something only to have it wiped out because it's submitted after the session expires. I prefer to warn them prior to that event and let them take some action to avoid it.
tvanfosson
@tvanfosson, yes, good idea, `$.ajaxSetup` looks like a great place to do this once and for all.
Darin Dimitrov
@tvanfosson, so you are periodically polling the server to detect that the authentication ticket is still valid?
Darin Dimitrov
yes I sort of agree with tvanfosson if the user times out it should come up with a message saying they are warned. However I don't know about like a 2min a warning or something. Like I said once the user goes to my page it's all ajax. So even if they come back and there is 30 seconds and want to do something. To do that something will be an ajax request. But I think instead of an auto direct a dialog should come up saying they timedout. Now with $.ajaxSetup can you show me what to do I tried to make one and it does not work.
chobo2
Also Darin I am guessing that there is no way to make the authorize tag send back the 303 redirect? Also why do you make your own header and not set a 303 redirect? Is this to avoid potential conflicts?
chobo2
@chobo2, if you want to warn the user that his session expired then simply put a warning in the `if` condition I provided in my answer.
Darin Dimitrov
@chobo2: see http://api.jquery.com/jQuery.ajaxSetup/, now put the if condition into this global success handler: `$.ajaxSetup({ success: function(data, textStatus, XMLHttpRequest) { ... } });`
Darin Dimitrov
@Darin - no -- I use the session time out from when the page renders minus some amount for the message to display, etc. I set a timer to expire just before the session would time out and put up a dialog. This starts another timer that, if it expires, will invoke the logout action. If the user performs any action that touches the server, including responding positively to the dialog causing an ajax "ping" back to the server, a global ajax handler resets the timer and starts the whole process over. The code is smart enough to only work when the session is authenticated, too.
tvanfosson
@Darin ya it is simple to make the dialog box. I see you put "success" would that not override all my other ajax success? I thought I should put it in ajax complete.
chobo2
Yes, that will override all your ajax success and I thought that was what you were looking for => alert the user if his session has expired no matter what AJAX call you are performing instead of rendering the ugly login page into a div. Correct me if I am wrong. I am really tired after the World Cup matches and all the beer :-) Cheers.
Darin Dimitrov
lol. Well what I was saying was as far as ajax is considered timing out is a success. However if it does not timeout I still have stuff that is written in each of my ajax successes(such as display error messages, success messages and so on.) So I can't really over ride it. So maybe complete is a better place to put it(other wise each success would have to have a if statement check first if not timeout then do success msg stuff).
chobo2