How to get the accurate total visitors count in ASP.NET

别来无恙 提交于 2019-12-03 09:03:02

You can never get an entirely accurate number: there is no way to (reliably) detect that a user "has navigated to another site" (and left yours) or that that user "closed the browser".

The Session_Start/Session_End way has the problem that Session_End is only called for "InProc" sessions, not if the sessions are stored in StateServer or SqlServer.

What you might be able to do:

  • Hold a Dictionary<string, DateTime> in Application scope. This stored session-id's (the string key) against the time of latest access (the DateTime value)
  • For each request with a valid session, find the session entry in the dictionary and update it's latest-access time (add a new entry if not found)
  • When you want to get the number of online users, first loop through all entries in the dictionary and remove items where the session timeout has passed. The remaining count is the number of online users.

One problem (at least): if one user uses two browsers simultaneously, he has two sessions open and is counted double. If users always log in, maybe you could count on login-id instead of session-id.

I want to propose something completely another: try to use Google Analytic for this. These guys add beta functionality that allows tracking online statistics now.

EDIT: You don't get me. I mentioned not standard Google Analytic functionality. I mentioned new feature - Real-Time. Check next article for details - What’s happening on your site right now? or watch this video - Google Analytics real-time beta

Just as Hans mentioned, you will probably have to switch your session state to StateServer or SQLServer, but this is not something a snippet of code can do. There is a very good reliable and detailed article on codeproject that treats this problem properly.

This is the source code I implemented according to Hans Kesting's suggestion.

Global.asax

void Session_Start(object sender, EventArgs e) 
    {
        System.Collections.Generic.Dictionary<string, DateTime> Visitors =
                            new System.Collections.Generic.Dictionary<string, DateTime>();
        Visitors.Add(Session.SessionID, DateTime.Now);        
        HttpContext.Current.Application.Lock();
        Application["Visitors"] = Visitors;
        HttpContext.Current.Application.UnLock();
    }

HttpHandleder.cs

private static void UpdateVisitors()
    {
        System.Collections.Generic.Dictionary<string, DateTime> Visitors = (System.Collections.Generic.Dictionary<string, DateTime>)HttpContext.Current.Application["Visitors"];
        Visitors[HttpContext.Current.Session.SessionID] = DateTime.Now;
    }

AnyPage.aspx.cs(where you want to get the number of total online users)

 protected int GetCurrentOnlineUsers()
        {
            int total = 0;
            Dictionary<string, DateTime> Visitors = (Dictionary<string, DateTime>)Application["Visitors"];
            foreach (KeyValuePair<string, DateTime> pair in Visitors)
            {
                TimeSpan Remaining = DateTime.Now - pair.Value;
                int remainingMinutes = Convert.ToInt32(Remaining.TotalMinutes);            
                if (remainingMinutes < 21) //Only count the visitors who have been active less than 20 minutes ago.
                    total++;
            }

            return total;
        }

Hans's solution is really great and working exactly what I want but I just found this article on MSDN recently which seems to be the best practice for this purpose.

REF: http://msdn.microsoft.com/en-AU/library/system.web.httprequest.anonymousid.aspx

Global.asax

void Application_Start(Object sender, EventArgs e)
    {
        // Initialize user count property
        Application["UserCount"] = 0;
    }

public void AnonymousIdentification_Creating(Object sender, AnonymousIdentificationEventArgs e)
    {
    // Change the anonymous id
    e.AnonymousID = "mysite.com_Anonymous_User_" + DateTime.Now.Ticks;

    // Increment count of unique anonymous users
    Application["UserCount"] = Int32.Parse(Application["UserCount"].ToString()) + 1;
}

.ASPX file

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
  void Page_Load(object sender, EventArgs e)
    {
      if (Application["UserCount"] != null)
      {
          lblUserCount.Text = Application["UserCount"].ToString();
          lblCurrentUser.Text = Request.AnonymousID;
      }
  }    
</script>


<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>AnonymousID Example</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        Number of users: 
        <asp:Label ID="lblUserCount" Runat="server"></asp:Label><br />
    Current user:
        <asp:Label ID="lblCurrentUser" Runat="server"></asp:Label><br />
    </div>
    </form>
</body>
</html>

Why not check the user IP to get unique visits. Add them to a hashset so you can do nice things like make a heatmap using a location API:

 // count users online on all desktopsites
        void Session_Start(object sender, EventArgs e)
        {
            try
            {
                // lock application object
                Application.Lock();

                // get hashset containing all online ip adresses
                var ips = (HashSet<string>)Application["visitors_online_list_ip"];

                // get user ip
                var ip = HttpContext.Current.Request.UserHostAddress;

                // add ip to hashset
                ips.Add(ip);

                // store ip in session to delete when session ends
                Session["ip"] = ip;

                // save hashset
                Application["visitors_online_list_ip"] = ips;

                // unlock application object 
                Application.UnLock();
            }
            catch {}
        }

        void Session_End(object sender, EventArgs e)
        {
            try
            {
                // lock application object
                Application.Lock();

                // get hashset containing all online ip adresses
                var ips = (HashSet<string>)Application["visitors_online_list_ip"];

                // get user ip from Session because httpcontext doesn't exist
                var ip = Session["ip"].ToString(); ;

                // remove ip from hashset
                ips.Remove(ip);

                // save hashset
                Application["visitors_online_list_ip"] = ips;

                // unlock application object 
                Application.UnLock();
            }
            catch {}
        }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!