TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #3033 2.29K
День 2521. #ЗаметкиНаПолях
Разбираем Server-Sent Events в
ASP.NET Core и .NET 10. Окончание
Начало
Продолжение

Фильтрация SSE по пользователю
SSE построены на основе стандартного HTTP. Поскольку это стандартный GET-запрос, вся существующая инфраструктура «просто работает»:
- Безопасность - вы можете передать стандартный JWT в заголовке Authorization.
- Контекст пользователя - вы можете получить доступ к HttpContext.User, чтобы извлечь идентификатор пользователя и отфильтровать поток. Вы отправляете пользователю только те данные, которые ему принадлежат.

Вот пример конечной точки SSE, которая передаёт потоком только заказы для конкретного пользователя:
app.MapGet("orders/realtime", (
ChannelReader<OrderPlacement> reader,
// Внедрённый контекст с метаданными пользователя
IUserContext context,
CancellationToken ct) =>
{
// Реализация IUserContext получает UserId из токена доступа JWT
var userId = context.UserId;

async IAsyncEnumerable<OrderPlacement>
GetUserOrders()
{
await foreach (var order in
reader.ReadAllAsync(ct))
{
// Выдаём только данные текущего пользователя
if (order.CustomerId == userId)
yield return order;
}
}

return TypedResults.ServerSentEvents(
GetUserOrders(),
"orders");
})
// Стандартная авторизация ASP.NET
.RequireAuthorization();

Обратите внимание, что при отправке сообщения в канал оно транслируется всем подключённым клиентам (ChannelReader<T>). Это вряд ли подойдёт, когда надо разделять сообщения для каждого пользователя. Поэтому в производственной среде понадобится более надёжная логика.

Обработка SSE в JavaScript
На стороне клиента не нужно устанавливать дополнительных npm-пакетов. Нативный API EventSource браузера берёт на себя основную работу, включая логику «повторного подключения и отправки Last-Event-ID», которую мы рассмотрели в предыдущем посте.
const es =
new EventSource('/orders/realtime/with-replays');

// Слушаем специальный тип событий 'orders', который определён в коде C# (см. выше)
es.addEventListener('orders', (event) => {
const payload = JSON.parse(event.data);
console.log(
`Новый заказ ${event.lastEventId}:`, payload.data);
});

// При открытии подключения
es.onopen = () => {
console.log('Connection opened');
};

// Обрабатываем общие сообщения (если есть)
es.onmessage = (event) => {
console.log('Получено сообщение:', event);
};

// Обрабатываем ошибки и переподключения
es.onerror = () => {
if (es.readyState === EventSource.CONNECTING) {
console.log('Повторное подключение…');
}
};


Итого
SSE в .NET 10 — это идеальный компромисс для простых односторонних обновлений, таких как панели мониторинга, уведомления и индикаторы выполнения. Они легковесны, работают по протоколу HTTP и легко обеспечивают безопасность с помощью существующего промежуточного ПО.
Однако SignalR остаётся надёжным и проверенным в боевых условиях вариантом для сложных двусторонних коммуникаций или масштабных задач, требующих бэкэнда.
Цель SSE не в замене SignalR, а в предоставлении более простого инструмента для более простых задач. Выбирайте самый простой инструмент, который решает вашу проблему.

Источник: https://www.milanjovanovic.tech/blog/server-sent-events-in-aspnetcore-and-dotnet-10
  • 👍 9
More from @netdeveloperdiary
  1. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  2. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  3. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  4. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  5. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  6. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →