I am stuck with count down in ajax, I have a small website where I ask each user 5 question in 1 min time, after they login using asp.net membership provider. I want when the user time is over he/she must be taken to result page and show the result, I am using asp.net ajax timer, but if the user press F5 his time start again and by pressing F5 he can continue his test.
how can I stop that. also is there a easy way to show countdown using Ajax for 60sec
Regards
Arshad
Anything client side is potentially hackable, so you can't effectively maintain a time limit using only client-side technologies. When they begin a test, keep a DateTime in their Session to indicate that a test has been begun. If the submission comes in after more than the time limit has elapsed based on the server time, then tell them to try again cause they cheated.
Related
I have got an Asp.Net MVC application. This is just an approach so I can't provide code.
Basically what I want to achieve is if the session is over show an alert on whatever page the user is on.
The picture from Azure shows what I want to achieve (but this is farther, I want to start with displaying an alert first).
So is there a function or anything provided by asp.net detecting if the session is over? And secondly how would I display an alert?
Unfortunately, there is no easy answer to this. The reason is that if you were to ping the server to check the session, that action would actually renew the session timeout, unless you configure the service to not access the session - which means you need yet another tracking mechanism. The "fake" way is to set a JavaScript time that equals the session timeout. You would need to reset that timer on any ajax call.
The more involved solution is to use a persistent connection technology like SignalR that notifies a subscriber on session_timeout.
There is no specific function in asp.net that notifies the user that the session is over or going to end. But this functionality is seen nowadays in many websites.
The session is started by the server when a postback request is received. When there is no user action for a specific period of time, session expires. You can use javascript alert to show popup to the user regarding session timeout.
I will suggest 2 ways :
Run a timer in client side and notify the user when it is about to expire. For eg. if your session timeout is 5 min, you can probably
notify the user after 4 min that the session will expire in 1 min if
no action is done.
The second approach is to initiate a post-back request to the controller automatically or when user clicks ok button on an
alert(Your session will expire soon and you will be logged out. Do you
wish to extend the session?)
A website I am working on is very data centric. Some reports take more than an hour to complete. Whenever a user submits a request for a report, a new thread is created which generates the report. The user is then redirected to a page which says that the report in progress, and to please refresh to download the report. If the user again refreshes the page and the report is still in progress, the same message is shown; otherwise a download link is provided.
All report/user relations are saved in the application variable. That works fine, except when the user is inactive for more than 20 min (while the report is being processed), and then the user is logged out; if the user logs in again, the report can still be downloaded.
I do not want to increase the session expiration time, but I need to stop the expiration if the user has something going in background, like a report being processed.
In Session_End I am able to retrieve the the userid and match it in Application["work"] to see the user has pending work or not.
However, I am clueless as to how I can defer the session end in the above case?
Edit: Every one has suggested as a workaround from 'maintaining a contact' to 'using query string'. 'Maintaining the contact' looked the most promising to me but it fails in the following scenarios: a. When browser is closed/computed goes in standby mode during lunch, etc. b. When user goes to another non-asp.net section (it's a legacy site).
Isn't It possible to cancel the Session_End event itself?
The short answer
There is currently (that I know of) no simple way to extend the life of a single ASP.NET session. There is one possible solution: use a custom Session-State Store Provider!
The long answer
First things first: Start with something that is already built! Use the sample Session-State Store Provider (and its tutorial) provided by Microsoft. This sample Session-State Store Provider uses Microsoft Access as its back end; although, because it uses ODBC connections, you can have virtually any database back end supported through your installed ODBC drivers.
This sample Session-State Store Provider is simply a custom version of what ASP.NET uses internally (with the exception that ASP.NET's runs in-memory).
Secondly: Let's prepare the Access Database requirements, and the configuration.
Create the table as specified in the tutorial and in the comments of the file:
CREATE TABLE Sessions
(
SessionId Text(80) NOT NULL,
ApplicationName Text(255) NOT NULL,
Created DateTime NOT NULL,
Expires DateTime NOT NULL,
LockDate DateTime NOT NULL,
LockId Integer NOT NULL,
Timeout Integer NOT NULL,
Locked YesNo NOT NULL,
SessionItems Memo,
Flags Integer NOT NULL,
CONSTRAINT PKSessions PRIMARY KEY (SessionId, ApplicationName)
)
NOTE: If you want to use SQL Server, simply replace Text(...) with varchar(...), YesNo with bit, and Memo with varchar(MAX).
Add/update your web.config with the following (you can use connectionstrings.com to help you generate a connection string):
<configuration>
<connectionStrings>
<add name="OdbcSessionServices" connectionString="DSN=SessionState;" />
</connectionStrings>
<system.web>
<sessionState
cookieless="true"
regenerateExpiredSessionId="true"
mode="Custom"
customProvider="OdbcSessionProvider">
<providers>
<add name="OdbcSessionProvider"
type="Samples.AspNet.Session.OdbcSessionStateStore"
connectionStringName="OdbcSessionServices"
writeExceptionsToEventLog="false" />
</providers>
</sessionState>
</system.web>
</configuration>
Third: Adding a function that will extend for more than the specified Timeout.
Make a copy of the ResetItemTimeout function, and name it ResetItemTimeout2:
var ExtendedTotalMinutes = 2 * 60; // hours * minutes
public override void ResetItemTimeout2(HttpContext context, string id)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd =
new OdbcCommand("UPDATE Sessions SET Expires = ? " +
"WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("#Expires", OdbcType.DateTime).Value
= DateTime.Now.AddMinutes(ExtendedTotalMinutes); // IMPORTANT!! Set your total expiration time.
cmd.Parameters.Add("#SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("#ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ResetItemTimeout");
throw new ProviderException(exceptionMessage);
}
else
throw e;
}
finally
{
conn.Close();
}
}
Fourth: Supporting the extension of a single ASP.NET Session!
Whenever you need to extend a session, call the ResetItemTimeout function as follows:
using Samples.AspNet.Session;
// from inside a User Control or Page
OdbcSessionStateStore.ResetItemTimeout2(this.Context, this.Session.SessionID);
// --or--
// from anywhere else
OdbcSessionStateStore.ResetItemTimeout2(System.Web.HttpContext.Current, System.Web.HttpContext.Current.Session.SessionID);
Footnotes
Read the comments on the page with the sample Session-State Store Provider;
There is one potential good entry about a Mistake in GetSessionStoreItem when using GetItem.
Another good one is that Timestamps should be UTC.
There are obvious performance/maintainability improvements that could be done (especially with having duplicate code in ResetItemTimeout and ResetItemTimeout2).
I have not tested this code!
Edits
I realized I missed the part where you want to extend more than the Timeout - answer has been fully updated.
Added footnotes section.
Maintain a contact with the server will avoid Session Timeout.
Create a empty Web service and run that in your server then call the web service by your site by JQuery by the interval of some seconds is enough to keep the session alive
May be this solution will help you..
Try this link for full details : Prevent Session Timeout in ASP.NET
While desperately looking for defering the session_end event I think it seems impossible?
The easiest work around that I was able to come with was 'Using Cookies' and modifying my authentication logic.
I implemented a method for writing a guid key to the cookie named admin when ever user requested for the report with expiration of 9 hour(Max time office will be open for work).
I save this guid with user id in a seperate table.
In the master page where i was checking for session userid I implemented another method to check for any cookie named admin. If it is found i set session to the user id saved in table else i redirect them to login page as before it was happening.
It seems to work like magic. But I need to know is this a right thing?
What you can do is set the Session timeout to a higher value when you detect that a report has been requested that will take a long time. This of course supposes that you can calculate whether a report will take a long time to run. If so, you can do this before you kick off the thread:
Session.Timeout = 120 // set timeout to two hours for this session only
Apart from pinging a page or service through Ajax, there really is no other way. (unless not relying on sessions at all is an option).
This is because of the way sessions are maintained: the ASP.NET runtime detects a session when the request contains a cookie. This cookie is set at every request / response and will contain an expiration date.
If in your initial request you set an expiration of 20 minutes and the user closes the browser or is inactive for more than 20 minutes there is no way on the server side you can detect which session the request belongs to.
So, to answer your question whether you can cancel the session_end, no you cannot do that as that code runs server side and it cannot access the client cookie. It's a simple event that is fired twenty minutes after you last set the cookie. This is completely asynchronous from the client-side.
The solution I proposed is a workaround that could work if you know how to calculate the duration (at least approximately).
Another solution, but way more complicated, would be to save the reports and make a separate section for the user where he can see all his reports. That way, even if the session times out, he can log back in and go to his history and retrieve the report.
It's best not to rely on Session_end as it doesn't always fire, such as when the worker process recycles or an uncaught exception occurs, i.e. it is basically killed / bounced.
If you want to revive a session then it seems that the best way is to store the user data somehow and totally manage the cache yourself.
It seems from your reply to previous posts that the additional network activity and subsequent page time load increase when using sql state management are unacceptable, and the difference between using sql server state provider to using a session server such as Microsoft AppFabric would be negligible, however it seems a distinct possibility that if you were to use the session server of AppFabric coupled with it's caching, things could be sped up a lot.
P.S. In general doing away with sessions would seem like the most efficient solution, see John Han's answer in this post just about sums it up sessions are bad mmkay.
In order for a session to stay alive, something (not necessarily the user's browser) has to make a request to your app with that user's ASP.NET_SessionId cookie every so often.
What if you had some code that saves the ASP.NET_SessionIds of the users you are interested in, and then have a windows service that requests a page on your app with the required ASP.NET_SessionId(s) every 20 minutes or so.
see http://erlend.oftedal.no/blog/?blogid=41 for some info about this cookie
Are you using FormsAuthentication? If so, you could increase the timeout for the authentication ticket, which will prevent the login screen even after the session has expired.
At the beginning of the request you could check the user through the ticket
After get the user if the session is null it means the user has been offline for while, you the can check the work in progress for that user.
If the user has a work in progress, load session values that you might need it and redirect them to the work in progress or report to download.
If the user has nothing, expire the ticket and redirect them to login page or just keep them logged in and reload session values.
The timeout for the authentication ticket is pretty big
http://msdn.microsoft.com/en-us/library/system.web.configuration.formsauthenticationconfiguration.timeout.aspx
Cheers
I'd suggest increasing the session timeout instead of trying to find a way around it. There's an interesting thread about session and form timeouts here
I suggest that you don't depend on sessions at all .. you can depend on the query string by adding a new GUID variable and use that variable value with the application object to map the user requested file(s) with the GUID value .. this way .. the user will always be able to download the file since he have the link to the file that is mapped to the application object and no need to handle any session timeout.
Why do not you try to show the loading file progress bar and inside that one you can use the logic of checking status of file downloaded so far. It will have two advantage , as you are hitting your website , Session will not expire at the same time you are giving the useful information back to end user.
My webapplication is online exam site. when user click on start for writing test, i have to restrict the user particular time only, after time is completed message should display to the user that your exam time is finished and he redirect to home page, how can i write the code, can i go for timer control or webservice which one is good for the online exam site, please help me.
You need to capture the time when the user starts the test inside a Session variable:
Session["StartTime"] = DateTime.Now;// when user start test
Then when you postback the page get the difference between the current time and the time you stored in the Session:
diffrencebetweentime = DateTime.Now - Convert.ToDateTime(Session["StartTime"]); // at every postback
If the time difference is more than what you have decided send user to home page.
I need to maintaing the Session throughout the day? On or before session expires, how do I enforce session throughout the day without giving any session timeout either in IIS or web.config?
Note: Default Session Timeout in IIS – 20 minutes.
Thanks in Advance
The first thing you can do is decouple the session from the process by using a SQL (or other database) session state server that holds the serialized copy of the session data attached to a session id. Then you could use a persistent cookie to pass the session id back and forth. Any session that expires could then be regenerated or reinstated.
Since you're wanting to maintain a session all day (which is innately insecure), we'll assume that most security considerations have already been thrown out. If you're concerned about replay attacks, you could use an HMAC to validate cookie session requests by having the session id, datetime, username (if that's part of your data), maybe IP address in a string followed by a one-way salted hash of this data. This way you rehash the data and compare the hash sent with the request with the generated hash from that data to see if the request is valid.
Forcing the page to be refreshed every 10 minutes or so by javascript. The session timeouts are how long after the last requested page, the session becomes invalid. When you refresh the page every 10 minutes or so, the session is extended for 20 minutes on every refresh.
If you refuse to change the setting in the web.config to a longer value, you could try to force the browser to refresh within a short time of the session timeout (eg at 17 minutes). There might be other nifty ways.
If you can find a way to do without the session, it will save you pain later. Either use a caching strategy (memcached) or look at your resource usage.
eg Do you really need to serialise X into the session?
Use StateServer instead of InProc
This delegates all session handling to a separate database and removes it from the servers process. This will mitigate problems with eating up server resources which then allows you to increase the session timeout to 24 hours.
I believe this is the only viable solution.
Peiter is on the right track -- making fake requests to keep things alive. You definitely don't want to refresh the page, that leads to unwanted updates and such. You don't even need to refresh part of the page. You just need to send an ajax request every X minutes while a user has a browser open to an IHttpHandler that does have session state enabled. This is very, very effective -- we've got one app which is compltely dependent upon sessions for everything that has a 5 minute session timeout. And a session heartbeat that fires every 4.5 minutes. Its been in production upwards of 3 years and we have not lost a session yet. And yes, session state is stored in process in this case -- the use of sessions is so heavy we don't want to wait for them to go out to SQL and back.
PS: protip -- make sure to make the request and response unique; caching kicks in otherwise in certain browsers rendering this trick ineffective.
put a ajax call into a timer, to a method which does nothing "", that's how even the user is on the page but not doing anything means "totally inactive", would not log out, we have implemented the same logic and resolved our problem, our target was 3 to 4 hours, and we did not want to change the value in web.config or using any other way cause of some reasons.
that ajax call would be in a "timer", set the timer time to "any".
Background: I'm creating a very simple chatroom-like ASP.NET page with C# Code-Behind. The current users/chat messages are displayed in Controls located within an AJAX Update Panel, and using a Timer - they pull information from a DB every few seconds.
I'm trying to find a simple way to handle setting a User's status to "Offline" when they exit their browser as opposed to hitting the "Logoff" button. The "Offline" status is currently just a 1 char (y/n) for IsOnline.
So far I have looked into window.onbeforeunload with Javascript, setting a hidden form variable with a function on this event -> Of course the trouble is, I'd still have to test this hidden form variable in my Code-Behind somewhere to do the final Server-Side DB Query, effectively setting the User offline.
I may be completely obfusticating this likely simple problem! and of course I'd appreciate any completely different alternative suggestions.
Thanks
I suspect you are barking up the wrong tree. Remember, it is possible for the user to suddenly lose their internet connection, their browser could crash, or switch off their computer using the big red switch. There will be cases where the server simply never hears from the browser again.
The best way to do this is with a "dead man's switch." Since you said that they are pulling information from the database every few seconds, use that opportunity to store (in the database) a timestamp for the last time you heard from a given client.
Every minute or so, on the server, do a query to find clients that have not polled for a couple of minutes, and set the user offline... all on the server.
Javascript cannot be reliable, because I can close my browser by abending it.
A more reliable method might be to send periodic "hi I'm still alive" messages from the browser to the server, and have the server change the status when it stops receiving these messages.
I can only agree with Joel here. There is no reliable way for you to know when the HTTP agent wants to terminate the conversation.