Asp.net mvc server side timer - c#

I am creating an online quiz application and need server side timer. For example if the user opens another browser or refresh the page or leave and back time shoud be proper.
Now i am using jquery timer and in every 5 minutes send ajax request to store proper information into the database. Also when the user answers the question i immediately send again ajax requst for the same purpose.
Should i use signalr instead? What would be more proper way to handle server side timer in asp.net mvc?

As long as you have a session, you could simply store the timestamp of when the user began taking the quiz in session state.
You could tell the time of any future event by looking at the timestamp of that event, minus the timestamp of when the user took the survey.
Example (server-side code):
if (Session["startTime"] == null)
{
Session["startTime"] = DateTime.Now;
}
var ticksRemaining = DateTime.Now - Session["startTime"];
// Use ticksRemaining to populate the start value for the count-down timer
// Works just fine even if they reload the page or open a new browser tab.
// You won't catch if they open a brand-new browser and start a new session,
// but that's a different kind of problem.

Related

ASP.NET Webservice- SessionState not timingout

I have a web application that utilizes JQuery as my front end code and ASP.NET as my backend web service.
I set the web.config setting <sessionState timeout="1">. When the user logs in, the web service creates a session variable with the user name.
System.Web.HttpContext.Current.Session["UserID"] = user_id;
In my web service, I have a function that checks if the variable still exists.
[WebMethod(EnableSession = true)]
[ScriptMethod(UseHttpGet = true)]
public string GetSessionUserID()
{
string user_id = "";
if (System.Web.HttpContext.Current.Session["UserID"] != null)
{
user_id = System.Web.HttpContext.Current.Session["UserID"].ToString();
}
return user_id;
}
I have a JS function that calls the web service that calls GetSessionUserID().
$(document).ready(function () {
getSessionID();
setInterval(getSessionID, 3000);
function getSessionID() {
console.log("getSessionID");
$.ajax({
url: "photoapp.asmx/GetSessionUserID",
//data: ,
success: OnGetSessionIDSuccess,
error: OnGetSessionIDError
});
}
function OnGetSessionIDSuccess(data, status) {
console.log("Success OnGetSessionIDSuccess");
console.log(data);
var strUser = $(data).find("string").text();
console.log(strUser);
if (strUser == "") {
window.location = "login.html";
}
}
}
In the document ready function, I also call setInterval() which will check the session every 3 seconds.
When testing, getSessionID gets called every 3 seconds, but after a minute, the getSessionID user variable can be found. I want the redirect the user back to login.html after the minute is done. Why is the session variable still alive after a minute? What am I not understanding about ASP.Net session state? How can this be fixed?
Be aware that if you adopt SQL server to save the session state, then the session timeout events never get called, and you thus can't know or tell if the user actually has logged out.
The only possible solution then is to ensure that all web pages have some kind of heartbeat or routine that calls the server every minute or so, and when that stops, then you know the user is gone or closed the web page.
In your case? If you touch the server every 3 seconds, then the session timeout will be re-set and start over with 1 minute. You also don't mention if you using in-memory, or using sql server for session state.
If you want to jump back to the logon page? Then your 3 second js code has to get/grab the time of the last heartbeat you call every 3 seconds. So, that routine has to set a start time, and then every 3 seconds check the elapsed time. Keep in mind that if you use sql sessions, then not even the logon event will fire, nor will even the authenticated user event fire.
So, the first time you start running that routine, you need to set a session value with the start time.
However, to my knowledge, every web service call will re-set the session time out to start over to 0. session timeout gets re-set when no activity occurs. So, if the user is doing something (or your ajax calls are), then session timeout will never occur.
You have to set a start time. And then get the elapsed time from that. You session will never timeout as long as you have the web page hitting and talking to the server.

C#, ASP.NET - How can I Update UI, wait 5 seconds, Update UI again?

I am using ASP.NET webforms.
What I am looking to do is
execute a method that returns a string
update label with that string
wait 5 seconds
execute method again
update label with 2nd string
repeat..
you can load your page after specific time using below line of code in
head section
<meta http-equiv="refresh" content="10"/>
content=10 tells the time delay after which the page gets reloaded. but please specify your problem to write code so that i can understand properly
If your "Method" needs to be executed Server Side then you can send Ajax Requests every 5 seconds or you can you use Signal R to push the results every 5 seconds. Check this link for Signal R:
Using Websockets through SignalR to broadcast data from Server to Client
If your method needs to be executed client side, then you can use setInterval:
setInterval(function() {
// method to be executed;
}, 5000);
I am guessing that you want to execute a method in the controller every 5 seconds so your view gets updatet? I don't know how you're passing a different parameter each time but I try to answer your question.
If you are using C# ASP.net you mostly try to avoid HTML or Javascript for this kind of actions. So I am using this to reload my HttpGet method from my controller:
Response.AppendHeader("Refresh", "5;url=/Home/" + MethodBase.GetCurrentMethod().Name);
"MethodBase.GetCurrentMethod().Name" = the name of your method,
"5;" is the number of seconds before it refreshes.
If the method name is not the same as your view name then just use a string.

Is this possible to clear the session whenever browser closed in asp.net?

In my asp.net application, i want to clear the session whenever my browser closed or my tab (if my browser containing multiple tabs)closed.
Please guide me to get out of this issue...
Short version, No.
There's no solid way of a server detecting if the client has closed their browser. It's just the nature of web development's asynchronous pattern.
Long version, if it's really, really important to you;
Put a bit of javascript in the page that sends a regular post to your website in the background and set up a serverside agent or service that disposes of the sessions if it doesnt receive these regular "heartbeat" signals.
You can put a javascript postback onto the page's unload() event but dont rely on it, it doesnt always fire.
This happens by default whenever you close your browser, and that's not just for ASP.NET. It's for most server-side programming languages that have a session state. Basically, any cookie that is added that doesn't specify an expiration date, will be deleted when the browser is closed.
Where this doesn't apply, is when you close a tab, which is something you will not have any control over because the tab close event will not get sent back to the Web server.
You can try to do that with javascript. Check it at:
http://www.codeproject.com/Tips/154801/How-to-end-user-session-when-browser-closed
Alternatively you can check you previous session state on every new browser opening and can Session.clear() or Session.abandon() the previous session.
this will make sure that every time you start application you will get new session.
use BasePage in your .net application.
Check the session.sessionid on basepage load.
More Inforamtion how to detect new session in basepage. BasePage.Session.Link
Hope this helps
regards
Shaz
public class BasePage : Page
{
protected string mySessionId;
private CurrentUser _currentUser;
public CurrentUser _CurrentUser
{
get { return ((CurrentUser)HttpContext.Current.Session["myCurrentUser"]); }
set { _currentUser = value; }
}
protected override void OnLoad(EventArgs e)
{
if (Session["myCurrentUser"] != null)
{
if (_CurrentUser.ProUser)
{
mySessionId = Session.SessionID; // it means New Session
}
if (!mySessionId.IsNullOrDefault() && mySessionId != Session.SessionID)
{
Session.Abandon(); //Abandon current session and start new one
}
}
}
}
I think cookies can better meet your requirement here for session management.
it means that session data should not be stored on the server and
should be with your call, so that you don't have to worry about
clearing the data on server.
Yes.First of all Browser automatically clear session when browser is closed. you can try to capture browser close or tab close event in browser using javascript function like on before unload and on unload. Mostly onbefore unload event captures browser close event in chrome, Firefox, IE 11.
You can use Session_End event of Global.aspx
//For Specific Session
Session.Remove("SessionName");
//All the Session
Session.Abandon();

How to count Number of refreshes of web page

I have a web form of Asp.Net, in which I want JavaScript to count how many time i have refreshed the page.
If you want to do it on clientside just save (and retrieve) the information on localstorage every time load event occurs
Do you want to count this per user ? Or for whole application ?
If you are doing for whole application you can use application variable in Global.asax on each page request . But that might get lost if your application recycles .
If you want to do for each user You can use server side sessions or cookies on clientside .
You can set the value in a cookie using js or asp, or in a session value (for a single user) or in application value (for all the users), is not necessary javascript.
You have to put this code server side on page load.
For all users:
Application["refresh_count"] =
Convert.ToInt64(HttpContext.Current.Application["refresh_count"]) + 1;
For a single user with session:
Session["refresh_count"] = Convert.ToInt64(Session["refresh_count"]) + 1;
OR
Response.Cookies["UserSettings"]["refresh_count"] = Convert.ToInt64(Response.Cookies["UserSettings"]["refresh_count"]) + 1;
Response.Cookies["UserSettings"].Expires = DateTime.Now.AddDays(1d);
You can save this in the Session Object.
You can use jQuery calling prepared address.
For example:
$.ajax({
url: ".../countPageRefreshes.aspx",
data: { page: "thisPageAddress" }
})
Then, in countPageRefreshes you can increase number of times, page was refreshed and save it somewhere.

How to get user local time at Page_Load

I have a web page written in ASP.NET and I need to retrieve the end user's local time at Page_Load. I thought about using Javascript to get the local time (by using new Date()) but the problem is that the script is run after the server events.
Any ideas on how to accomplish this?
EDIT: My page is quite complex: it displays a chart with lots of calculated fields from a database, object/fields selection lists, etc; The customer now requested that it should consider the user's timezone and that the timezone should be determined automatically by the web page. The user date is important to determine the chart interval (which day to display data on).
Data loading (since it is so complicated) is done in both Page_Load and Page_PreRender. Giving up these events would require a full page rewrite.
FINAL SOLUTION INSPIRED BY ANSWER:
Here is how I solved the problem eventually. I am keeping the local date in a cookie. Here is the method that sets the cookie:
function SetLocalDateCookie() {
var cookieName = 'LOCALDATE';
var localDate = new Date();
var realMonth = localDate.getMonth() + 1;
var localDateString = localDate.getFullYear() + "/" + realMonth + "/" + localDate.getDate();
setCookie(cookieName, localDateString, 2);
try {
var exdate = new Date();
exdate.setDate(exdate.getDate() + 2);
document.cookie = cookieName + "=" + escape(localDateString) + ";expires=" + exdate.toGMTString();
}
catch (e)
{ }
}
In my Master page I call this method on $(document).ready.
On the page where I use this cookie I added the following code to Page_Init:
if (string.IsNullOrEmpty(CookieHandler.Instance.GetCookie(CookieKeys.LocalDate)))
{
Response.ClearContent();
Response.Write(#"<form id='local' method='post' name='local'>
<script type='text/javascript'>
SetLocalDateCookie();
document.getElementById('local').submit();
</script>
</form>");
Response.Flush();
Response.End();
}
Then I can just use the cookie value in the C# code.
Thank you for your answers/comments!
I'll explain a bit the following code and what lefts for you to do.
At the first request off this page, the code checks if the LocalTime is not already stored in Session and if not it will write a form element, a hidden input and a javascript which will post that form with the local time. The response ends, so your report won't get the chance to be generated.
This submit will immediately create a POST request with the localTime set, then ASP .Net stores this POST value into the Session.
I also added a 302 redirect (Response.Redirect) to the original page, because of the usability. The User made initially a GET request, not a POST, so if he/she wants to refresh the page, the browser will reiterate the last action, which was that form.submit() and not the GET request.
You have now the local time. But you don't have to read it at every request since it can be compared to the UTC time, then with the server's time.
edit: You need to parse the UTC time into a DateTime, but probably it's easy to find the format, though might depend on the user's culture (not sure about this statement).
public ReportPage()
{
this.Init += (o, e) =>
{
// if the local time is not saved yet in Session and the request has not posted the localTime
if (Session["localTime"] == null && String.IsNullOrEmpty(Request.Params["localTime"]))
{
// then clear the content and write some html, a javascript code which submits the local time
Response.ClearContent();
Response.Write(#"<form id='local' method='post' name='local'>
<input type='hidden' id='localTime' name='localTime' />
<script type='text/javascript'>
document.getElementById('localTime').value = new Date();
document.getElementById('local').submit();
</script>
</form>");
//
Response.Flush();
// end the response so PageLoad, PagePreRender etc won't be executed
Response.End();
}
else
{
// if the request contains the localtime, then save it in Session
if (Request.Params["localTime"] != null)
{
Session["localTime"] = Request.Params["localTime"];
// and redirect back to the original url
Response.Redirect(Request.RawUrl);
}
}
};
}
I don't think this would be possible, you can't get the time off the client's local machine at server side.
The only way to achieve this would be using some javascript (as this is client based, so it will use the client's current date/time). But as you've stated, this will be after your server events have been ran, and your web page has been rendered into HTML and sent to the client.
One alternative would be to capture the clients time before the Post Back, but it wouldn't be possible to do this with an inital Page_Load.
How about you place a hidden textbox on the page, attach an OnChange-eventhandler to it in C# and use an OnLoad JavaScript function to set the value to the value you need from the client?
As far as I'm aware, there isn't any way to get the users local time in the Page_Load event as that is executed on the server-side, and would therefore only be aware of the server's local date time.
To get the user's local time you would need to either execute an asynchronous call to the server upon the page loading in JavaScript, or store the local time in a hidden field and then read it on post-back.
Or just use an interstitial page that contains nothing but the js to get local time and redirects to your current page passing the time information via query string or session variable or post

Categories