You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在ASP.NET中实现用户在线/离线/空闲状态的获取与图标展示?

嘿,我来帮你搞定ASP.NET里的用户状态(在线/空闲/离线)显示需求!下面是我实战过的方案,一步步来很容易实现~

一、先明确状态判定规则

首先得把三个状态的定义理清楚,避免逻辑混乱:

  • 在线:用户已登录,且在最近X分钟内有主动操作(比如刷新页面、点击按钮)
  • 空闲:用户已登录,但超过X分钟没有任何操作(但Session还没过期)
  • 离线:用户未登录,或者Session已过期/超过Y分钟无任何活动

你可以根据业务需求调整X和Y的数值,比如X设为10分钟,Y设为30分钟。

二、实现步骤

1. 记录用户的最后活跃时间

我们需要在用户每次发起请求时,更新他的最后活跃时间。这里用Action过滤器是最方便的方式,不用在每个Controller里重复写代码:

public class TrackUserActivityAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var user = filterContext.HttpContext.User;
        if (user.Identity.IsAuthenticated)
        {
            // 这里可以把最后活跃时间存在Session里,或者数据库/Redis(多服务器场景推荐)
            filterContext.HttpContext.Session["LastActiveTime"] = DateTime.Now;
            
            // 如果是数据库存储,示例:
            // var userId = user.Identity.GetUserId();
            // var userService = filterContext.HttpContext.RequestServices.GetService<IUserService>();
            // userService.UpdateLastActiveTime(userId, DateTime.Now);
        }
        base.OnActionExecuting(filterContext);
    }
}

然后在项目里注册这个过滤器:

// ASP.NET MVC 5及之前(Global.asax)
GlobalFilters.Filters.Add(new TrackUserActivityAttribute());

// ASP.NET Core(Startup.cs)
services.AddControllersWithViews(options =>
{
    options.Filters.Add<TrackUserActivityAttribute>();
});

2. 编写状态判定逻辑

写一个工具类或者服务方法,根据用户的最后活跃时间返回对应的状态:

public enum UserStatus
{
    Online,
    Idle,
    Offline
}

public static class UserStatusHelper
{
    private const int IdleThresholdMinutes = 10; // 空闲阈值:10分钟无操作
    private const int OfflineThresholdMinutes = 30; // 离线阈值:30分钟无操作

    public static UserStatus GetUserStatus(HttpContextBase httpContext)
    {
        var user = httpContext.User;
        if (!user.Identity.IsAuthenticated)
        {
            return UserStatus.Offline;
        }

        var lastActiveTime = httpContext.Session["LastActiveTime"] as DateTime?;
        if (!lastActiveTime.HasValue)
        {
            return UserStatus.Offline;
        }

        var timeSinceLastActive = DateTime.Now - lastActiveTime.Value;
        if (timeSinceLastActive.TotalMinutes < IdleThresholdMinutes)
        {
            return UserStatus.Online;
        }
        else if (timeSinceLastActive.TotalMinutes < OfflineThresholdMinutes)
        {
            return UserStatus.Idle;
        }
        else
        {
            return UserStatus.Offline;
        }
    }

    // ASP.NET Core版本的方法,参数换成HttpContext
    public static UserStatus GetUserStatus(HttpContext httpContext)
    {
        var user = httpContext.User;
        if (!user.Identity.IsAuthenticated)
        {
            return UserStatus.Offline;
        }

        var lastActiveTime = httpContext.Session.Get<DateTime>("LastActiveTime");
        var timeSinceLastActive = DateTime.Now - lastActiveTime;
        // 同上的判断逻辑...
    }
}

3. 前端展示对应图标

在用户资料页面的视图里,根据状态输出不同的图标。这里用Font Awesome图标举例(你也可以换成自定义图片):

@{
    var status = UserStatusHelper.GetUserStatus(HttpContext);
}

<div class="user-profile-status">
    @if (status == UserStatus.Online)
    {
        <i class="fa-solid fa-circle text-success" title="在线"></i>
    }
    else if (status == UserStatus.Idle)
    {
        <i class="fa-solid fa-circle text-warning" title="空闲"></i>
    }
    else
    {
        <i class="fa-solid fa-circle text-muted" title="离线"></i>
    }
    <span>@status.ToString()</span>
</div>

如果不用Font Awesome,也可以用自定义图片:

@{
    var status = UserStatusHelper.GetUserStatus(HttpContext);
    string iconUrl = "";
    string statusText = "";
    switch(status)
    {
        case UserStatus.Online:
            iconUrl = "/images/online-green.png";
            statusText = "在线";
            break;
        case UserStatus.Idle:
            iconUrl = "/images/idle-orange.png";
            statusText = "空闲";
            break;
        default:
            iconUrl = "/images/offline-gray.png";
            statusText = "离线";
            break;
    }
}

<div class="user-status">
    <img src="@iconUrl" alt="@statusText" />
    <span>@statusText</span>
</div>
三、注意事项
  • 如果是多服务器部署的场景,不要用Session存储最后活跃时间,改用Redis或者数据库,不然不同服务器的Session不共享,状态判断会出错。
  • 可以根据需求灵活调整阈值时间,比如把空闲阈值改成5分钟,离线阈值改成60分钟。
  • 如果需要实时更新状态(比如用户长时间不操作自动从在线变空闲),可以用前端定时AJAX请求后端获取最新状态,或者用SignalR实现实时推送。

内容的提问来源于stack exchange,提问作者satyam

火山引擎 最新活动