[英]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.