[英]C# asp.net MVC: When to update LastActivityDate?
我正在使用ASP.NET MVC并创建一个公共网站。 我需要跟踪在线用户。 我看到asp.net中的标准方法是跟踪LastActivityDate
。 我的问题是我应该何时更新?
如果我每次用户点击某处都更新它,我会觉得性能退缩。 但是,如果我不这样做,那些只能浏览的人将被列为离线状态。
在asp.net MVC中执行此操作的最佳方法是什么?
只需在主页底部放置一个ajax javascript调用即可跟踪。
此时不要担心性能问题。 如果它已经实施并且您认为它是一个问题,那么回过头来寻找更好的解决方案。 如此简单的东西不应该是性能问题。
试想一下像谷歌分析。 它位于数百万页的底部,对这些网站的用户体验几乎没有影响。
刚遇到同样的问题,这是我对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);
}
}
我开始使用SimpleMembershipProvider 。 它非常简单,不再有LastActivityDate
跟踪。 所以我不得不自己动手。
我刚刚在Users表中添加了一个LastActivityDate
列,并且很好...
按照_Layout.cshtml
的提示并在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):-)
为什么不将LastActivityDate的更新实现为异步调用? 这样您就可以触发更新并继续处理。
正如@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);
}
}
}
我的表现没有任何问题。
HTHS,
查尔斯
我把它放入一个特殊的队列,只允许一个给定的密钥在队列中(在这种情况下使用userId作为密钥)。 然后我有一个低优先级的线程,通过这个队列进行数据库更新。 因此,用户不会减速,并且一个用户在一秒内完成100次更新不会造成任何伤害。 如果它成为一个问题,我将对数据库进行批量更新这些更新,但现在这种方法工作得很好。
如果应用程序崩溃,我会丢失几秒钟的最后一次活动数据,但这很好。 当然,我每次都会更新内存中的User对象,以便它反映在UI中,即使它还没有进入数据库。 通常它是在他们收到完整的页面之前就已经存在了。
如果您使用的是InProc SessionState,请使用SessionStateModule.End事件。 当会话状态从底层缓存存储中逐出时会发生这种情况。 通常,这在20分钟不活动后发生,您可以在web.config中设置时间。
好问题,也考虑过这些,以及这些机制在考虑性能方面有多准确,有几个想法:
1)跟踪上次登录日期
2)使用LastLoginDate +预期的会话长度来设置某种LastOnlineDate,可用于检查用户是否在线。
如果您在每个请求上获取当前登录用户并且每次都更新LastActivityDate
字段,我认为性能不会受到很大的损失(如果您小心并且每个http调用一次登录用户的GetUser
方法)请求)。 通过这种方式,您还可以确保始终拥有用户的数据,例如电子邮件,姓名等,以防他/她更新该数据。
我在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
,但我添加了一个AppUser
类从继承IdentityUser
类,并在AppUser
我添加类LastActivityDate property
。
这是在WebForms Applicaction
而不是MVC
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.