ASP.NET Core 2如何获取所有活动会话?需展示登录用户(原ASP.NET方法无效)
Hey there! I totally get where you’re coming from—trying to pull up all logged-in users (active sessions) in ASP.NET Core 2, only to find the old ASP.NET method you found doesn’t work anymore. That’s super common because ASP.NET Core did a full rewrite of session management, ditching a lot of the old static collections like HttpContext.Current.Application["Sessions"].
No worries though—here’s a practical, working approach to track active users in ASP.NET Core 2:
Since ASP.NET Core doesn’t include a built-in way to list active sessions, we’ll build a custom service to track logged-in users, plus handle cleanup when sessions expire or users log out.
Step 1: Create an Active User Tracking Service
First, we’ll make a thread-safe service to store and manage active user data. We’ll use ConcurrentDictionary to avoid race conditions since multiple requests will access this service.
// Define a model to hold active user details public class ActiveUser { public string SessionId { get; set; } public string UserId { get; set; } public string UserName { get; set; } public DateTime LoginTime { get; set; } } // Interface for the service (good for dependency injection and testing) public interface IActiveUserService { void AddActiveUser(string sessionId, string userId, string userName); void RemoveActiveUser(string sessionId); IEnumerable<ActiveUser> GetAllActiveUsers(); } // Concrete implementation of the service public class ActiveUserService : IActiveUserService { private readonly ConcurrentDictionary<string, ActiveUser> _activeUsers = new(); public void AddActiveUser(string sessionId, string userId, string userName) { _activeUsers.TryAdd(sessionId, new ActiveUser { SessionId = sessionId, UserId = userId, UserName = userName, LoginTime = DateTime.UtcNow }); } public void RemoveActiveUser(string sessionId) { _activeUsers.TryRemove(sessionId, out _); } public IEnumerable<ActiveUser> GetAllActiveUsers() { return _activeUsers.Values; } }
Step 2: Register the Service in Startup
We need to register this service as a singleton so it’s shared across the entire application:
public class Startup { public void ConfigureServices(IServiceCollection services) { // ... other service registrations (like Identity, MVC) // Register our active user service as a singleton services.AddSingleton<IActiveUserService, ActiveUserService>(); // Enable session support (required to get SessionId) services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); // Match your session timeout options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // ... other middleware (like error handling, static files) // Use session middleware (must come before MVC) app.UseSession(); app.UseMvcWithDefaultRoute(); } }
Step 3: Track Users on Login/Logout
Update your login and logout actions to add/remove users from the service:
Login Action
public class AccountController : Controller { private readonly IActiveUserService _activeUserService; private readonly SignInManager<IdentityUser> _signInManager; private readonly UserManager<IdentityUser> _userManager; public AccountController(IActiveUserService activeUserService, SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager) { _activeUserService = activeUserService; _signInManager = signInManager; _userManager = userManager; } [HttpPost] public async Task<IActionResult> Login(LoginViewModel model) { if (ModelState.IsValid) { var result = await _signInManager.PasswordSignInAsync( model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false); if (result.Succeeded) { // Get the current session ID and user details var sessionId = HttpContext.Session.Id; var user = await _userManager.FindByNameAsync(model.UserName); // Add the user to our active list _activeUserService.AddActiveUser(sessionId, user.Id, user.UserName); return RedirectToAction("Index", "Home"); } ModelState.AddModelError("", "Invalid login attempt."); } return View(model); } }
Logout Action
[HttpPost] public async Task<IActionResult> Logout() { // Remove the user from active list before signing out var sessionId = HttpContext.Session.Id; _activeUserService.RemoveActiveUser(sessionId); await _signInManager.SignOutAsync(); return RedirectToAction("Index", "Home"); }
Step 4: Clean Up Expired Sessions
ASP.NET Core doesn’t have a built-in Session_End event, so we’ll add a background service to periodically remove users whose sessions have expired:
public class SessionCleanupService : IHostedService, IDisposable { private readonly IActiveUserService _activeUserService; private Timer _cleanupTimer; private readonly TimeSpan _sessionTimeout = TimeSpan.FromMinutes(30); // Match your session timeout public SessionCleanupService(IActiveUserService activeUserService) { _activeUserService = activeUserService; } public Task StartAsync(CancellationToken cancellationToken) { // Run cleanup every 5 minutes (adjust as needed) _cleanupTimer = new Timer(CleanupExpiredSessions, null, TimeSpan.Zero, TimeSpan.FromMinutes(5)); return Task.CompletedTask; } private void CleanupExpiredSessions(object state) { var activeUsers = _activeUserService.GetAllActiveUsers().ToList(); foreach (var user in activeUsers) { // Check if the session has expired if (user.LoginTime.Add(_sessionTimeout) < DateTime.UtcNow) { _activeUserService.RemoveActiveUser(user.SessionId); } } } public Task StopAsync(CancellationToken cancellationToken) { _cleanupTimer?.Change(Timeout.Infinite, 0); return Task.CompletedTask; } public void Dispose() { _cleanupTimer?.Dispose(); } }
Register this background service in Startup.cs:
services.AddHostedService<SessionCleanupService>();
Step 5: Display Active Users
Now you can inject IActiveUserService into any controller or view to show the list of logged-in users:
public class HomeController : Controller { private readonly IActiveUserService _activeUserService; public HomeController(IActiveUserService activeUserService) { _activeUserService = activeUserService; } public IActionResult ActiveUsers() { var activeUsers = _activeUserService.GetAllActiveUsers(); return View(activeUsers); } }
For Multi-Server Deployments
If your app runs on multiple servers, the in-memory ConcurrentDictionary won’t work (each server will have its own list). Instead, use a distributed cache like Redis or SQL Server to store active user data. You’d modify ActiveUserService to use IDistributedCache instead of the in-memory dictionary, serializing/deserializing the ActiveUser objects.
内容的提问来源于stack exchange,提问作者Alireza Mn

