SignalR - правильная реализация чата
Мне нужно реализовать чат на моем веб-проекте. Как реализовать это на одной странице - об этом много статей. Но мне нужно иметь возможность: 1. Уведомить других пользователей, что кто-то вошел на сайт (на любой странице, не только на странице чата) 2. Уведомить других пользователей, что кто-то вышел из системы
Итак, у меня есть следующий код хаба:
public void Connect()
{
try
{
var id = Context.ConnectionId;
string username = Context.User.Identity.Name;
var currentUser = connectedUsers.Where(p => p.Username == username).FirstOrDefault();
if (currentUser == null)
{
AddNewUserToCollection();
}
else
{
// update ConnectionId for sure (connection id is changed sometimes (probably if user is logged out and login again))
if (currentUser.ConnectionId != id)
{
var companyId = _chatRepository.GetCompanyIdOfUser(username); // throws exception if companyId is null
Groups.Remove(currentUser.ConnectionId, companyId.ToString());
Groups.Add(id, companyId.ToString());
currentUser.ConnectionId = id;
//Clients.Group(companyId.ToString()).onNewUserConnected(username);
}
}
}
catch(InvalidCompanyException c_ex)
{
Clients.Client(Context.ConnectionId).onErrorMessage($"User '{c_ex.Username}' does not exist");
}
}
public void Disconnect()
{
string username = Context.User.Identity.Name;
var item = connectedUsers.Where(p => p.Username == username).FirstOrDefault();
if (item != null)
{
connectedUsers.Remove(item);
Groups.Remove(item.ConnectionId, item.CompanyID.ToString());
Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username);
}
}
public override Task OnDisconnected(bool stopCalled)
{
var item = connectedUsers.Where(p => p.ConnectionId == Context.ConnectionId).FirstOrDefault();
if (item != null)
{
connectedUsers.Remove(item);
Groups.Remove(item.ConnectionId, item.CompanyID.ToString());
Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username);
}
return base.OnDisconnected(stopCalled);
}
и я добавил следующий код в _layout.cshtml:
<script>
$(document).ready(function () {
var chat = $.connection.chatHub;
$.connection.hub.start().done(function () {
chat.server.connect();
});
});
</script>
уведомить других пользователей, что текущий пользователь зарегистрирован. Но отладчик говорит, что пара OnDisconnected/Connect вызывается каждый раз, когда пользователь перезагружает страницу (переходят по страницам) с другим connectionId. Когда я удаляю этот код клиента - эта пара не называется. Как правильно это реализовать, чтобы уведомить других пользователей, что кто-то в сети, но каждый раз без повторного подключения?
1 ответ
Поскольку у вас есть вызов connect() на странице бритвы (_layout.cshtml), вы будете эффективно отключаться / подключаться к каждому посту обратно (загрузка страницы).
Сценарий, который вы пытаетесь использовать, лучше всего подходит для сценария SPA (или AJAX), где навигация выполняется асинхронно с помощью клиентского JavaScript. Ваша текущая настройка обновляет экран, перезагружает JavaScript, перезапускает функцию document ready() с каждым отображаемым сервером переходом.
Другой альтернативой является использование действительного идентификатора пользователя клиента и передача его методу server.connect(id). Затем используйте этот идентификатор пользователя для отслеживания активности пользователя вместо хаба ConnectionId.