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);
}
}
}
}
}
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...
AspNetUserstable. Set it to true when they login and false when they logout.