C# asp.net MVC:何时更新 LastActivityDate?

发布于 2024-08-30 01:42:09 字数 222 浏览 8 评论 0原文

我正在使用 ASP.NET MVC 并创建一个公共网站。我需要跟踪在线用户。我发现 asp.net 中执行此操作的标准方法是跟踪 LastActivityDate。我的问题是我什么时候应该更新这个?

如果我每次用户点击某个地方时都更新它,我会感觉到性能下降。然而,如果我不这样做,那些只上网冲浪的人将被列为离线。

在 ASP.NET MVC 中执行此操作的最佳方法是什么?

I'm using ASP.NET MVC and creating a public website. I need to keep track of users that are online. I see that the standard way in asp.net of doing this is to keep track of LastActivityDate. My question is when should I update this?

If I update it every time the users clicks somewhere, I will feel a performance draw back. However if I do not do that, people that only surf around will be listed as offline.

What is the best way to do this in asp.net MVC?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

魔法少女 2024-09-06 01:42:10

为什么不将 LastActivityDate 的更新实现为异步调用?这样您就可以触发更新并继续处理。

Why not implement the update to LastActivityDate as an asynchronous call? That way you can fire the update and continue processing.

述情 2024-09-06 01:42:10

正如 @Jab 所说,只需实现它,如果您将来将其视为性能问题 - 那么就处理它。

这就是我在应用程序中的做法:

protected void Application_EndRequest()
{
    if ((Response.ContentType == "text/html") && (Request.IsAuthenticated))
    {
        var webUser = Context.User as WebUser;
        if (webUser != null)
        {
            //Update their last activity
            webUser.LastActivity = DateTime.UtcNow;

            //Update their page hit counter
            webUser.ActivityCounter += 1;

            //Save them
            var webUserRepo = Kernel.Get<IWebUserRepository>(); //Ninject
            webUserRepo.Update(webUser);
        }
    }
}

我没有遇到任何性能问题。

HTH,
查尔斯

As @Jab says, just implement it and if you see it as a performance issue in the future - deal with it then.

This is how I've done it in my application:

protected void Application_EndRequest()
{
    if ((Response.ContentType == "text/html") && (Request.IsAuthenticated))
    {
        var webUser = Context.User as WebUser;
        if (webUser != null)
        {
            //Update their last activity
            webUser.LastActivity = DateTime.UtcNow;

            //Update their page hit counter
            webUser.ActivityCounter += 1;

            //Save them
            var webUserRepo = Kernel.Get<IWebUserRepository>(); //Ninject
            webUserRepo.Update(webUser);
        }
    }
}

I haven't had any problems with performance.

HTHs,
Charles

你列表最软的妹 2024-09-06 01:42:10

我将其放入一个特殊的队列中,该队列仅允许给定键之一位于队列中(并在本例中使用 userId 作为键)。然后我有一个低优先级线程通过该队列进行数据库更新。因此,用户不会减慢速度,一个用户在一秒钟内执行 100 次更新不会造成任何伤害。如果它成为一个问题,我会将这些更新变成针对数据库的批量更新,但目前这种方法效果很好。

如果应用程序崩溃,我会丢失几秒钟的最后活动数据,但这没关系。当然,我每次也会更新内存中的 User 对象,以便它反映在 UI 中,即使它尚未进入数据库也是如此。通常在他们收到完整的页面之前它就已经存在了。

I put it into a special queue that allows only one of a given key to be in the queue (and use the userId as the key in this case). Then I have a low priority thread that works its way through this queue doing database updates. Thus no slow down for the user, and one user doing 100 updates in one second doesn't cause any harm. If it ever becomes an issue I'll make those updates into batch updates against the database but for now this approach works just fine.

If the application crashed I'd lose a few seconds of last activity data but that's just fine. Of course I also update the in memory User object every time so that it's reflected in the UI even if it hasn't made its way to the database yet. Typically it's there before they've received the completed page anyway.

只为一人 2024-09-06 01:42:10

如果您使用的是 InProc SessionState,请使用 SessionStateModule.End 事件。当会话状态从底层缓存存储中被逐出时,就会发生这种情况。通常,这种情况会在 20 分钟不活动后发生,您可以在 web.config 中设置时间。

If you are using InProc SessionState, use the SessionStateModule.End event. This happens when the session state is evicted from the underlying cache storage. Typically this happens after 20 minutes of inactivity, you can set the time in web.config.

聽兲甴掵 2024-09-06 01:42:10

好问题,也考虑过这个问题,以及这些机制在考虑性能方面的准确性,有几个想法:

1)跟踪上次登录日期

2)使用LastLoginDate +预期的会话长度来设置某种LastOnlineDate,可以用于检查用户是否在线。

Good question, have thought about that too and how accurate these mechanisms can be considering performance, a couple of ideas:

1) Track the the last login date

2) Use the LastLoginDate + the expected session length to set some kind of LastOnlineDate that can be used to check if the user is online.

不醒的梦 2024-09-06 01:42:10

我认为,如果您在每个请求中获取当前登录的用户并每次更新 LastActivityDate 字段(如果您小心并调用 GetUser< /code> 每个 http 请求登录用户的方法)。通过这种方式,您还可以确保用户的数据始终是最新的,例如电子邮件、姓名等,以防他/她更新该数据。

I don't think there is big penalty in performance if you fetch the current logged-in user on every request and update the LastActivityDate field every time (if you have care and invoke the GetUser method for the logged-in user once per http-request). In this way you can also make sure you always have the user's data fresh, like email, name, etc in case he/she updates that data.

写下不归期 2024-09-06 01:42:10

我在 Global.asax 中尝试了 Charlino 的代码,如下所示,

        protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if ((Response.ContentType == "text/html") && (Request.IsAuthenticated))
        {

        }
    }

但是我总是得到 Request.IsAuthenticated false 。
因此,我将代码移至 Site.Master page 中的一个方法,如下所示,

 public void RegisterActivity()
    {
        if ((Response.ContentType == "text/html") && (Request.IsAuthenticated))
        {
            string userName = Page.User.Identity.Name;

            UserManager userManager = new UserManager();
            AppUser appUser = userManager.FindByName(userName);
            appUser.LastActivityDate = DateTime.UtcNow;
            userManager.Update(appUser);
        }
    }

我从 Master page Page_Load 事件调用该方法,然后它起作用了。

我使用的是 asp.net Identity 而不是 Membership,但我添加了一个继承于 IdentityUser 类的 AppUser 类,并且在 AppUser 类中,我添加了 LastActivityDate 属性

这是在 WebForms 应用程序 中,而不是在 MVC 中。

I tried Charlino's code in the Global.asax like this

        protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if ((Response.ContentType == "text/html") && (Request.IsAuthenticated))
        {

        }
    }

However I was getting the Request.IsAuthenticated false all the time.
So I moved the code to a method in my Site.Master pagelike this

 public void RegisterActivity()
    {
        if ((Response.ContentType == "text/html") && (Request.IsAuthenticated))
        {
            string userName = Page.User.Identity.Name;

            UserManager userManager = new UserManager();
            AppUser appUser = userManager.FindByName(userName);
            appUser.LastActivityDate = DateTime.UtcNow;
            userManager.Update(appUser);
        }
    }

I call the method from the Master page Page_Load event, and there it worked.

I'm using asp.net Identity not Membership but I added an AppUser class inheriting from the IdentityUser class and in the AppUser class I added LastActivityDate property.

This is in a WebForms Applicaction not MVC.

黎歌 2024-09-06 01:42:09

只需在母版页底部放置一个 ajax javascript 调用即可跟踪此情况。

此时不用担心性能。如果它已实施并且您发现它是一个问题,那么请回过头来寻找更好的解决方案。如此简单的事情不应该是性能问题。

就像谷歌分析一样思考一下。它位于数百万个页面的底部,对这些网站的用户体验几乎没有影响。

Just put an ajax javascript call at the bottom of your master page to track this.

Don't worry about performance at this time. If it's implemented and you see it being a problem then come back to finding a better solution. Something so simple shouldn't be a performance problem.

Just think about it like Google analytics. It sits at the bottom of millions of pages with little to no impact on the user experiences of those sites.

梦里人 2024-09-06 01:42:09

刚刚遇到了同样的问题,这是我对 MVC 用户的回答:

这个想法是为每个页面加载触发 Membership.GetUser("..", true) 。这将自动更新 LastActivityDate。

我将其放在“RegisterGlobalFilters”下的 global.asax 中:

filters.Add(new MembershipTriggerLastActivityDate());

我创建了一个如下所示的新类:

class MembershipTriggerLastActivityDate : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            MembershipUser user = Membership.GetUser(filterContext.HttpContext.User.Identity.Name, true);
        }   
        base.OnActionExecuting(filterContext);
    }
}

Just ran into the same problem, here's my answer for MVC users:

The idea is to trigger Membership.GetUser("..", true) for every page load. This will automatically update the LastActivityDate.

I put this in my global.asax under "RegisterGlobalFilters":

filters.Add(new MembershipTriggerLastActivityDate());

I created a new class that looks like this:

class MembershipTriggerLastActivityDate : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            MembershipUser user = Membership.GetUser(filterContext.HttpContext.User.Identity.Name, true);
        }   
        base.OnActionExecuting(filterContext);
    }
}
荒路情人 2024-09-06 01:42:09

我开始使用 SimpleMembershipProvider。它非常简单,不再需要 LastActivityDate 跟踪。所以我不得不自己动手。

我刚刚在用户表中添加了一个 LastActivityDate 列,一切顺利...

遵循 @Jab 的提示< /a> 并在 ASP.NET MVC 应用程序中使用 _Layout.cshtml 页面(母版页),我在 jQuery 的帮助下完成了此操作:

$(document).ready((function () {

    var isUserAuthenticated = '@User.Identity.IsAuthenticated';

    if (isUserAuthenticated) {

        $.ajax({
            type: "POST",
            url: "@Url.Action(MVC.Account.ActionNames.UpdateLastActivityDate, MVC.Account.Name)",
            data: { userName: '@User.Identity.Name' },
            cache: false
        });
    }
});

这是操作方法:

public virtual ActionResult UpdateLastActivityDate(string userName)
{
    User user = Database.Users.Single(u => u.UserName == userName);

    user.LastActivityDate = DateTime.Now;

    Database.Entry(user).State = EntityState.Modified;

    Database.SaveChanges();

    return new EmptyResult();
}

仅 133 毫秒 (YMMV) :- )

在此处输入图像描述

I started using the SimpleMembershipProvider. It's so simple that there's no more LastActivityDate tracking. So I had to roll my own.

I just added a LastActivityDate column in the Users table and was good to go...

Following @Jab's tip and using the _Layout.cshtml page (master page) in an ASP.NET MVC app, I did this with the help of jQuery:

$(document).ready((function () {

    var isUserAuthenticated = '@User.Identity.IsAuthenticated';

    if (isUserAuthenticated) {

        $.ajax({
            type: "POST",
            url: "@Url.Action(MVC.Account.ActionNames.UpdateLastActivityDate, MVC.Account.Name)",
            data: { userName: '@User.Identity.Name' },
            cache: false
        });
    }
});

Here's the action method:

public virtual ActionResult UpdateLastActivityDate(string userName)
{
    User user = Database.Users.Single(u => u.UserName == userName);

    user.LastActivityDate = DateTime.Now;

    Database.Entry(user).State = EntityState.Modified;

    Database.SaveChanges();

    return new EmptyResult();
}

Only 133ms (YMMV) :-)

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文