获取asp.net mvc中的在线用户列表

maX*_*maX 3 asp.net asp.net-mvc

我的应用程序中有一个页面,它总是显示更新的在线用户列表.现在,为了保持存储在应用程序对象中的列表更新,我执行以下步骤

  1. 登录时将用户添加到列表中

  2. 注销时删除用户

  3. 然后为了处理浏览器关闭/导航的情况,我有一个时间戳和集合中的用户名每隔90秒调用一次ajax更新时间戳.

问题:我需要每隔120秒清理一次该列表,以删除带有旧时间戳的条目.

如何在我的Web应用程序中执行此操作?即每2分钟调用一次函数.

PS:我想过使用调度程序每2分钟调用一次web服务,但托管环境不允许任何调度.

Ant*_*onK 8

在全局过滤器中执行以下操作.

public class TrackLoginsFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Dictionary<string, DateTime> loggedInUsers = SecurityHelper.GetLoggedInUsers();

        if (HttpContext.Current.User.Identity.IsAuthenticated )
        {
            if (loggedInUsers.ContainsKey(HttpContext.Current.User.Identity.Name))
            {
                loggedInUsers[HttpContext.Current.User.Identity.Name] = System.DateTime.Now;
            }
            else
            {
                loggedInUsers.Add(HttpContext.Current.User.Identity.Name, System.DateTime.Now);
            }

        }

        // remove users where time exceeds session timeout
        var keys = loggedInUsers.Where(u => DateTime.Now.Subtract(u.Value).Minutes >
                   HttpContext.Current.Session.Timeout).Select(u => u.Key);
        foreach (var key in keys)
        {
            loggedInUsers.Remove(key);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

检索用户列表

public static class SecurityHelper
{
    public static Dictionary<string, DateTime> GetLoggedInUsers()
    {
        Dictionary<string, DateTime> loggedInUsers = new Dictionary<string, DateTime>();

        if (HttpContext.Current != null)
        {
            loggedInUsers = (Dictionary<string, DateTime>)HttpContext.Current.Application["loggedinusers"];
            if (loggedInUsers == null)
            {
                loggedInUsers = new Dictionary<string, DateTime>();
                HttpContext.Current.Application["loggedinusers"] = loggedInUsers;
            }
        }
        return loggedInUsers;

    }
}
Run Code Online (Sandbox Code Playgroud)

不要忘记在global.asax中注册过滤器.有一个应用程序设置来关闭它可能是一个好主意.

GlobalFilters.Filters.Add(new TrackLoginsFilter());
Run Code Online (Sandbox Code Playgroud)

还要在注销时删除用户以使其更准确.

SecurityHelper.GetLoggedInUsers().Remove(WebSecurity.CurrentUserName);
Run Code Online (Sandbox Code Playgroud)

  • 您的解决方案非常有用,也很好,但还有一个问题是我使用 setauthcookie 进行登录,因此如果用户不单击“记住我”,请关闭浏览器注销用户。但是它还是在LoggedInUsers里面? (2认同)

dev*_*dev 6

在您的帐户控制器中

   public ActionResult Login(LoginModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                if (HttpRuntime.Cache["LoggedInUsers"] != null) //if the list exists, add this user to it
                {
                    //get the list of logged in users from the cache
                    List<string> loggedInUsers = (List<string>)HttpRuntime.Cache["LoggedInUsers"];
                    //add this user to the list
                    loggedInUsers.Add(model.UserName);
                    //add the list back into the cache
                    HttpRuntime.Cache["LoggedInUsers"] = loggedInUsers;
                }
                else //the list does not exist so create it
                {
                    //create a new list
                    List<string> loggedInUsers = new List<string>();
                    //add this user to the list
                    loggedInUsers.Add(model.UserName);
                    //add the list into the cache
                    HttpRuntime.Cache["LoggedInUsers"] = loggedInUsers;
                }
                if (!String.IsNullOrEmpty(returnUrl))
                {
                    return Redirect(returnUrl);
                }
                else
                {

                    return RedirectToAction("Index", "Home");
                }
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }


    public ActionResult LogOff()
    {
        string username = User.Identity.Name; //get the users username who is logged in
        if (HttpRuntime.Cache["LoggedInUsers"] != null)//check if the list has been created
        {
            //the list is not null so we retrieve it from the cache
            List<string> loggedInUsers = (List<string>)HttpRuntime.Cache["LoggedInUsers"];
            if (loggedInUsers.Contains(username))//if the user is in the list
            {
                //then remove them
                loggedInUsers.Remove(username);
            }
            // else do nothing
        }
        //else do nothing
        FormsAuthentication.SignOut();
        return RedirectToAction("Index", "Home");
    }
Run Code Online (Sandbox Code Playgroud)

在你的局部视图中.

@if (HttpRuntime.Cache["LoggedInUsers"] != null)
{
    List<string> LoggedOnUsers = (List<string>)HttpRuntime.Cache["LoggedInUsers"];
    if (LoggedOnUsers.Count > 0)
    {
    <div class="ChatBox">
        <ul>
            @foreach (string user in LoggedOnUsers)
            {
                <li>
                    <div class="r_row">
                       <div class="r_name">@Html.Encode(user)</div>
                    </div>
                </li>
            }
        </ul>
    </div>
    }
}
Run Code Online (Sandbox Code Playgroud)

用户登录时呈现此部分视图.

使用此脚本调用90秒

<script type="text/javascript">
    $(function () {
        setInterval(loginDisplay, 90000);
    });

    function loginDisplay() {
        $.post("/Account/getLoginUser", null, function (data) {

        });
    }
</script>
Run Code Online (Sandbox Code Playgroud)


Pra*_*eep 2

这是白象解决方案。

不要在应用程序对象中维护此列表,而是在数据库中维护此列表。然后,您可以使用数据库作业定期处理该列表。在此对象上建立 SQL 通知,以便每次清除此列表时,您都可以在应用程序中获得刷新的数据。