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

梦想与她 提交于 2020-01-01 03:44:11

问题


I want to know the number of visitors online on my site. I did my research and found two solutions.

Source: Code Project
Online active users counter in ASP.NET

It is easy to setup and easy to use but it increases the user count for every Ajax request/response too. My home page alone has 12 Ajax requests(8 requests to one page and 4 requests to another page). This dramatically increases the user count.

Source: Stack Overflow Q/A
Count the no of Visitors This one works exactly the same as the previous one.

Source: ASP.Net Forum How to see "who is online" using C#

This one looks better than the previous two. Here is the detail code of this solution.

void Application_Start(object sender, EventArgs e) 
    {
        // Code that runs on application startup
        HttpContext.Current.Application["visitors_online"] = 0;
    }

void Session_Start(object sender, EventArgs e) 
    {
        Session.Timeout = 20; //'20 minute timeout
        HttpContext.Current.Application.Lock();
        Application["visitors_online"] = Convert.ToInt64(HttpContext.Current.Application["visitors_online"]) + 1;
        HttpContext.Current.Application.UnLock();
    }

void Session_End(object sender, EventArgs e) 
    {
        HttpContext.Current.Application.Lock();
        Application["visitors_online"] = Convert.ToInt64(HttpContext.Current.Application["visitors_online"]) - 1;
        HttpContext.Current.Application.UnLock();
    }

It seems to be able to ignore the increasing the count for every Ajax response but it still adds up for each page refresh or page request.

Is there any approach to count the accurate number of online visitors in ASP.Net?


回答1:


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.




回答2:


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




回答3:


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.




回答4:


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;
        }



回答5:


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>



回答6:


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 {}
        }


来源:https://stackoverflow.com/questions/11389880/how-to-get-the-accurate-total-visitors-count-in-asp-net

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