0

I have a single page application in ASP.NET c#. All informations in the application are getting loaded using AJAX calls. There's no POSTBACK at all. However, every time I click on a different menu item that loads data from Web Services it checks if user has a valid session. Since there's no postback and when session expires users still see the main page and when they click on a menu item the data will not load since session expired (but users don't know that).

I do know how to redirect to login page when session expires if there's a postback, but how can I achieve the same result without a postback?

smr5
  • 2,593
  • 6
  • 39
  • 66

3 Answers3

2

The only thing that comes to mind here is to use an AJAX call to a webservice which will check if the session is active, and then act accordingly. Something along these lines (untested):

ASHX handler:

<%@ WebHandler Language="C#" Class="CheckSessionAlive" %>
using System;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using System.Web.Script.Serialization;

public class CheckSessionAlive : IHttpHandler, IRequiresSessionState {

    public void ProcessRequest (HttpContext cx) {
        cx.Response.ContentType = "text/json";
        cx.Response.Write(new JavaScriptSerializer().Serialize(new
        {
            Result = cx.Session["SomeRandomValue"] != null ? 1 : -1
        }));
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

Javascript (JQuery) call:

function CheckSessionAlive() {
    $.ajax({
        url: "CheckSessionAlive.ashx",
        type: "GET",
        success: function (data) {
            if (data.Result == 1)
                setTimeout(CheckSessionAlive, 5000); // 5 seconds
            else
                window.location.href = "http://www.google.com";
        }
    });
}

$(document).ready(function () {
    CheckSessionAlive();
});

I hope it's useful :).

DARKGuy
  • 843
  • 1
  • 12
  • 34
  • Thank you for your reply. Session length is set inside the webconfig file in my application. How would webservices know if session expired or not? – smr5 Apr 22 '15 at 17:20
  • You're wecome :). The webservice will be called every 5 seconds by the AJAX call and it will check for a session value you can set in your login sequence (if you're using asp:Login you can do it in the OnLoggedIn event) with a dummy value. Once the session expires by itself the check will return a null value, making the webservice return -1 and the AJAX function will redirect you to google.com, in my example. – DARKGuy Apr 22 '15 at 17:34
0

How does the user logs in the first place? If they login from a different page, you have to redirect them to the page to login. If you do it within your one page application, web service calls needs to return a flag indicating session status. If session expired, your ajax call should trigger login view. Hope it helps.

  • User logs in using `login.aspx` page. Once the user successfully logs in I set the session variable and redirect the user to `default.aspx` However, after that redirect everything that's happening inside default page has no postback at all. – smr5 Apr 22 '15 at 17:14
0

I was able to resolve this issue. Here's my approach.

In pageload of default.aspx I get the session time from web.config file.

protected void Page_Load(object sender, EventArgs e)
{
  Response.Cache.SetCacheability(HttpCacheability.NoCache);
  if (!this.IsPostBack)
  {
    Session["Reset"] = true;
    Configuration config = WebConfigurationManager.OpenWebConfiguration("~/Web.Config");
    SessionStateSection section = (SessionStateSection)config.GetSection("system.web/sessionState");
    int timeout = (int)section.Timeout.TotalMinutes * 1000 * 60;
    ClientScript.RegisterStartupScript(this.GetType(), "SessionAlert", "SessionExpireAlert(" + timeout + ");", true);
  }
}

And then using JavaScript function I do a countdown and show a warning message when it hits 60 seconds.

<script type="text/javascript">
function SessionExpireAlert(timeout) {
var seconds = timeout / 1000;
document.getElementsByName("secondsIdle").innerHTML = seconds;
setInterval(function () {
    seconds--;
    document.getElementById("secondsIdle").innerHTML = seconds;
}, 1000);
setTimeout(function () {
    //Show Popup before 20 seconds of timeout.
     toastr.info('You will be logged out in: <span id="secondsIdle">' '</span> seconds.<br/>Click here to stay logged in.', "Warning",
        { timeOut: 0, 'position-class': 'toast-tontainer',onclick: renewSessionState}
}, timeout - 20 * 1000);
setTimeout(function () {
    window.location = "logout.aspx";
}, timeout);
};
</script>  


function renewSessionState() {
$.ajax({
    url: "/Handlers/Ping.ashx",
    method: 'POST'
});
}

Note* Ping.ashx is just an empty handler.

smr5
  • 2,593
  • 6
  • 39
  • 66
  • That's a good alternative, it would be great if you could mark my suggestion as an answer since I see it was helpful - however I see a small caveat there: If by some reason you have slidingExpiration=true in your web.config file, the timeout won't be synchronized. Also, you depend on the browser's timer, and the timeout can be altered with a simple console javascript function or greasemonkey script. A server-side way is more secure, IMHO :P – DARKGuy Apr 22 '15 at 20:30