简体   繁体   中英

ASP.NET MVC - Get log in status of a user

In my application, I would like to check whether or not a particular user is logged in or not so I can display a status saying that that user is either "online" or "offline" to another user. This question is not about authenticating a user, only about getting the authentication status of a user.

How would I go about achieving this?

I think an option is to use some real-time solutions. SignalR for example. When a user logs in , you connect it to the hub. OnConnected() action save its state.Then OnDisconnected() remove from "OnlineRepository".

Update with example Here is how I did this in a asp.Net Mvc 5 app.

  • A Model class that holds a single user like:

     public class SingleConnection { public SingleConnection() { ConnectionId = new List(); } public string Id { get; set; } public List ConnectionId { get; set; } } 
  • A connection mapping class that helps in adding/removeing and getting a user from list

     public class ConnectionMapping { private readonly List _connections = new List(); public int Count { get { return _connections.Count; } } public void Add(string key, string connectionId) { lock (_connections) { var sn = _connections.Where(x => x.Id == key).FirstOrDefault(); if (sn != null) // there is a connection with this key { _connections.Find(x => x.Id == key).ConnectionId.Add(connectionId); } else { _connections.Add(new SingleConnection { Id = key, ConnectionId = new List { connectionId } }); } } } public List GetConnections(string id) { var con = _connections.Find(x => x.Id == id); return con != null ? con.ConnectionId : new List(); } public List AllConnectionIds() { List results = new List(); var allItems = _connections.Where(x => x.ConnectionId.Count > 0).ToList(); foreach (var item in allItems) { results.AddRange(item.ConnectionId); } return results; } public List AllKeys() { return _connections.Select(x => x.Id).ToList(); } public void Remove(string key, string connectionId) { lock (_connections) { var item = _connections.Find(x => x.Id == key); if (_connections.Find(x => x.Id == key) != null) { _connections.Find(x => x.Id == key).ConnectionId.Remove(connectionId); if (_connections.Find(x => x.Id == key).ConnectionId.Count == 0) { _connections.Remove(item); } } } } } 
    • In my Hub Class
     private void IsActive(string connection, bool connected) { Clients.All.clientconnected(connection, connected); } public override Task OnConnected() { string name = Context.User.Identity.Name; _connections.Add(name, Context.ConnectionId); IsActive(name, true); return base.OnConnected(); } public override Task OnDisconnected(bool stopCalled) { string name = Context.User.Identity.Name; _connections.Remove(name, Context.ConnectionId); IsActive(name, false); return base.OnDisconnected(stopCalled); } public override Task OnReconnected() { string name = Context.User.Identity.Name; if (!_connections.GetConnections(name).Contains(Context.ConnectionId)) { _connections.Add(name, Context.ConnectionId); } IsActive(name, false); return base.OnReconnected(); } 
  • In _Layout.cshtml

     // reference scripts // add a callback or the OnConnected() Will not fire chat.client.clientconnected = function (id,active){ /* this will be called everytime a user connect or disconnect to the hub */ } $.connection.hub.start(); 

Now with this I get in realtime all users that are online.
Note: This is an InMemory solution. Other solutions are here

Hope this helps...

I would create my own system to define what are your "active" users:

  • You can keep the track of your users with a dictionary stored in the System.Web.Caching.Cache class.
  • In your base controller (because it would be instantiate for any client request) insert the current user to your cached dictionary by calling the KeepTrackActiveUsers method.
  • Add the SetInactiveUser method to your logout method.

{

private Dictionary<int,DateTime> ActiveUsers
{
    get 
    { 
      if(Cache["ActiveUsers"] == null)
        Cache["ActiveUsers"] = new Dictionary<int,DateTime>();
      return Cache["ActiveUsers"];
    } 
    set { Cache["ActiveUsers"] = value; }
}

private void KeepTrackActiveUsers()
{
    ActiveUsers[CurrentUserId] = DateTime.Now;
}   

private const int expirationTime = 600;   
private IEnumerable<int> GetActiveUsers()
{       
    DateTime now = DateTime.Now;
    ActiveUsers = ActiveUsers
        .Where(x => now.Subtract(x.Value).TotalSeconds < expirationTime)
        .ToDictionary(x => x.Key, x => x.Value);
    return ActiveUsers.Keys;
}

private void SetInactiveUser()
{
    ActiveUsers.Remove(CurrentUserId);
}

//to be defined
private int CurrentUserId
{
    get { return default(int); }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM