Is it a good idea to set day-long Session Time Out? - asp.net

Everytime my page is reloaded, I reset the session time out to 1 day.
Is this a good idea in the shared hosting environment?

No, it's a very bad idea, and even rude, as every new session created will consume more and more resources and enough sessions will bring your and every other hosted app to its knees.
Are you just trying to avoid having to log in repeatedly? Because you can use alternative methods of authentication with cookies once you pass the initial test.

That is decidedly odd, you'd keep in RAM every single session object with all their object handles that you create throughout each day.
If you're just trying to prevent timeouts during use, why not just use an ajax call every 30sec-2min to a heart-beat page so the server refreshes the timeout for your application. This way, a 10min timeout will be more than sufficient.

Related

Session state blocking async ajax call from processed concurrently

I am trying to make 6 asynchronous jQuery ajax calls to my .NET Page Method all at once on document.ready to request for different sets of data from the database and in return render as charts to users.
Problem is that when one chart takes a long time to generate, it locks up generation of the next 5 charts, for instance, when each chart takes 1 min to generate, the user will be approx waiting for 6 mins, instead of 1 - 2 mins which i thought it will be when using async ajax calls and page method gets processed in parallel.
After reading a lot of useful posts in this forum, i found that this is because I have to read and write to session objects within the page methods, and asp.net will lock the whole request, as a result making them run sequentially.
I have seen people suggesting to set the session state to read only in #Page tag, but it will not address my problem because i need write to the session as well. I have considered moving from inProc session to sql database session, but my session object is not serializable and is used across the whole project. I also cannot change to use Cache instead because the session contains user specific details.
Can anyone please help and point me to the right direction? I have been spending days to investigate this page inefficiency and still haven't yet found a nice way yet.
Thanks in advance
From my personal experience, switching to SQL session will NOT help this problem as all of the concurrent threads will block in SQL as the first thread in will hold an exclusive lock on one or more rows in the database.
I'm curious as to why your session object isn't serializable. The only solution that I can think of is use a database table to store the user specific data that you are keeping in session and then only holding onto a database lock for as long as it takes you to update the user data.
You can use the ASP.NET session id or other unique cookie value as the database key.
The problem may not be server side at all.
Browsers have a built in limit on how many concurrent HTTP requests they will make - this is part of the HTTP/1.1 spec which sugests a limit of 2.
In IE7 the limit is 2. in IE8 it is 6. But when a page loads you could easily hit 6 due to the concurrent requests for CSS, JS, images etc.
A good source of info about these limits is BrowserScope (see Connections per Hostname column).
What about combining those 6 requests into 1 request? This will also load a little faster.

Access Session on End?

I am trying to "log" forcefully when a user has been inactive and or the session has ended (either by inactivity or more importantly, when the browser has closed).
I dont want to use any silly AJAX solution to perform a post every few minutes for "im alive" or call when the browser is closed.
I was under the impression that if you store an object in Session, and you reach the Session_End event, then you will not be able to gain access to anything stored in Session as its ended.
But from some testing I have done, it appears that this is probably the last chance you can obtain access to the object.
Could this be true? is it reliable?
using ASP.NET 4.0 here.
Typically there are two things done.
The first is that a javascript timer is added to the client, not as a heartbeat, but rather as a reminder. If they are close to the session ending, then it simply says "session is about to end. Are you still there?" If so, then it does the "silly" post to ensure the server keeps the session going. This is purely to be nice to your users.
The second (and point of your question) is that you put something in session_end in order to clean up the session. Reliable? well.. most of the time.
Session_End won't run if the app pool is recycled. However, assuming the app pool is ok then yes it will execute when the session expires. The app pool can be recycled for a LOT of reasons ranging from the app crashing to exceeded memory usage to simply because it's been a while since the last reset. This is configurable in IIS.
Would I trust session_end? No. Not 100%. Of course, I wouldn't put anything inside of a session object that would require me to trust it 100% anyway.
For logging the timeout You can use the Global events to log at timeout. See this link for order of events http://www.techrepublic.com/article/working-with-the-aspnet-globalasax-file/5771721

What is exact event(global.asax) to clear cache in asp.net

Im working on asp.net website.
In some pages I'm saving the datatable into chache as
cache["dt"]=dt;
and using whereever I want in that page by fetching from chache.
I'm thinking that whenever session close I want to clear session in session_end event of global.asax file.
as cache["dt"]=null;
What is the better location to close either application_end or session end.
If I close in session_end will it affect to another user?
Please provide me clear helpful info regarding this.
Thanks
Since you are putting the datatable in Cache, meaning, that it's shared by all the users, then there's no right place/need to do this, since the only time when it actually needs to be removed is when the application ends and at that point all resources are freed; your application is no longer running.
Perhaps what you should/meant to do was to put the datatable in Session. If that is what you want, then you could remove it OnSession_End in Global.asax but know that SessionEnd is not guaranteed to fire. You can also do Session.Abandon() when the user logs out, which will clear all session objects.
I think you misunderstood the concept between Application Data, Session Data, and Cache. These three of them all different things.
Application Data/State stores the information available in application scope, i.e. all session/user can access these data.
Session Data store info for the current session data. The duration of the session can be specified in the configuration files.
Cache stores frequently used data. And this data may be costly to regenerate every time.
In your case, since you are using cache, I assume that this cache stores some frequently used data. Ideally, this cache should always be valid, as long as the information does not changes.
As such, my recommendations is to keep this cache value as long as possible.

How to find how many people are online in a website

I have to show how many people are online in that site. The site has developed by using ASP.NET 2.0. Currently I am using the Session start (increase by 1) and Session End Event (decrease by 1) in Global.asax. But the Session_End Event not calling properly most of the times. Is there any better way to achieve this?
You're not going to get much better then incrementing in Session_Start and decrementing in Session_End unless you use some other means like a database.
When you are authenticating your requests you could update a timestamp in the database to show that the user has been active, and after a given time (say 15 minutes), the query that collects the number of concurrent users ignores that row in the database (thus decrementing the count).
A quick Google search revealed a handy way of doing this with a HttpModule.
All in all, Yohann did a great job with this. It does implement a set timeout that was suggested above, but otherwise there is no set way of doing this accurately outside of checking the server's perfmon.exe and checking the WebService >> WebAppPool's count of current connections.
When I implemented this myself I used a SQL Server table to store a date/time and user info on authentication. I decremented the count by re-assesing and matching the IP addresses whenever I had to refresh the data cache (once every 10 mins).
We have the same issue in a project, after tried several methods, we end with tracking idle time of each user, when the idle time is over the session timeout, we consider the user is not online anymore. of course you also need to consider the other issue such as the user log off, or log back in after timeout...
I've done this before and can attest that Session_End will only be called if you manually destroy the session (Session.Abandon). When you think about it, it makes sense. If the user isn't on the website, the code never gets executed.
What I did was store a hashtable in Application state that contained the Username and a Datetime for the last time the user was seen on the site. For every page load I would call a function that would either insert or update this value for the current user. Then it would cull the entire list and remove all of the entries that are older than the session timeout (20 minutes or whatever). Remember to use lock or sync to avoid race conditions when making changes to this list.
This has the added benefit of not only knowing how many people, but specifically which users.
If you don't have something unique like a Username, you can use Session.SessionID instead. It should be unique per visitor of your site.
But be careful, using an Application or App Instance state variable has its own share of problems since it won't share between processes in "Web Garden Mode" or in a multi-server setup. You would need a more persistent medium such as a database or distributed cache for larger scale setups.

How do I explicitly set asp.net sessions to ONLY expire on closing the browser or explicit logou?

By default the session expiry seems to be 20 minutes.
Update: I do not want the session to expire until the browser is closed.
Update2: This is my scenario. User logs into site. Plays around the site. Leaves computer to go for a shower (>20 mins ;)). Comes back to computer and should be able to play around. He closes browser, which deletes session cookie. The next time he comes to the site from a new browser instance, he would need to login again.
In PHP I can set session.cookie_lifetime in php.ini to zero to achieve this.
If you want to extend the session beyond 20 minutes, you change the default using the IIS admin or you can set it in the web.config file. For example, to set the timeout to 60 minutes in web.config:
<configuration>
<system.web>
<sessionState timeout="60" />
... other elements omitted ...
</system.web>
... other elements omitted ....
</configuration>
You can do the same for a particular user in code with:
Session.Timeout = 60
Whichever method you choose, you can change the timeout to whatever value you think is reasonable to allow your users to do other things and still maintain their session.
There are downsides of course: for the user, there is the possible security issue of leaving their browser unattended and having it still logged in when someone else starts to use it. For you there is the issue of memory usage on the server - the longer sessions last, the more memory you'll be using at any one time. Whether or not that matters depends on the load on your server.
If you don't want to guesstimate a reasonable extended timeout, you'll need to use one of the other techniques already suggested, requiring some JavaScript running in the browser to ping the server periodically and/or abandon the session when a page is unloaded (provided the user isn't going to another page on your site, of course).
You could set a short session timeout (eg 5 mins) and then get the page to poll the server periodically, either by using Javascript to fire an XmlHttpRequest every 2 minutes, or by having a hidden iframe which points to a page which refreshes itself every 2 minutes.
Once the browser closes, the session would timeout pretty quickly afterwards as there would be nothing to keep it alive.
This is not a new problem, there are several scenarios that must be handled if you want to catch all the ways a session can end, here are general examples of some of them:
The browser instance or tab is closed.
User navigates away from your website using the same browser instance or tab.
The users loses their connection to the internet (this could include power loss to user's computer or any other means).
User walks away from the computer (or in some other way stops interacting with your site).
The server loses power/reboots.
The first two items must be handled by the client sending information to the server, generally you would use javascript to navigate to a logout page that quickly expires the session.
The third and fourth items are normally handled by setting the session state timeout (it can be any amount of time). The amount of time you use is based on finding a value that allows the users to use your site without overwhelming the server. A very rough rule of thumb could be 30 minutes plus or minus 10 minutes. However the appropriate value would probably have to be the subject of another post.
The fifth item is handled based on how you are storing your sessions. Sessions stored in-state will not survive a reboot since they are in the computer's ram. Sessions stored in a db or cookie would survive the reboot. You could handle this as you see fit.
In my limited experience when this issue has come up before, it's been determined that just setting the session timeout to an acceptable value is all that's needed. However it can be done.
This is default. When you have a session, it stores the session in a "Session Cookie", which is automatically deleted when the browser is closed.
If you want to have the session between 2 browser session, you have to set the Cookie.Expired to a date in the feature.
Because the session you talk about is stored by the server, and not the client you can't do what you want.
But consider not using ASP.NET server side session, and instead only rely on cookies.
Unfortunately due to the explicit nature of the web and the fact there is no permanent link between a website server and a users browser it is impossible to tell when a user has closed their browser. There are events and JavaScript which you can implement (e.g. onunload) which you can use to place calls back to the server which in turn could 'kill' a session - Session.Abandon();
You can set the timeout length of a session within the web.config, remember this timeout is based on the time since the last call to the server was placed by the users browser.
Browser timedout did not added.
There's no way to explicitly clear the session if you don't communicate in some way between the client and the server at the point of window closing, so I would expect sending a special URI request to clear the session at the point of receiving a window close message.
My Javascript is not good enough to give you the actual instructions to do that; sorry :(
You cant, as you can't control how the html client response.
Actually why you need to do so? As long as no one can pick up the session to use again, it would expire after that 20 minutes. If resources does matter, set a more aggressive session expiry (most hosting companies did that, which is horribly annoying) or use less objects in session. Try to avoid any kind of object, instead just store the keys for retrieving them, that is a very important design as it helps you to scale your session to a state server when you get big.
Correct me if I am misreading the intent of your question, but the underlying question seems to be less about how to force the session to end when a user closes the browser and more about how to prevent a session from ending until the browser is closed.
I think the real answer to this is to re-evaluate what you are using sessions to do. If you are using them to maintain state, I agree with the other responses that you may be out of luck.
However, a preferred approach is to use a persistent state mechanism with the same scope as the browser session such as a cookie that expires when the browser is closed. That cookie could contain just enough information to re-initiate the session on the server if it has expired since the last request. Combined with a relatively short (5-10 min) session timeout, I think this gives you the best balance between server resource usage and not making the user continually "re-boot" the site.
Oh you have rewritten the question.
That one is absolutely feasible, as long as javascript is alive. Use any timed ajax will do. Check with prototype library http://www.prototypejs.org PeriodicalExecutor or jQuery with the ajax + timer plugin. Setup a dummy page which your executor will call from time to time, so your session is always alive unless if he logouts (kill the ajax timer in the same time) or close browser (which means the executor is killed anyway)

Resources