如何在ASP.NET中获得准确的访问者总数

时间:2012-07-09 06:16:26

标签: c# asp.net c#-2.0

我想知道我网站上的在线访客人数。我做了我的研究,找到了两个解决方案。

资料来源:代码项目
Online active users counter in ASP.NET

它易于设置且易于使用,但它也增加了每个Ajax请求/响应的用户数。仅我的主页有12个Ajax请求(对一个页面的8个请求和对另一个页面的4个请求)。这大大增加了用户数量。

来源:Stack Overflow Q / A
Count the no of Visitors 这个与前一个完全相同。

资料来源:ASP.Net论坛 How to see "who is online" using C#

这个看起来比前两个好。以下是此解决方案的详细代码。

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

似乎可以忽略每个Ajax响应的计数增加,但它仍然会增加每个页面刷新或页面请求。

是否有任何方法可以计算ASP.Net中准确的在线访问者数量?

6 个答案:

答案 0 :(得分:5)

您永远无法获得完全准确的数字:无法(可靠地)检测到用户“已导航到另一个网站”(并离开您的网站)或该用户“关闭了浏览器”。

Session_Start / Session_End方式的问题是Session_End仅针对“InProc”会话调用,而不是会话存储在StateServer或SqlServer中。

您可以做的事情:

  • 在应用范围中保留Dictionary<string, DateTime>。此存储的session-id(字符串键)与最新访问时间(DateTime值)
  • 相对应
  • 对于具有有效会话的每个请求,在字典中查找会话条目并更新它的最新访问时间(如果未找到则添加新条目)
  • 当您想获得在线用户的数量时,首先遍历字典中的所有条目并删除会话超时已经过去的项目。剩余的数量是在线用户数。

一个问题(至少):如果一个用户同时使用两个浏览器,他会打开两个会话并计算为双倍。如果用户总是登录,也许您可​​以依靠login-id而不是session-id。

答案 1 :(得分:1)

我想提出另一个完全不同的建议:尝试使用Google Analytic。这些人添加了测试功能,允许现在跟踪在线统计数据。

编辑:你没有得到我。我提到的不是标准的Google Analytic功能。我提到了新功能 - 实时。查看下一篇文章了解详情 - What’s happening on your site right now?或观看此视频 - Google Analytics real-time beta

答案 2 :(得分:0)

就像Hans提到的那样,您可能需要将会话状态切换为StateServerSQLServer,但这不是一段代码可以做的事情。有一个非常好的可靠和detailed article on codeproject正确处理这个问题。

答案 3 :(得分:0)

这是我根据Hans Kesting的建议实施的源代码。

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(您希望获得在线总用户数)

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

答案 4 :(得分:0)

汉斯的解决方案非常棒,并且正是我想要的,但我刚刚在MSDN上发现这篇文章,这似乎是最佳实践。

参考: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文件

<%@ 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>

答案 5 :(得分:0)

为什么不检查用户IP以获得唯一身份访问权限。将它们添加到哈希集中,这样您就可以使用位置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 {}
        }