How is possible to count all application on-line "Sessions"?
Not all connected PC (from ID address), but all sessions.
E.g.: If in same PC open Chrome and Firefox with my app, the counter must be 2.
If you have only one instance of the application, it is easier. You can create a middleware and store session ids in a Set. Then to get the count, you can just use the element count in the Set. If you have multiple instances of the application, you need to create a common db like Redis, and use their Set features. Don't forget to remove the session ids when the session ends, or perhaps make them expire after a while unless renewed.
Related
I want to save some small info (say, user's device id) about the user, after or during sign-in. This data is dynamic, and I'd like the lookup to be very fast (without database hit), as I need it in many controllers. I tried adding it to user's claims like this:
((ClaimsIdentity)User.Identity).AddClaim(new Claim("UserDeviceId", userDeviceId));
to subsequently retrieve it like this: User.FindFirstValue("UserDeviceId") inside any controller. But it seems that the data is not persisted between requests! It returns NULL on another HTTP request.
I use standard SingInManager.PasswordSignIn() to sign the user in. I don't have claim store at all - I don't use default Identity EF implementation, I supply my own stores (IUserStore, IUserPasswordStore, and IUserRoleStore implementations). But even if I did, this data is dynamic and should not be persisted to / retrieved from a storage at all. The data is available upon sign in (basically client app sends hardware id).
As I understand, the dynamically added claim gets wiped out because it is never injected into the cookie, when I add it to User.Identity it just adds to in-memory instance, which gets overwritten by the cookie at next request. (or at least that's my best guess).
Is there any solution to this problem? I'd really like to avoid setting up Session mechanism, all I need is a single small value persisted across the requests, and even though strictly speaking it might not fully qualify as a "user claim", it is (conceptually) very close - it is a device id the user is currently connected from.
I use User.FindFirstValue(ClaimTypes.NameIdentifier) in my controllers to get userId without any performance impact, and it is very convenient. It's setup by Identity itself obviously. I'd like to have similar mechanism for another identifier, preferably without rewriting half of Asp.Net Identity :) Is that doable? If not, what's my best alternative (besides setting up Session storage or supplying the value in every request)?
We use "Websites" in Windows Azure. I need to get unique application instance. I know about "RoleEnvironment.CurrentRoleInstance.Id" but as long as I know it works only for web roles. So I'm thinking about the following way to get unique application ID for each instance. I'm interested whether it's OK to use. Or am I missing something?
Once the application is started I generate some unique name (in the "Application_Start" method). For example, Guid.NewGuid().
Once it's done I store this unique value in some static variable.
When a second instance in started, steps 1 and 2 are repeated and some other new unique name is generated
This way I have unique names for each instance. Of course, once a site (or some instance) is restarted I'll get new absolutely unique values. But it's fine in our case.
Please let me know if you find any pitfalls in this solution
You could use the COMPUTERNAME or the WEBSITE_INSTANCE_ID environment variables instead.
In fact, you can browse the full list of environment variables at https://<yoursite>.scm.azurewebsites.net/Env
This should work, but of course the GUID will only be around for the lifetime of the w3wp process. So you would have unique names per w3wp process which would imply that you would have unique names for each instance.
If you wanted to use a more targeted unique name, you could experiment with the ARR affinity cookie. Azure Web app runs with a sticky session load balancer (when running with multiple instances) by default. It injects ARR affinity cookie in the HTTP response that helps in redirecting a user to the same instance with which it established the session at the first time.
You can also use the environment variables to uniquely identify the instance, i.e. Environment.ComputerName.
A fairly simple question really.
I am trying to hold a series of values in a Cached object, which is populated via a range of session objects.
It isn't, but we can kind of think of it as like a chat system.
There are multiple users, signed in on multiple machines, therefore multiple session states should exist.
In order to give a multi-user view, the master collection is held in the cache (so it can be viewed across the multiple sessions)
When a new machine starts a new session, the cache object is updated, but when a session ends, I need to be able to remove an item by Key from the Cache, but the key will be lost AFTER session ends!
So... is there any way to grab a value immediately before a session ends?
I created two different very simple apps (ASP .NET) and host on the local iis.
Both apps are open in same browser in two tabs. In first application (AppA) I store some data in Session (Session["name"] = "john") and in second application (AppB) I read this value. When I explore cookies (with FireCookie) I saw that SessionIDs for both applications are same. Also, In both apps SessionID is printed and are the same. When I try get this value in AppB from session (with correct key), session is empty, but session id is still same. In AppA session data are still alive.
Why session data are different when both apps ask web server (with same session id) to return data?
The sessions are not shared, because it are different applications. So even when they got the same id, they don't "know" eachother. Check out this article for a possible solution http://www.codeguru.com/article.php/c19357
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.