How To Show Currently Online Users (Members) Using Asp.Net MVC And Identity

How To Show Currently Online Users (Members) Using Asp.Net MVC Identity

Introduction

In this post, I’m going to show you how to implement a feature to show who is online, and a link to their profile(which not implemented in my sample). In the old Membership system of ASP.NET, things were a little easier, you could get the list of all users, also you could see who is online and who is not, and consequently do something like this, but with new Identity system, things are not as easy as it were, you have to do your custom implementation for that, which most of the time, is not as efficient as it should be. The solution I’m going to use here is the method I’ve used in one of my clients project, and to be honest, I’m not sure if it is the most efficient way of doing it, without using something like SignalR, but if you think it is not, I’m all ears and eager to make it more efficient.

 

Adding Logged In Users To The List Of Online Users

The first step we need to take, is to add the currently logging in user name (which is user email in this case) along with his/her date and time of doing it, to a our dictionary, we do it in our login action if the login succeed, here is the code:

case SignInStatus.Success:
                    {
                        //if the list exists, add this user to it
                        if (HttpRuntime.Cache["LoggedInUsers"] != null)
                        {
                            //get the list of logged in users from the cache
                            var loggedInUsers = (Dictionary)HttpRuntime.Cache["LoggedInUsers"];

                            if (!loggedInUsers.ContainsKey(model.Email))
                            {
                                //add this user to the list
                                loggedInUsers.Add(model.Email, DateTime.Now);
                                //add the list back into the cache
                                HttpRuntime.Cache["LoggedInUsers"] = loggedInUsers;
                            }
                        }

                        //the list does not exist so create it
                        else
                        {
                            //create a new list
                            var loggedInUsers = new Dictionary();
                            //add this user to the list
                            loggedInUsers.Add(model.Email, DateTime.Now);
                            //add the list into the cache
                            HttpRuntime.Cache["LoggedInUsers"] = loggedInUsers;
                        }

                        return RedirectToLocal(returnUrl);
                    }

Here, first we check if our Dictionary<string, DateTime> that we stored in the cache is empty, if it’s not, we go ahead and retrieve it form the cache, and if our dictionary doesn’t contain the current user name, we add the user and the DateTime of logging in to our dictionary, and pass our dictionary to the cache for later retrieval.
On the other hand, if there is no dictionary, we go ahead and create one, and add the user to it, and save the dictionary to the cache for later use.

Keeping The Active Users In The List, And Removing Inactive Users

Next, we check if the user is still online, if he/she is, we are going to update the DateTime in the dictionary, and in the next bit of code, we loop through the user list, and if he wasn’t online for the past 10 minutes, we will remove him/her form the list, I’ll explain it in more detail, first let’s take a look at the code, add this in global.asax:

protected void Application_EndRequest()
        {
            var loggedInUsers = (Dictionary)HttpRuntime.Cache["LoggedInUsers"];

            if (User.Identity.IsAuthenticated)
            {
                var userName = User.Identity.Name;
                if (loggedInUsers != null)
                {
                    loggedInUsers[userName] = DateTime.Now;
                    HttpRuntime.Cache["LoggedInUsers"] = loggedInUsers;
                }
            }

            if (loggedInUsers != null)
            {
                foreach (var item in loggedInUsers.ToList())
                {
                    if (item.Value < DateTime.Now.AddMinutes(-10))
                    {
                        loggedInUsers.Remove(item.Key);
                    }
                }
                HttpRuntime.Cache["LoggedInUsers"] = loggedInUsers;
            }

        }

Here, we first retrieve the list of users from the cache, and if the user is authenticated, we get the current user name, and if our list of users wasn’t null, we go ahead and use the key of the dictionary, which here is the user name, and update the value, which here is the DateTime value.

In the next section, we check if the list of users is not empty, and if not, we loop though the list and remove any item that its DateTime value is more than ten minutes in the past, and save the value back to our cache, this way we remove the users who aren’t made any request to the site, and keep the users who did made a request in our list.

Showing Online Users On The Page

In the end, we are going to make some pages to show the online users, to do this, we simply read the dictionary of users form cache and show it on the page, we use a partial view here:

@if (HttpRuntime.Cache["LoggedInUsers"] != null)
{
    var loggedOnUsers = HttpRuntime.Cache["LoggedInUsers"] as Dictionary<stringDateTime>;
 
    if (loggedOnUsers != null)
    {
        <div class="LoggedInUserBox">
            <span> Online Users: </span>
            @foreach (var item in loggedOnUsers)
            {
                <a href="/Users/Panel/UserProfile/@item.Key">@item.Key</a>
                @:&nbsp;
            }
        </div>
    }
}

You can download the sample project which used this method from here, also as a bonus to this article, I’ve included some code to show all of the online users, check the _Stats partial and some code in global.asax for that.

Conclusion

First let me caution you that we do a loop through online users in every end request event, and this might slow your site down, before using this method, test it to see if it has any impact on your site performance, there was other methods for doing this which involved using SignalR and sending heart beat request to the server, you can read about it here. Generally when implementing such features there is always compromises to be made. I welcome any comment and critique about the solution I’ve proposed, tell me what you think and how did it worked for you in the comment section.

Share...
 

Hamid Mosalla

Hi, I'm Hamid Mosalla, I'm a software developer, indie cinema fan and a classical music aficionado. Here I write about my experiences mostly related to web development and .Net.