What is the best approach to handle session timeouts in asp.net - c#

There are various ways to handle session timeouts, like "meta refreshes" javascript on load functions etc.
I would like something neat like: 5 minutes before timeout, warn the user...
I am also contemplating keeping the session open for as long as the browser is open(still need to figure out how to do it though... probably some iframe with refreshing).
How do you handle session timeouts, and what direction do you think i should go in?

The best approach to handle sessions timeouts.
I say that there is 2 basic cases.
One is when the users enter little or no data, and just read reports, or do small thinks with his mouse. In this case there is not easy way to inform him that the session is going to expire. If you going to check the time left for the session calling the code behind, then automatically you update the session. Then if you have a timer to count down the session, then maybe the user have open a new tab of your web and the session is going to expired but not the time you have note with javascript and the user receive wrong message.
So for me, when the user enter little or no data, just let the session expired, if he lose one click, it will do it again later.
Second is when the user need to enter many data, that some time can take time, a long text for example, to write it and fix it. In this case I use the below technique and I am not let the session go out.
How to keep the session open as long as the browser.
Here is a very nice and simple technique, I use an image that I make an reload of it before the session is timeout using JavaScript.
<img id="keepAliveIMG" width="1" height="1" src="/img/ui/spacer.gif?" />
<script language="javascript" type="text/javascript">
var myImg = document.getElementById("keepAliveIMG");
if (myImg){
window.setInterval(function(){
myImg.src = myImg.src.replace(/\?.*$/, '?' + Math.random());
}, 6000);
}
</script>
In a third case, you can do this. We care if the session is expired only on post back. When the user have enter some data and on the post back the application is redirect him on the login page and the post lost.
In this third case you can capture the post data and saved them until the user re-login. You capture the post data on global.asax on the
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
This is the function that called before the redirect to the login page, and there you see if you have post data and the use required to login, you save that post data, ether to a new redirect page, ether to the server (maybe on session, maybe on your temporary database).
Now after the user is login again, you redirect him again to the last page with the saved post data, and the user is continue as it is.
The only trick here is to make a middle page, that render the form with the last posted data and an automatically redirect javascript call.

The only thing I can think of is to generate some script on the page that creates a client timer, so that when the page is received and rendered, it can show an alert X-minutes later (that is 5mins before expire).
If you'd rather have the session just keep itself alive, you can do this with a generic handler (ASHX) that you periodically call via AJAX. This will help refresh the session and it should stay alive for as long as the AJAX calls continue.
Example "keepalive.ASHX":
<%# WebHandler Language="C#" Class="keepalive" %>
using System;
public class keepalive : System.Web.IHttpHandler
{
public void ProcessRequest (System.Web.HttpContext context)
{
context.Response.ContentType = "text/json";
var thisUser = System.Web.Security.Membership.GetUser();
if (thisUser != null)
context.Response.Write("[{\"User\": \"" + thisUser.UserName + "\"}]");
}
public bool IsReusable
{
get { return false; }
}
}
And here's the script on the page to call it (with jQuery for simplicity):
<script type='text/javascript'>
function keepAliveInterval()
{
$.ajax(
{
url: "keepalive.ashx",
context: document.body,
error: function () {
alert("AJAX keepalive.ashx error :(");
}
});
}
$(document).ready(function () {
window.setInterval('keepAliveInterval()', 60000);
});
</script>

Use some jquery that keys off of your session timeout variable in the web.config. You can use this Jquery delay trick that when a specific time occurs (x number of minutes after load of the page), it pops up a div stating session timeout in x minutes. Nice, clean and pretty simple.
Regarding session timeout, Codesleuth's ajax call would be perfect.

Related

How to log the link click which make form submission?

I wanna to track the user activity (log data). i have several links on the page which submit form through specific way .the problem is :
I can't find a suitable way to handle the click event and insert the log in the database in a simple way.
My code :
HtmlGenericControl a = new HtmlGenericControl("a");
a.Attributes["onclick"] = "$('#" + frm.ClientID + "').submit();";
a.InnerText = "site " + dt_list.ElementAtOrDefault(0).Field<string>("pro_name").TrimEnd();
inner_li_1.Controls.Add(a);
Now i wanna to handle the click event of the link which make the submission ?!!
This is too much, how ever its works, and I use it in some case that I can not do other way.
The javascript call, I call the log first, then continue with submit. I have also show a wait message when I make the click, how ever the events happends too fast and the user did not understand that is wait for anything. I also take care to avoid double log of the action with simple javascript. I call this function on the onclick event.
var confirmSubmited = false;
function SubmitWithLog(me)
{
// to avoid many clicks...
if(confirmSubmited)
return false;
confirmSubmited=true;
jQuery.ajax({
url: "/LogAction.ashx",
type: "GET",
timeout: 3000,
async: true, // you can try and async:false - maybe is better for you
data: action=4, // here you send the log informations
cache: false,
success: function(html) {
jQuery("#FormID").submit();
},
error: function(responseText, textStatus, XMLHttpRequest) {
jQuery("#FormID").submit();
}
});
return false;
}
The handler is as
public class LogAction : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// log here what you wish
// end up with no content
context.Response.TrySkipIisCustomErrors = true;
context.Response.Status = "204 No Content";
context.Response.StatusCode = 204;
}
}
I like to clear that this is not a good way to log the user action, but its a way when you can not do otherwise. I use it only ones, when the user make submit and leave my site and go to one other site, and I use it to write this action.
In all other cases I use ether a reference in the url, ether make log on code behind, ether I include an empty image in the html page that make the log like that: ASP server stats for html pages
I have try to call ajax, and right way make the submit, but its fails, the ajax is stop by submit. The next way was to use timeout, to call ajax, and set timeout 500ms to make the submit, but I avoid the timeout because the ajax call takes less than 100ms as I have made it.
#Aristos -- Why in the world would you negatively impact the user experience by waiting for the Ajax call that does the logging to return before moving on with the event (click, submit, whatever...)?!? Logging is a non-critical part of the application, where the user experience does not change based on its results. It's a "send and forget" type routine. Fire off the Ajax request, leave the success and failure routines empty, and execute the submit on the line immediately following the $.ajax(); call.
So, some pseudo code for you...
function handleClick(e) {
handleLoggingOnClick("something happened here");
myForm.submit();
}
function handleLoggingOnClick(message) {
$.ajax({url:"logging.do", data:"message="+message});
}

How to get a list of active sessions in a web application?

I am trying to get a list of active session id's in my web application.
I tried to manage a list in Global.asax.
I add session id when Session_Start is fired, and remove session id when Session_End is fired.
The problem is in cases when the user closes the browser or shut down the computer.
The Session_End is not fired, and the seesion still exists in the list.
Somebody has an idea how can I get the list?
Thanks!
There is no solution to this problem that avoids the complication you note. Unless there is some explicit way to end a user's session - and the user activates it - the only way to know when a session has ended is to allow it to expire.
Session_End will eventually fire, when the session times out. The only time you never see Session_End called is when the application domain itself unexpectedly quits. In such a case, you know that all of your sessions are dead, anyway.
Andrew Barber is correct. There is just one more thing you can do:
Ask your users to logout. In fact not just ask them but in a way force/remind them that they have to log out.
Here is how i did it:
<script type="text/javascript">
$(function () {
$("a").click(function () {
window.onbeforeunload = null;
});
});
</script>
<script type="text/javascript">
window.onbeforeunload = confirmExit;
function preConfirm() {
if ((window.event.clientX < 0) || (window.event.clientY < 0)) {
confirmExit();
}
}
function confirmExit() {
return "You have attempted to leave this page. It is suggested to log out using the link. Are you sure you want to exit this page?";
}
</script>
By adding these scripts to your master page (if that is the case or in every page) the browser prompts the user with a modal window with your message if they try to load another page or close the browser without logging off.
Of course the user my decide to leave the page anyway even though you remind him to log off but really you have tried your best!!
If you use a SQL Server database to store your sessions in it becomes easier to retrieve what appears to be currently active by using an SQL query to get what you need.
I say appears because like others have noted sessions can hang around if they are not properly cleared using Session.Abandon() e.g. if the user just closes their browser window without logging out. This means that you can only rely on the expiry date of the session to be sure the session is completely finished with, however long you have set that to be.
I should also point out that if you do use a database as your session store, the Session_End event will never fire.

C# MVC Creating a timer based auto-logout with jquery?

How do I create an jquery script to automatically log out the user after a set period of inactivity? Or is there a jquery plugin that does this? It would need to do something like:
Create timer with setTimeout (eg for 30 mins)
Reset the timeout every time the user interacts with the page
After the setTimeout expires, use ajax to call the /logout action on the server (asp.net mvc)
Show a modal/lightbox dialog telling the user to login again
You have couple of different aspects that you need to consider here. First of all, what happens if the user just closes the browser or if the computer the person is using dies? If the user visits the page within 30 minutes, should the person still be logged in?
Let's say that the user should be logged in for 30 minutes, no matter what. The easiest way to start is to set a cookie timeout on an authentication cookie. Remember to update the timeout when each page refreshes. And use a jQuery timer to check if the cookie is still valid or not, or just keep track of the users login time.
So, jQuery timers, you could on each page load refresh the cookie and then just check if the timer/delay executes, if so, remove the cookie and display a modal box.
There's tons of ways of doing this, using the timers are one way.
$(this).oneTime(1800 , function() {
location.href='/logout'; // redirects to logout page.
});
Another aproach is to use server side checking for this, but you will not get the model box for this, as I said, there are tons of ways, it all depends on your preferences.
I know it's very old question, but could be useful for someone looking for similar solution to log out user if they are idle for certain timeperiod
http://www.dotnetfunda.com/articles/show/3130/automatically-logout-when-user-is-idle-for-sometime
The link may disappear so here is the code -
<script>
$(function () {
$("body").on('click keypress', function () {
ResetThisSession();
});
});
var timeInSecondsAfterSessionOut = 30; // change this to change session time out (in seconds).
var secondTick = 0;
function ResetThisSession() {
secondTick = 0;
}
function StartThisSessionTimer() {
secondTick++;
var timeLeft = ((timeInSecondsAfterSessionOut - secondTick) / 60).toFixed(0); // in minutes
timeLeft = timeInSecondsAfterSessionOut - secondTick; // override, we have 30 secs only
$("#spanTimeLeft").html(timeLeft);
if (secondTick > timeInSecondsAfterSessionOut) {
clearTimeout(tick);
window.location = "/Logout.aspx";
return;
}
tick = setTimeout("StartThisSessionTimer()", 1000);
}
StartThisSessionTimer();

redirect user after inactivity, but keep session alive

I try to redirect my page for a logged in user with a certain amount of inactivity to a different page without killing the session.
I would like to substract the time I spent on the first page from the session, put the user on the new page, and then log the user out after his session (rest of the session time) times out and redirect the user to the login page.
I found this:
HttpContext.Current.Response.AppendHeader("Refresh", Convert.ToString(((HttpContext.Current.Session.Timeout * 2) - 5)) + "; Url=Dashboard.aspx");
but this interferes with my master page:
Context.Response.AppendHeader("Refresh",Convert.ToString((Session.Timeout * 60)) + "; URL=" + ResolveUrl("~/Logout.aspx"));
If it is easier, the user session does not need to be subtracted by the time the user spent on the first page.
Is there maybe an easy javascript out there that I missed on google?
Thanks,
Patrick
Ok, I did the following to solve this issue: Everytime a user hits a button, i call detime(), and also on the page_load I call detime(). Maybe not the best solution, but at least I got what I want ;)
function timer()
{
time1 = window.setTimeout('redirect();', 300000);
}
function redirect()
{
window.location = "XXX.aspx";
}
function detime()
{
if (time1 !=null) {
window.clearTimeout(time1);
time1 = null;
}
timer()
}
Well, I suppose it depends on your server platform, but in my experience it's the server that determines session timeout. The reload that your client-side code triggers will, unless you somehow override the normal behavior of the server, refresh the session and start the timer over again.
Now, what you could do is update the page client-side and not talk to the server at all. To do that, you'd effectively load the code to the "almost timed out" page at the same time you load the original page. Then, when your timeout fires, you just show the desired page and hide whatever's there.
I would encourage you to consider the usability issues with this overall scheme.
It seems like what you want to do is pass a timestamp along with the redirect and then capture the timestamp and either use that or, if its undefined, the current time as the time the user started. Then once that time has run out send the user to an explicit log out that kills their session.
As long as you redirect to a page that explicitly kills the session, I don't think you'll have a problem with expiration. Accept in the case where the user gets redirected to the new page, and then closes the browser, which maybe you could use an onunload script to kill the session explicitly again.

Threading using AJAX

When the user clicks on a link to generate report I make an AJAX call which generates a pdf file in the background.Now the files are huge running upto 10mb or more.So it takes some time.In the mean time the user should be able to navigate other links as if nothing has happened.So I need to implement in such a way that the pdf generation process gets started & user doesn't have to wait for the process to finish.Is this possible?I am using AJAX Pro with c# with dot net framework 2.0
The problem here is that as soon as the AJAX activity begins the browser enters into a hung stage & the user has to wait although he clicks on a different link.
I would probably create a 'queue' or an 'inbox' for the user ...
start your pdf generation routine with a ThreadPool.QueueUserWorkItem (you would also need to modify your generation method to output to their inbox)
then on each http request check that inbox and notify the user of the item ... you can always poll the server on an interval or somthing
Sure, but once the user navigates to another page, the Javascript that is waiting for the Ajax response is no longer running, so that request is lost. You'd have to either find a way to keep that page open (using frames or exclusively Ajaxified navigiation), or find a way to store the response and notify the user of its completion on the next page view. For instance, storing a session variable that indicates that the operation is completed, or storing it in a database with (perhaps) an "unread" boolean value.
You can have asynchronous Ajax call with which you can do other tasks while response objects returns from the Ajax page.
Here is some example, testAjax.aspx is the Ajax page here :
http_request.onreadystatechange = function() { alertContents(http_request); };
http_request.open('GET', 'testAjax.aspx?', true);
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http_request.send(null);
function alertContents(http_request)
{//debugger;
if (http_request.readyState == 4)
{
if (http_request.status == 200)
{
var vResult;
vResult=http_request.responseText;
//Write your logic after successful Ajax call here.
}
else
{
alert('There was a problem with the request.');
}
}
}

Categories

Resources