SignalR для C# (.NET): полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое SignalR и зачем он нужен?

SignalR — это библиотека для ASP.NET Core, которая упрощает добавление функций реального времени (real-time) в веб-приложения. Она позволяет серверу мгновенно отправлять данные подключенным клиентам (браузерам, мобильным приложениям, десктопным приложениям) без необходимости постоянных запросов от клиента.

Зачем это нужно? Традиционный HTTP-протокол работает по принципу «запрос-ответ»: клиент отправляет запрос, сервер отвечает. Для получения обновлений клиент должен постоянно опрашивать сервер (polling). Это неэффективно и создает задержки. SignalR решает эту проблему, предоставляя постоянное двустороннее соединение.

Основные сценарии использования:

  • Чаты и мессенджеры (мгновенная доставка сообщений)
  • Панели мониторинга и дашборды (обновление курсов валют, котировок акций)
  • Совместное редактирование документов (Google Docs-like)
  • Уведомления в реальном времени (новые заказы, оповещения)
  • Многопользовательские игры
  • Прогресс выполнения длительных операций (загрузка файлов, обработка данных)

SignalR автоматически выбирает наилучший транспортный протокол для соединения:

  • WebSocket — самый эффективный, постоянное двустороннее соединение
  • Server-Sent Events (SSE) — односторонняя передача от сервера к клиенту
  • Long Polling — fallback-механизм, если WebSocket и SSE недоступны

Установка SignalR

Установка на сервер (ASP.NET Core)

Для серверной части используется NuGet-пакет. Выполните в терминале:

dotnet add package Microsoft.AspNetCore.SignalR

Или через Package Manager Console в Visual Studio:

Install-Package Microsoft.AspNetCore.SignalR

Установка клиента для JavaScript (браузер)

Для клиентской части (браузер) используйте npm:

npm install @microsoft/signalr

Или подключите через CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.0/signalr.min.js"></script>

Установка клиента для .NET (C#)

Для клиента на C# (например, консольное приложение или WPF):

dotnet add package Microsoft.AspNetCore.SignalR.Client

Быстрый старт: пример "Hello, World!"

Создадим простой чат: сервер принимает сообщение и рассылает его всем подключенным клиентам.

Шаг 1: Создаем Hub (серверная часть)

Создайте файл ChatHub.cs:

using Microsoft.AspNetCore.SignalR;

namespace SignalRChat.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            // Отправляем сообщение всем подключенным клиентам
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

Шаг 2: Регистрируем SignalR в Program.cs

using SignalRChat.Hubs;

var builder = WebApplication.CreateBuilder(args);

// Добавляем SignalR
builder.Services.AddSignalR();

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

// Маппим хаб на путь /chatHub
app.MapHub<ChatHub>("/chatHub");

app.Run();

Шаг 3: Создаем клиент (HTML + JavaScript)

<!DOCTYPE html>
<html>
<head>
    <title>SignalR Chat</title>
</head>
<body>
    <h2>SignalR Chat</h2>
    <div>
        <input type="text" id="userInput" placeholder="Ваше имя" />
        <input type="text" id="messageInput" placeholder="Сообщение" />
        <button onclick="sendMessage()">Отправить</button>
    </div>
    <ul id="messagesList"></ul>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.0/signalr.min.js"></script>
    <script>
        // Создаем соединение
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("/chatHub")
            .build();

        // Подписываемся на получение сообщений
        connection.on("ReceiveMessage", (user, message) => {
            const li = document.createElement("li");
            li.textContent = `${user}: ${message}`;
            document.getElementById("messagesList").appendChild(li);
        });

        // Запускаем соединение
        connection.start().catch(err => console.error(err.toString()));

        // Функция отправки сообщения
        function sendMessage() {
            const user = document.getElementById("userInput").value;
            const message = document.getElementById("messageInput").value;
            connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));
        }
    </script>
</body>
</html>

Основные методы/функции SignalR

1. HubConnectionBuilder.WithUrl() (клиент)

Что делает: Настраивает URL-адрес хаба для подключения.

Параметры:

  • url (string) — URL хаба на сервере
  • options (Action<HttpConnectionOptions>) — дополнительные опции (токены, заголовки)

Пример:

var connection = new HubConnectionBuilder()
    .WithUrl("https://myserver.com/chatHub")
    .Build();

2. HubConnection.On() (клиент)

Что делает: Подписывается на получение сообщений от сервера с указанным именем метода.

Параметры:

  • methodName (string) — имя метода на сервере
  • handler (Delegate) — функция-обработчик

Пример:

connection.On<string, string>("ReceiveMessage", (user, message) => {
    Console.WriteLine($"{user}: {message}");
});

3. HubConnection.InvokeAsync() (клиент)

Что делает: Вызывает метод на сервере и ожидает результат (если метод возвращает значение).

Параметры:

  • methodName (string) — имя вызываемого метода
  • args (object[]) — аргументы метода

Пример:

await connection.InvokeAsync("SendMessage", "User1", "Hello!");

4. HubConnection.SendAsync() (клиент)

Что делает: Вызывает метод на сервере без ожидания результата (fire-and-forget).

Параметры: Аналогично InvokeAsync.

Пример:

await connection.SendAsync("SendMessage", "User1", "Hello!");

5. Clients.All.SendAsync() (сервер)

Что делает: Отправляет сообщение всем подключенным клиентам.

Параметры:

  • method (string) — имя метода на клиенте
  • args (object[]) — аргументы

Пример:

await Clients.All.SendAsync("ReceiveMessage", user, message);

6. Clients.Caller.SendAsync() (сервер)

Что делает: Отправляет сообщение только тому клиенту, который вызвал текущий метод.

Пример:

await Clients.Caller.SendAsync("ReceiveMessage", "Сервер", "Привет, только тебе!");

7. Clients.Others.SendAsync() (сервер)

Что делает: Отправляет сообщение всем клиентам, кроме вызвавшего.

Пример:

await Clients.Others.SendAsync("ReceiveMessage", user, message);

8. Clients.Group().SendAsync() (сервер)

Что делает: Отправляет сообщение всем клиентам в указанной группе.

Параметры:

  • groupName (string) — имя группы

Пример:

await Clients.Group("Room1").SendAsync("ReceiveMessage", user, message);

9. Groups.AddToGroupAsync() (сервер)

Что делает: Добавляет текущее соединение в указанную группу.

Параметры:

  • connectionId (string) — ID соединения
  • groupName (string) — имя группы

Пример:

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "Room1");
    await base.OnConnectedAsync();
}

10. Groups.RemoveFromGroupAsync() (сервер)

Что делает: Удаляет текущее соединение из указанной группы.

Пример:

await Groups.RemoveFromGroupAsync(Context.ConnectionId, "Room1");

11. Hub.OnDisconnectedAsync() (сервер)

Что делает: Вызывается при отключении клиента. Можно переопределить для очистки ресурсов.

Пример:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await Groups.RemoveFromGroupAsync(Context.ConnectionId, "Room1");
    await base.OnDisconnectedAsync(exception);
}

12. HubConnection.StopAsync() (клиент)

Что делает: Останавливает соединение с сервером.

Пример:

await connection.StopAsync();

Реальный практический пример: Система уведомлений

Создадим систему уведомлений для интернет-магазина: при поступлении нового заказа администратор получает мгновенное оповещение.

Серверная часть (NotificationHub.cs)

using Microsoft.AspNetCore.SignalR;

namespace StoreApp.Hubs
{
    public class NotificationHub : Hub
    {
        // Администраторы подключаются к группе "Admins"
        public async Task JoinAdminGroup()
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, "Admins");
        }

        // Метод для отправки уведомления всем администраторам
        public async Task NotifyNewOrder(string orderId, string customerName, decimal amount)
        {
            await Clients.Group("Admins").SendAsync("NewOrderNotification", orderId, customerName, amount);
        }
    }
}

Контроллер для создания заказа (OrdersController.cs)

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using StoreApp.Hubs;

[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly IHubContext<NotificationHub> _hubContext;

    public OrdersController(IHubContext<NotificationHub> hubContext)
    {
        _hubContext = hubContext;
    }

    [HttpPost]
    public async Task<IActionResult> CreateOrder([FromBody] OrderDto order)
    {
        // Логика создания заказа в БД...

        // Отправляем уведомление администратора                    

Рекомендаций