Подтвердить что ты не робот

С# asp.net MVC: Когда обновлять LastActivityDate?

Я использую ASP.NET MVC и создаю общедоступный веб-сайт. Мне нужно отслеживать пользователей, которые находятся в сети. Я вижу, что стандартный способ в asp.net сделать это - отслеживать LastActivityDate. Мой вопрос в том, когда следует обновить это?

Если я обновляю его каждый раз, когда пользователи нажимают на него, я почувствую, что производительность снижается. Однако, если я этого не сделаю, люди, которые только будут путешествовать, будут указаны как офлайн.

Каков наилучший способ сделать это в asp.net MVC?

4b9b3361

Ответ 1

Просто разместите javascript-вызов ajax в нижней части главной страницы, чтобы отслеживать это.

Не беспокойтесь о производительности в это время. Если он будет реализован, и вы увидите, что это проблема, вернитесь к поиску лучшего решения. Что-то настолько простое не должно быть проблемой производительности.

Просто подумайте об этом, как о Google Analytics. Он находится внизу миллионов страниц, что практически не влияет на пользовательский опыт этих сайтов.

Ответ 2

Просто столкнулся с той же проблемой, вот мой ответ для пользователей MVC:

Идея состоит в том, чтобы запускать функцию Membership.GetUser( "..", true) для каждой загрузки страницы. Это автоматически обновит LastActivityDate.

Я помещаю это в свой global.asax в разделе "RegisterGlobalFilters":

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);
    }
}

Ответ 3

Я начал использовать SimpleMembershipProvider. Это так просто, что больше нет LastActivityDate отслеживания. Поэтому мне пришлось сворачивать самостоятельно.

Я только что добавил столбец LastActivityDate в таблице "Пользователи", и мне было хорошо...

Следуя @Jab tip и используя страницу _Layout.cshtml (главная страница) в приложении ASP.NET MVC, я сделал это с помощью 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): -)

enter image description here

Ответ 4

Почему бы не реализовать обновление LastActivityDate в качестве асинхронного вызова? Таким образом вы можете запустить обновление и продолжить обработку.

Ответ 5

Как @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,
Чарльз

Ответ 6

Я помещаю его в специальную очередь, которая позволяет только одному из заданного ключа находиться в очереди (и в этом случае использовать userId как ключ). Затем у меня есть поток с низким приоритетом, который прокладывает себе путь через эту очередь, делая обновления базы данных. Таким образом, для пользователя не замедляется, а один пользователь, выполняющий 100 обновлений за одну секунду, не наносит никакого вреда. Если это когда-нибудь станет проблемой, я сделаю эти обновления пакетными обновлениями по базе данных, но на данный момент этот подход работает очень хорошо.

Если приложение потерпит крах, я потеряю несколько секунд последних данных активности, но это будет просто отлично. Конечно, я также каждый раз обновляю объект User в памяти, чтобы он отражался в пользовательском интерфейсе, даже если он еще не пробился к базе данных. Обычно это там, пока они не получили завершенную страницу.

Ответ 7

Если вы используете InProc SessionState, используйте SessionStateModule.End событие. Это происходит, когда состояние сеанса удаляется из основного хранилища кеша. Обычно это происходит после 20 минут бездействия, вы можете установить время в web.config.

Ответ 8

Хороший вопрос, подумал об этом и насколько точны эти механизмы, можно рассматривать производительность, пару идей:

1) Отслеживание последней даты входа в систему

2) Используйте LastLoginDate + ожидаемую длину сеанса, чтобы установить какой-то LastOnlineDate, который можно использовать для проверки, находится ли пользователь в сети.

Ответ 9

Я не думаю, что есть большой штраф в производительности, если вы прибегаете к текущему зарегистрированному пользователю по каждому запросу и обновляете поле LastActivityDate каждый раз (если у вас есть вопросы и вызывают метод GetUser для зарегистрированных пользователей - на пользователя один раз на http-запрос). Таким образом, вы также можете убедиться, что у вас всегда есть данные пользователя, такие как электронная почта, имя и т.д., Если он обновит эти данные.

Ответ 10

Я попробовал Charlino код в Global.asax, как этот

        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 not Membership, но я добавил класс AppUser, наследующий от класса IdentityUser, и в классе AppUser я добавил LastActivityDate property.

Это находится в WebForms Applicaction не MVC.