В On-Premise signalr, Параллельное соединение работает должным образом в вебе MVC. Но Azure Gov не работает должным образом и включил Websocket.
Параллельные значения словаря не поддерживают стабильные значения.
В Azure нет возможности включить службу Signalr в среде GOV.
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
namespace BasicChat
{
public class User
{
public string Name { get; set; }
public HashSet<string> ConnectionIds { get; set; }
}
[Authorize]
public class AlertHub : Hub
{
private WhistlerLogger logger = new WhistlerLogger(typeof(AlertHub));
private static readonly ConcurrentDictionary<string, User> dicLoggedInUsers = new ConcurrentDictionary<string, User>(StringComparer.InvariantCultureIgnoreCase);
public bool CheckConCurrentUser(string currentUser)
{
bool isFlag = false;
try {
User userObj = null;
logger.Info($"Signalr Hub CheckConCurrentUser currentUser : {currentUser}");
dicLoggedInUsers.TryGetValue(currentUser, out userObj);
if (userObj != null && userObj.Name != null && userObj.ConnectionIds != null)
{
logger.Info($"Signalr Hub CheckConCurrentUser currentUser : {userObj.Name} : {string.Join(",", userObj.ConnectionIds.Select(c => string.Format("'{0}'", c)))}");
}
else
{
logger.Info($"Signalr Hub CheckConCurrentUser no user found");
}
isFlag = userObj != null && userObj.ConnectionIds.Count > 1;
}
catch(Exception ex)
{
logger.Error($"Signalr Hub CheckConCurrentUser currentUser : {currentUser}",ex);
}
return isFlag;
}
public override Task OnConnected()
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
try
{
logger.Info($"Signalr Hub OnConnected Method: Current Conext userName: {userName} ConnectionID : {connectionId}");
var user = dicLoggedInUsers.GetOrAdd(userName, _ => new User
{
Name = userName,
ConnectionIds = new HashSet<string>()
});
lock (user.ConnectionIds)
{
user.ConnectionIds.Add(connectionId);
logger.Info($"Signalr Hub OnConnected Method: {string.Join(",", user.ConnectionIds.Select(c => string.Format("'{0}'", c)))}");
}
}
catch (Exception ex)
{
logger.Error($"Signalr Hub OnConnected Method: {userName} {connectionId}", ex);
}
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
if(!stopCalled)
{
logger.Info($"Client {0} timed out .", Context.ConnectionId);
}
logger.Info($"Signalr Hub OnDisconnected Method: Current Conext userName: {userName} ConnectionID: {connectionId}");
try
{
User user;
dicLoggedInUsers.TryGetValue(userName, out user);
if (user != null)
{
lock (user.ConnectionIds)
{
logger.Info($"Signalr Hub OnDisconnected Method: 1.GoingToRemove UserName: {userName} User ConnectionID: {connectionId}");
logger.Info($"Signalr Hub OnDisconnected Method: 2.GoingToRemove:{ user.Name} User Count: {string.Join(",", user.ConnectionIds.Select(c => string.Format("'{0}'", c)))}");
user.ConnectionIds.RemoveWhere(cid => cid.Equals(connectionId));
if (!user.ConnectionIds.Any())
{
User removedUser;
dicLoggedInUsers.TryRemove(userName, out removedUser);
logger.Info($"Signalr Hub OnDisconnected Method: 1.Removed User: {removedUser.Name} ConnectionIDs : {string.Join(",", removedUser.ConnectionIds.Select(c => string.Format("'{0}'", c)))}");
}
}
if(user.ConnectionIds !=null && user.ConnectionIds.Any())
{
logger.Info($"Signalr Hub OnDisconnected Method: 2. After Removed:{ user.Name} User Count: {string.Join(",", user.ConnectionIds.Select(c => string.Format("'{0}'", c)))}");
}
else
{
logger.Info("no user connection id found");
}
}
}
catch (Exception ex)
{
logger.Error($"Signalr Hub OnDisconnected Method: {userName} {connectionId}", ex);
}
//
return base.OnDisconnected(stopCalled);
}
public override Task OnReconnected()
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
// if (!_connections.GetConnections(name).Contains(Context.ConnectionId))
// {
// _connections.Add(name, Context.ConnectionId);
// }
logger.Info($"Signalr Hub OnReconnected Method: Current Conext userName: {userName} ConnectionID : {connectionId}");
foreach (var each in dicLoggedInUsers)
{
logger.Info($"Signalr Hub OnReconnected Method: User Loop: {each.Key} : User ConnectionsIDs Count: {each.Value.ConnectionIds.Count} ");
if (each.Key == userName)
{
var filterUserConnectionId = each.Value.ConnectionIds.Where(x=> x.Contains(connectionId)).Any();
if(!filterUserConnectionId)
{
var user = dicLoggedInUsers.GetOrAdd(userName, _ => new User
{
Name = userName,
ConnectionIds = new HashSet<string>()
});
lock (user.ConnectionIds)
{
user.ConnectionIds.Add(connectionId);
logger.Info($"Signalr Hub OnReconnected Method: {string.Join(",", user.ConnectionIds.Select(c => string.Format("'{0}'", c)))}");
}
}
}
}
return base.OnReconnected();
}
public void ConcurrentLogout(string connectionId)
{
logger.Info("Signalr Hub ConcurrentLogout :", connectionId);
try
{
foreach (var each in dicLoggedInUsers)
{
logger.Info($"Signalr Hub ConcurrentLogout Method: User Loop: {each.Key} : User ConnectionsIDs Count: {each.Value.ConnectionIds.Count} ");
if (each.Key == Context.User.Identity.Name)
{
foreach (var veach in each.Value.ConnectionIds)
{
if (veach != connectionId)
{
logger.Info($"Signalr Hub ConcurrentLogout Method: {veach} : UserName: {each.Key} ");
Clients.Client(veach).Signout();
}
}
}
}
if(dicLoggedInUsers !=null && dicLoggedInUsers.Any())
{
User loguser;
dicLoggedInUsers.TryGetValue(Context.User.Identity.Name, out loguser);
logger.Info($"Signalr Hub ConcurrentLogout Method: After Called Signed Out:{ loguser.Name} User Count: {string.Join(",", loguser.ConnectionIds.Select(c => string.Format("'{0}'", c)))}");
}
}
catch (Exception ex)
{
logger.Error($"Signalr Hub ConcurrentLogout Method connectionId
: {connectionId}", ex);
}
}
}
Если пользователю больше, чем логин, необходимо подтвердить и выйти из другого сеанса того же пользователя.