ASP.NET MVC3:已连接的客户端数量

时间:2012-07-21 13:48:52

标签: asp.net asp.net-mvc-3 session count

在我的ASP.NET MVC3 Web应用程序中,我想添加一条显示当前正在浏览该站点的用户数量的小消息。

我目前正在使用Session_StartSession_End应用程序事件来增加或减少Global.asax中的静态属性。

这有效,但根本不准确。由于我的会话超时配置为20mn,因此更新之间会有很大的延迟。

有更优雅,更精确的方法吗?

我曾想过通过AJAX调用一个动作,它只对Session.Abandon() javascript事件window.onbeforeunload进行调用,但每次用户更改页面时都会调用它。有没有办法确定用户何时关闭浏览器或离开域?

欢迎任何提示,评论或代码示例!

以下是当前代码的相关部分:

public class MvcApplication : System.Web.HttpApplication
{
    public static int UsersConnected { get; set; }

    protected void Session_Start(object sender, EventArgs e)
    {
        Application.Lock();
        UsersConnected++;
        Application.UnLock();
    }

    protected void Session_End(object sender, EventArgs e)
    {
        Application.Lock();
        UsersConnected--;
        Application.UnLock();
    }

    ...
}

2 个答案:

答案 0 :(得分:2)

好的,这有点棘手,但我已经找到了一个“好的”解决方案。

首先,我在Global.asax 中创建了一个静态字典,它将存储客户端的IP地址及其上次轮询日期。

public class MvcApplication : System.Web.HttpApplication
{
   public static Dictionary<string, DateTime> ConnectedtUsers { get; set; }

   protected void Application_Start()
   {
        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
        ConnectedtUsers = new Dictionary<string, DateTime>();
   }

   ...
}

然后,在我的 CommonsController 中,我创建了这个动作,它将添加新客户端,删除在过去30秒内未被轮询的客户端并更新已注册客户端的轮询日期:

public class CommonsController : Controller
{
    ...

    public JsonResult UserConnected()
    {
        string ip = Request.UserHostAddress;

        if (MvcApplication.ConnectedtUsers.ContainsKey(ip))
        {
            MvcApplication.ConnectedtUsers[ip] = DateTime.Now;
        }
        else
        {
            MvcApplication.ConnectedtUsers.Add(ip, DateTime.Now);
        }

        int connected = MvcApplication.ConnectedtUsers.Where(c => c.Value.AddSeconds(30d) > DateTime.Now).Count();

        foreach (string key in MvcApplication.ConnectedtUsers.Where(c => c.Value.AddSeconds(30d) < DateTime.Now).Select(c => c.Key))
        {
            MvcApplication.ConnectedtUsers.Remove(key);
        }

        return Json(new { count = connected }, JsonRequestBehavior.AllowGet);
    }
}

最后,在我的布局页面上,添加了这段代码,它每30秒调用一次我的动作并输出结果:

<span id="connectedUsers"></span>

<script type="text/javascript">
    function PollUsers()
    {
        $(function() {
            $.getJSON("/Commons/UserConnected", function(json){ $('#connectedUsers').text(json.count + " user(s) connected")}); 
        });
    }

    setInterval(PollUsers, 30000);
</script>

当然,来自同一IP的多个用户将计入一个用户。但这是迄今为止我尝试过的最佳解决方案。

答案 1 :(得分:0)

你可以在卸载体事件上从javascript调用webmethod。 http://www.codeproject.com/Tips/89661/Execute-server-side-code-on-close-of-a-browser 最好的问候