Взаимодействие с клиентами

Последнее обновление: 03.08.2022

Для взаимодействия с клиентами в классе Hub определено свойство Clients. Оно представляет всех подключенных клиентов в виде объекта IHubCallerClients. Если в классе хаба необходимо вызвать на клиенте функцию и отправить ей некоторые данные, то мы можем использовать данный объект. Например:

public class ChatHub : Hub
{
	public async Task Send(string message)
	{
		await Clients.All.SendAsync("Receive", message);
	}
}

В данном случае у всех подключенных клиентов вызывается функция Receive, которой передается строка message.

У объекта Clients есть следующие свойства:

  • All: представляет всех подключенных клиентов

  • Caller: представляет только текущего клиента, который обратился к хабу

  • Others: представляет всех клиентов за исключением текущего клиента, который обратился к хабу

Кроме свойств объект Clients имеет ряд методов:

  • AllExcept(IReadOnlyList<string> connectionIds): представляет всех клиентов за исключением тех, id которых передаются в метод

  • Client(string connectionId): вызывает метод у клиента по id подключения

  • Clients(IReadOnlyList<string> connectionIds): вызывает метод у клиентов, id которых передаются в метод

  • Group(string groupName): вызывает метод у клиентов определенной группы

  • GroupExcept(string groupName, IReadOnlyList<string> connectionIds): вызывает метод у клиентов группы по имени groupName за исключением тех клиентов, id которых передаются в качестве второго параметра

  • Groups(IReadOnlyList<string> groupNames): вызывает метод у клиентов групп, названия которых передаются в метод

  • OthersInGroup(string OthersInGroup): вызывает метод у клиентов определенной группы за исключением текущего клиента

  • User(string userId): вызывает метод у пользователя по id

  • Users(IReadOnlyList<string> userIds): вызывает метод у пользователей, id которых передаются в метод

Обратите внимание, что концепция клиентов и концепция пользователей в данном случае отличается. Клиент по сути представляет отдельное подключение, с которым ассоциируется определенный идентификатор подключения. Если мы откроем в браузере две вкладки, у нас будет два подключения. А пользователи относятся к системе аутентификации приложения.

Например, определим следующий хаб:

using Microsoft.AspNetCore.SignalR;

namespace SignalRApp
{
    public class ChatHub : Hub
    {
        public async Task Send(string product)
        {
            await Clients.Caller.SendAsync("Notify", "Ваш товар добавлен");
            await Clients.Others.SendAsync("Receive", $"Добавлено: {product} в {DateTime.Now.ToShortTimeString()}");
        }
    }
}

При вызове метода Send у текущего клиента будет вызываться функция Notify, а у всех остальных клиентов - функция Receive.

Для теста определим следующую страницу index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Metanit.com</title>
</head>
<body>
    <div>
        <input type="text" id="product" />
        <input type="button" id="sendBtn" value="Добавить" />
    </div>
    <div id="status"></div>
    <div id="info"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>
    <script>
        const hubConnection = new signalR.HubConnectionBuilder()
            .withUrl("/chat")
            .build();

        document.getElementById("sendBtn").addEventListener("click", function () {
            const product = document.getElementById("product").value;

            hubConnection.invoke("Send", product)
                .catch(function (err) {
                    return console.error(err.toString());
                });
        });
        // получение данных с сервера
        hubConnection.on("Receive", function (message) {

            const messageElem = document.createElement("p");
            messageElem.textContent = message;

            // добавляем новый элемент в самое начало
            // для этого сначала получаем первый элемент
            const firstElem = document.getElementById("info").firstChild;
            document.getElementById("info").insertBefore(messageElem, firstElem);
        });

        hubConnection.on("Notify", function (message) {
            document.getElementById("status").innerText = message;
        });


        hubConnection.start()
            .then(function () {
                document.getElementById("sendBtn").disabled = false;
            })
            .catch(function (err) {
                return console.error(err.toString());
            });
    </script>
</body>
</html>

И после условного добавления товара клиент получит одно сообщение:

Отправка сообщений сервера клиенту в ASP NET Core SignalR и C#

А все остальные подключенные клиенты получат своего рода push-уведомление о произведенных действиях:

Push уведомления в ASP NET Core SignalR и C#

Также мы могли бы переписать метод Send в хабе следующим образом:

using Microsoft.AspNetCore.SignalR;

namespace SignalRApp
{
    public class ChatHub : Hub
    {
        public async Task Send(string product)
        {
            await Clients.Client(Context.ConnectionId).SendAsync("Notify", "Ваш товар добавлен");
            await Clients.AllExcept(new List<string> { Context.ConnectionId }).SendAsync("Receive", $"Добавлено: {product} в {DateTime.Now.ToShortTimeString()}");
        }
    }
}

В данном случае метод Send выполняет все те же действия, только теперь для определения клиентов для отправки сообщений применяется идентификатор клиента, который получаем из контекста хаба.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850