Использование центров SignalR для ASP.NET Core
SignalR API Центров позволяет подключенным клиентам вызывать методы на сервере. Сервер определяет методы, вызываемые из клиента, и клиент определяет методы, вызываемые с сервера. SignalR все необходимое для обеспечения возможности обмена данными между клиентами и серверами в режиме реального времени.
Настройка SignalR центров
Чтобы зарегистрировать службы, необходимые центрам SignalR , вызовите AddSignalR в Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Чтобы настроить SignalR конечные точки, вызовите MapHubтакже в Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Примечание.
ASP.NET сборки на SignalR стороне сервера теперь устанавливаются с помощью пакета SDK для .NET Core. Дополнительные сведения см SignalR . в сборках в общей платформе .
Создание и использование центров
Создайте концентратор, объявив класс, наследуемый от Hub. Добавьте public
методы в класс, чтобы сделать их вызываемыми из клиентов:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Примечание.
- Не сохраняйте состояние в свойстве класса концентратора. Каждый вызов метода концентратора выполняется в новом экземпляре концентратора.
- Не создавайте экземпляр концентратора непосредственно с помощью внедрения зависимостей. Для отправки сообщений клиенту из другого места в приложении используется
IHubContext
. - Используйте
await
при вызове асинхронных методов, зависящих от центра, оставающегося в живых. Например, метод, напримерClients.All.SendAsync(...)
, может завершиться ошибкой, если он вызывается без вызоваawait
, а метод концентратора завершается доSendAsync
завершения.
Объект Context
Класс Hub содержит Context свойство, содержащее следующие свойства со сведениями о подключении:
Свойство | Description |
---|---|
ConnectionId | Возвращает уникальный идентификатор подключения, назначенный SignalR. Для каждого подключения существует один идентификатор подключения. |
UserIdentifier | Возвращает идентификатор пользователя. По умолчанию SignalR в качестве идентификатора пользователя используется ClaimTypes.NameIdentifier из ClaimsPrincipal связанного с подключением. |
User | Возвращает связанный ClaimsPrincipal с текущим пользователем. |
Items | Возвращает коллекцию ключей и значений, которую можно использовать для совместного использования данных в область этого подключения. Данные можно хранить в этой коллекции, и они будут сохраняться для подключения между различными вызовами методов концентратора. |
Features | Возвращает коллекцию функций, доступных в соединении. Сейчас эта коллекция не требуется в большинстве сценариев, поэтому она еще не описана. |
ConnectionAborted | CancellationToken Возвращает уведомление о прерывании подключения. |
Hub.Context также содержит следующие методы:
Метод | Description |
---|---|
GetHttpContext | HttpContext Возвращает значение для подключения или null если подключение не связано с HTTP-запросом. Для HTTP-подключений используйте этот метод для получения таких сведений, как заголовки HTTP и строки запроса. |
Abort | Прерывает подключение. |
Объект Client
Класс Hub содержит свойство, содержащее следующие свойства для обмена данными между сервером Clients и клиентом:
Свойство | Description |
---|---|
All | Вызывает метод для всех подключенных клиентов |
Caller | Вызывает метод на клиенте, который вызвал метод концентратора. |
Others | Вызывает метод для всех подключенных клиентов, кроме клиента, вызвавого метод |
Hub.Clients также содержит следующие методы:
Метод | Description |
---|---|
AllExcept | Вызывает метод для всех подключенных клиентов, кроме указанных подключений. |
Client | Вызывает метод для определенного подключенного клиента. |
Clients | Вызывает метод для определенных подключенных клиентов |
Group | Вызывает метод для всех подключений в указанной группе |
GroupExcept | Вызывает метод для всех подключений в указанной группе, за исключением указанных подключений. |
Groups | Вызывает метод для нескольких групп подключений |
OthersInGroup | Вызывает метод в группе подключений, за исключением клиента, вызывающего метод концентратора. |
User | Вызывает метод для всех подключений, связанных с конкретным пользователем |
Users | Вызывает метод для всех подключений, связанных с указанными пользователями |
Каждое свойство или метод в предыдущих таблицах возвращает объект с методом SendAsync
. Метод SendAsync
получает имя метода клиента для вызова и любых параметров.
Объект, возвращаемый Client
методами, Caller
также содержит InvokeAsync
метод, который можно использовать для ожидания результата от клиента.
Отправка сообщений клиентам
Чтобы выполнить вызовы к определенным клиентам, используйте свойства Clients
объекта. В следующем примере существует три метода концентратора:
SendMessage
отправляет сообщение всем подключенным клиентам с помощьюClients.All
.SendMessageToCaller
отправляет сообщение обратно вызывающей стороне с помощьюClients.Caller
.SendMessageToGroup
отправляет сообщение всем клиентам вSignalR Users
группе.
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
Строго типизированные центры
Недостаток использования SendAsync
заключается в том, что он использует строку для указания вызываемого метода клиента. При этом код остается открытым для ошибок среды выполнения, если имя метода пропущено или отсутствует в клиенте.
Альтернативой использованию SendAsync
является строго тип Hub класса с Hub<T>. В следующем примере ChatHub
метод клиента извлечен в интерфейс с именем IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Этот интерфейс можно использовать для рефакторинга предыдущего ChatHub
примера, чтобы быть строго типизированным:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
=> await Clients.All.ReceiveMessage(user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.ReceiveMessage(user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}
Использование Hub<IChatClient>
включает проверка компиляции клиентских методов. Это предотвращает проблемы, вызванные использованием строк, так как Hub<T>
может предоставлять доступ только к методам, определенным в интерфейсе. Использование строго типизированного Hub<T>
отключает возможность использования SendAsync
.
Примечание.
Суффикс Async
не удаляется из имен методов. Если метод клиента не определен с .on('MyMethodAsync')
именем, не используйте MyMethodAsync
его в качестве имени.
Получение результатов от клиента
Помимо вызова клиентов, сервер может запросить результат от клиента. Для этого требуется, чтобы сервер использовал ISingleClientProxy.InvokeAsync
, а клиент возвращал результат от своего обработчика .On
.
Существует два способа использования API на сервере, первое — вызов Client(...)
или Caller
Clients
свойство в методе Hub:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
Второй способ — вызвать Client(...)
экземпляр IHubContext<T>
:
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Строго типизированные концентраторы также могут возвращать значения из методов интерфейса:
public interface IClient
{
Task<string> GetMessage();
}
public class ChatHub : Hub<IClient>
{
public async Task<string> WaitForMessage(string connectionId)
{
string message = await Clients.Client(connectionId).GetMessage();
return message;
}
}
Клиенты возвращают результаты в обработчиках .On(...)
, как показано ниже:
Клиент .NET
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Клиент Typescript
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Клиент на Java
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
Изменение имени метода концентратора
По умолчанию имя метода концентратора сервера — это имя метода .NET. Чтобы изменить это поведение по умолчанию для определенного метода, используйте атрибут HubMethodName . Клиент должен использовать это имя вместо имени метода .NET при вызове метода:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Внедрение служб в концентратор
Конструкторы концентратора могут принимать службы от внедрения зависимостей в качестве параметров, которые можно хранить в свойствах класса для использования в методе концентратора.
При внедрении нескольких служб для различных методов концентратора или в качестве альтернативного способа написания кода методы концентратора также могут принимать службы из di. По умолчанию параметры метода концентратора проверяются и разрешаются из DI, если это возможно.
services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
// ...
public class ChatHub : Hub
{
public Task SendMessage(string user, string message, IDatabaseService dbService)
{
var userName = dbService.GetUserName(user);
return Clients.All.SendAsync("ReceiveMessage", userName, message);
}
}
Если неявное разрешение параметров из служб не нужно, отключите его с помощью DisableImplicitFromServicesParameters.
Чтобы явно указать, какие параметры разрешаются из di в методах концентратора, используйте этот параметр и используйте DisableImplicitFromServicesParameters
[FromServices]
атрибут или настраиваемый атрибут, реализующий IFromServiceMetadata
параметры метода концентратора, которые должны быть разрешены из di.
services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
options.DisableImplicitFromServicesParameters = true;
});
// ...
public class ChatHub : Hub
{
public Task SendMessage(string user, string message,
[FromServices] IDatabaseService dbService)
{
var userName = dbService.GetUserName(user);
return Clients.All.SendAsync("ReceiveMessage", userName, message);
}
}
Примечание.
Эта функция использует IServiceProviderIsService, которая при необходимости реализуется реализацией DI. Если контейнер DI приложения не поддерживает эту функцию, внедрение служб в методы концентратора не поддерживается.
Поддержка ключевых служб в внедрении зависимостей
Ключи служб относятся к механизму регистрации и получения служб внедрения зависимостей (DI) с помощью ключей. Служба связана с ключом путем вызова AddKeyedSingleton (или AddKeyedScoped
AddKeyedTransient
) для регистрации. Доступ к зарегистрированной службе путем указания ключа с атрибутом [FromKeyedServices]
. В следующем коде показано, как использовать ключи служб:
using Microsoft.AspNetCore.SignalR;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
var app = builder.Build();
app.MapRazorPages();
app.MapHub<MyHub>("/myHub");
app.Run();
public interface ICache
{
object Get(string key);
}
public class BigCache : ICache
{
public object Get(string key) => $"Resolving {key} from big cache.";
}
public class SmallCache : ICache
{
public object Get(string key) => $"Resolving {key} from small cache.";
}
public class MyHub : Hub
{
public void SmallCacheMethod([FromKeyedServices("small")] ICache cache)
{
Console.WriteLine(cache.Get("signalr"));
}
public void BigCacheMethod([FromKeyedServices("big")] ICache cache)
{
Console.WriteLine(cache.Get("signalr"));
}
}
Обработка событий для подключения
SignalR API Центров предоставляет OnConnectedAsync и OnDisconnectedAsync виртуальные методы для управления и отслеживания подключений. Переопределите виртуальный OnConnectedAsync
метод для выполнения действий, когда клиент подключается к центру, например добавление его в группу:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Переопределите виртуальный OnDisconnectedAsync
метод для выполнения действий при отключении клиента. Если клиент намеренно отключается, например путем вызова connection.stop()
, exception
параметр имеет значение null
. Однако если клиент отключается из-за ошибки, например сбоя сети, exception
параметр содержит исключение, описывающее сбой:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync не нужно OnDisconnectedAsyncвызывать его, он автоматически обрабатывается для вас.
Обработка ошибок
Исключения, возникающие в методах концентратора, отправляются клиенту, который вызвал метод. В клиенте invoke
JavaScript метод возвращает JavaScript Promise
. Клиенты могут присоединить catch
обработчик к возвращаемого обещания или использовать/catch
try
для async
/await
обработки исключений:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Подключение не закрываются, когда концентратор создает исключение. По умолчанию SignalR возвращается универсальное сообщение об ошибке клиенту, как показано в следующем примере:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Непредвиденные исключения часто содержат конфиденциальную информацию, например имя сервера базы данных в исключении, активируется при сбое подключения к базе данных. SignalR не предоставляет эти подробные сообщения об ошибках по умолчанию в качестве меры безопасности. Дополнительные сведения о том, почему сведения об исключении подавляются, см . в разделе "Вопросы безопасности" в ASP.NET Core SignalR.
Если исключительное условие должно распространяться на клиент, используйте HubException класс. HubException
Если в методе концентратора создается исключение, SignalRотправляется клиенту все сообщение об исключении, не измененное:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Примечание.
SignalR отправляет Message
клиенту только свойство исключения. Трассировка стека и другие свойства исключения недоступны клиенту.
Дополнительные ресурсы
SignalR API Центров позволяет подключенным клиентам вызывать методы на сервере. Сервер определяет методы, вызываемые из клиента, и клиент определяет методы, вызываемые с сервера. SignalR все необходимое для обеспечения возможности обмена данными между клиентами и серверами в режиме реального времени.
Настройка SignalR центров
Чтобы зарегистрировать службы, необходимые центрам SignalR , вызовите AddSignalR в Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Чтобы настроить SignalR конечные точки, вызовите MapHubтакже в Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Примечание.
ASP.NET сборки на SignalR стороне сервера теперь устанавливаются с помощью пакета SDK для .NET Core. Дополнительные сведения см SignalR . в сборках в общей платформе .
Создание и использование центров
Создайте концентратор, объявив класс, наследуемый от Hub. Добавьте public
методы в класс, чтобы сделать их вызываемыми из клиентов:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Примечание.
- Не сохраняйте состояние в свойстве класса концентратора. Каждый вызов метода концентратора выполняется в новом экземпляре концентратора.
- Не создавайте экземпляр концентратора непосредственно с помощью внедрения зависимостей. Для отправки сообщений клиенту из другого места в приложении используется
IHubContext
. - Используйте
await
при вызове асинхронных методов, зависящих от центра, оставающегося в живых. Например, метод, напримерClients.All.SendAsync(...)
, может завершиться ошибкой, если он вызывается без вызоваawait
, а метод концентратора завершается доSendAsync
завершения.
Объект Context
Класс Hub содержит Context свойство, содержащее следующие свойства со сведениями о подключении:
Свойство | Description |
---|---|
ConnectionId | Возвращает уникальный идентификатор подключения, назначенный SignalR. Для каждого подключения существует один идентификатор подключения. |
UserIdentifier | Возвращает идентификатор пользователя. По умолчанию SignalR в качестве идентификатора пользователя используется ClaimTypes.NameIdentifier из ClaimsPrincipal связанного с подключением. |
User | Возвращает связанный ClaimsPrincipal с текущим пользователем. |
Items | Возвращает коллекцию ключей и значений, которую можно использовать для совместного использования данных в область этого подключения. Данные можно хранить в этой коллекции, и они будут сохраняться для подключения между различными вызовами методов концентратора. |
Features | Возвращает коллекцию функций, доступных в соединении. Сейчас эта коллекция не требуется в большинстве сценариев, поэтому она еще не описана. |
ConnectionAborted | CancellationToken Возвращает уведомление о прерывании подключения. |
Hub.Context также содержит следующие методы:
Метод | Description |
---|---|
GetHttpContext | HttpContext Возвращает значение для подключения или null если подключение не связано с HTTP-запросом. Для HTTP-подключений используйте этот метод для получения таких сведений, как заголовки HTTP и строки запроса. |
Abort | Прерывает подключение. |
Объект Client
Класс Hub содержит свойство, содержащее следующие свойства для обмена данными между сервером Clients и клиентом:
Свойство | Description |
---|---|
All | Вызывает метод для всех подключенных клиентов |
Caller | Вызывает метод на клиенте, который вызвал метод концентратора. |
Others | Вызывает метод для всех подключенных клиентов, кроме клиента, вызвавого метод |
Hub.Clients также содержит следующие методы:
Метод | Description |
---|---|
AllExcept | Вызывает метод для всех подключенных клиентов, кроме указанных подключений. |
Client | Вызывает метод для определенного подключенного клиента. |
Clients | Вызывает метод для определенных подключенных клиентов |
Group | Вызывает метод для всех подключений в указанной группе |
GroupExcept | Вызывает метод для всех подключений в указанной группе, за исключением указанных подключений. |
Groups | Вызывает метод для нескольких групп подключений |
OthersInGroup | Вызывает метод в группе подключений, за исключением клиента, вызывающего метод концентратора. |
User | Вызывает метод для всех подключений, связанных с конкретным пользователем |
Users | Вызывает метод для всех подключений, связанных с указанными пользователями |
Каждое свойство или метод в предыдущих таблицах возвращает объект с методом SendAsync
. Метод SendAsync
получает имя метода клиента для вызова и любых параметров.
Объект, возвращаемый Client
методами, Caller
также содержит InvokeAsync
метод, который можно использовать для ожидания результата от клиента.
Отправка сообщений клиентам
Чтобы выполнить вызовы к определенным клиентам, используйте свойства Clients
объекта. В следующем примере существует три метода концентратора:
SendMessage
отправляет сообщение всем подключенным клиентам с помощьюClients.All
.SendMessageToCaller
отправляет сообщение обратно вызывающей стороне с помощьюClients.Caller
.SendMessageToGroup
отправляет сообщение всем клиентам вSignalR Users
группе.
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
Строго типизированные центры
Недостаток использования SendAsync
заключается в том, что он использует строку для указания вызываемого метода клиента. При этом код остается открытым для ошибок среды выполнения, если имя метода пропущено или отсутствует в клиенте.
Альтернативой использованию SendAsync
является строго тип Hub класса с Hub<T>. В следующем примере ChatHub
метод клиента извлечен в интерфейс с именем IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Этот интерфейс можно использовать для рефакторинга предыдущего ChatHub
примера, чтобы быть строго типизированным:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
=> await Clients.All.ReceiveMessage(user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.ReceiveMessage(user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}
Использование Hub<IChatClient>
включает проверка компиляции клиентских методов. Это предотвращает проблемы, вызванные использованием строк, так как Hub<T>
может предоставлять доступ только к методам, определенным в интерфейсе. Использование строго типизированного Hub<T>
отключает возможность использования SendAsync
.
Примечание.
Суффикс Async
не удаляется из имен методов. Если метод клиента не определен с .on('MyMethodAsync')
именем, не используйте MyMethodAsync
его в качестве имени.
Получение результатов от клиента
Помимо вызова клиентов, сервер может запросить результат от клиента. Для этого требуется, чтобы сервер использовал ISingleClientProxy.InvokeAsync
, а клиент возвращал результат от своего обработчика .On
.
Существует два способа использования API на сервере, первое — вызов Client(...)
или Caller
Clients
свойство в методе Hub:
public class ChatHub : Hub
{
public async Task<string> WaitForMessage(string connectionId)
{
var message = await Clients.Client(connectionId).InvokeAsync<string>(
"GetMessage");
return message;
}
}
Второй способ — вызвать Client(...)
экземпляр IHubContext<T>
:
async Task SomeMethod(IHubContext<MyHub> context)
{
string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
"GetMessage");
}
Строго типизированные концентраторы также могут возвращать значения из методов интерфейса:
public interface IClient
{
Task<string> GetMessage();
}
public class ChatHub : Hub<IClient>
{
public async Task<string> WaitForMessage(string connectionId)
{
string message = await Clients.Client(connectionId).GetMessage();
return message;
}
}
Клиенты возвращают результаты в обработчиках .On(...)
, как показано ниже:
Клиент .NET
hubConnection.On("GetMessage", async () =>
{
Console.WriteLine("Enter message:");
var message = await Console.In.ReadLineAsync();
return message;
});
Клиент Typescript
hubConnection.on("GetMessage", async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("message");
}, 100);
});
return promise;
});
Клиент на Java
hubConnection.onWithResult("GetMessage", () -> {
return Single.just("message");
});
Изменение имени метода концентратора
По умолчанию имя метода концентратора сервера — это имя метода .NET. Чтобы изменить это поведение по умолчанию для определенного метода, используйте атрибут HubMethodName . Клиент должен использовать это имя вместо имени метода .NET при вызове метода:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Внедрение служб в концентратор
Конструкторы концентратора могут принимать службы от внедрения зависимостей в качестве параметров, которые можно хранить в свойствах класса для использования в методе концентратора.
При внедрении нескольких служб для различных методов концентратора или в качестве альтернативного способа написания кода методы концентратора также могут принимать службы из di. По умолчанию параметры метода концентратора проверяются и разрешаются из DI, если это возможно.
services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
// ...
public class ChatHub : Hub
{
public Task SendMessage(string user, string message, IDatabaseService dbService)
{
var userName = dbService.GetUserName(user);
return Clients.All.SendAsync("ReceiveMessage", userName, message);
}
}
Если неявное разрешение параметров из служб не нужно, отключите его с помощью DisableImplicitFromServicesParameters.
Чтобы явно указать, какие параметры разрешаются из di в методах концентратора, используйте этот параметр и используйте DisableImplicitFromServicesParameters
[FromServices]
атрибут или настраиваемый атрибут, реализующий IFromServiceMetadata
параметры метода концентратора, которые должны быть разрешены из di.
services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
options.DisableImplicitFromServicesParameters = true;
});
// ...
public class ChatHub : Hub
{
public Task SendMessage(string user, string message,
[FromServices] IDatabaseService dbService)
{
var userName = dbService.GetUserName(user);
return Clients.All.SendAsync("ReceiveMessage", userName, message);
}
}
Примечание.
Эта функция использует IServiceProviderIsService, которая при необходимости реализуется реализацией DI. Если контейнер DI приложения не поддерживает эту функцию, внедрение служб в методы концентратора не поддерживается.
Обработка событий для подключения
SignalR API Центров предоставляет OnConnectedAsync и OnDisconnectedAsync виртуальные методы для управления и отслеживания подключений. Переопределите виртуальный OnConnectedAsync
метод для выполнения действий, когда клиент подключается к центру, например добавление его в группу:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Переопределите виртуальный OnDisconnectedAsync
метод для выполнения действий при отключении клиента. Если клиент намеренно отключается, например путем вызова connection.stop()
, exception
параметр имеет значение null
. Однако если клиент отключается из-за ошибки, например сбоя сети, exception
параметр содержит исключение, описывающее сбой:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync не нужно OnDisconnectedAsyncвызывать его, он автоматически обрабатывается для вас.
Обработка ошибок
Исключения, возникающие в методах концентратора, отправляются клиенту, который вызвал метод. В клиенте invoke
JavaScript метод возвращает JavaScript Promise
. Клиенты могут присоединить catch
обработчик к возвращаемого обещания или использовать/catch
try
для async
/await
обработки исключений:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Подключение не закрываются, когда концентратор создает исключение. По умолчанию SignalR возвращается универсальное сообщение об ошибке клиенту, как показано в следующем примере:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Непредвиденные исключения часто содержат конфиденциальную информацию, например имя сервера базы данных в исключении, активируется при сбое подключения к базе данных. SignalR не предоставляет эти подробные сообщения об ошибках по умолчанию в качестве меры безопасности. Дополнительные сведения о том, почему сведения об исключении подавляются, см . в разделе "Вопросы безопасности" в ASP.NET Core SignalR.
Если исключительное условие должно распространяться на клиент, используйте HubException класс. HubException
Если в методе концентратора создается исключение, SignalRотправляется клиенту все сообщение об исключении, не измененное:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Примечание.
SignalR отправляет Message
клиенту только свойство исключения. Трассировка стека и другие свойства исключения недоступны клиенту.
Дополнительные ресурсы
SignalR API Центров позволяет подключенным клиентам вызывать методы на сервере. Сервер определяет методы, вызываемые из клиента, и клиент определяет методы, вызываемые с сервера. SignalR все необходимое для обеспечения возможности обмена данными между клиентами и серверами в режиме реального времени.
Настройка SignalR центров
Чтобы зарегистрировать службы, необходимые центрам SignalR , вызовите AddSignalR в Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
Чтобы настроить SignalR конечные точки, вызовите MapHubтакже в Program.cs
:
app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");
app.Run();
Примечание.
ASP.NET сборки на SignalR стороне сервера теперь устанавливаются с помощью пакета SDK для .NET Core. Дополнительные сведения см SignalR . в сборках в общей платформе .
Создание и использование центров
Создайте концентратор, объявив класс, наследуемый от Hub. Добавьте public
методы в класс, чтобы сделать их вызываемыми из клиентов:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Примечание.
- Не сохраняйте состояние в свойстве класса концентратора. Каждый вызов метода концентратора выполняется в новом экземпляре концентратора.
- Не создавайте экземпляр концентратора непосредственно с помощью внедрения зависимостей. Для отправки сообщений клиенту из другого места в приложении используется
IHubContext
. - Используйте
await
при вызове асинхронных методов, зависящих от центра, оставающегося в живых. Например, метод, напримерClients.All.SendAsync(...)
, может завершиться ошибкой, если он вызывается без вызоваawait
, а метод концентратора завершается доSendAsync
завершения.
Объект Context
Класс Hub содержит Context свойство, содержащее следующие свойства со сведениями о подключении:
Свойство | Description |
---|---|
ConnectionId | Возвращает уникальный идентификатор подключения, назначенный SignalR. Для каждого подключения существует один идентификатор подключения. |
UserIdentifier | Возвращает идентификатор пользователя. По умолчанию SignalR в качестве идентификатора пользователя используется ClaimTypes.NameIdentifier из ClaimsPrincipal связанного с подключением. |
User | Возвращает связанный ClaimsPrincipal с текущим пользователем. |
Items | Возвращает коллекцию ключей и значений, которую можно использовать для совместного использования данных в область этого подключения. Данные можно хранить в этой коллекции, и они будут сохраняться для подключения между различными вызовами методов концентратора. |
Features | Возвращает коллекцию функций, доступных в соединении. Сейчас эта коллекция не требуется в большинстве сценариев, поэтому она еще не описана. |
ConnectionAborted | CancellationToken Возвращает уведомление о прерывании подключения. |
Hub.Context также содержит следующие методы:
Метод | Description |
---|---|
GetHttpContext | HttpContext Возвращает значение для подключения или null если подключение не связано с HTTP-запросом. Для HTTP-подключений используйте этот метод для получения таких сведений, как заголовки HTTP и строки запроса. |
Abort | Прерывает подключение. |
Объект Client
Класс Hub содержит свойство, содержащее следующие свойства для обмена данными между сервером Clients и клиентом:
Свойство | Description |
---|---|
All | Вызывает метод для всех подключенных клиентов |
Caller | Вызывает метод на клиенте, который вызвал метод концентратора. |
Others | Вызывает метод для всех подключенных клиентов, кроме клиента, вызвавого метод |
Hub.Clients также содержит следующие методы:
Метод | Description |
---|---|
AllExcept | Вызывает метод для всех подключенных клиентов, кроме указанных подключений. |
Client | Вызывает метод для определенного подключенного клиента. |
Clients | Вызывает метод для определенных подключенных клиентов |
Group | Вызывает метод для всех подключений в указанной группе |
GroupExcept | Вызывает метод для всех подключений в указанной группе, за исключением указанных подключений. |
Groups | Вызывает метод для нескольких групп подключений |
OthersInGroup | Вызывает метод в группе подключений, за исключением клиента, вызывающего метод концентратора. |
User | Вызывает метод для всех подключений, связанных с конкретным пользователем |
Users | Вызывает метод для всех подключений, связанных с указанными пользователями |
Каждое свойство или метод в предыдущих таблицах возвращает объект с методом SendAsync
. Метод SendAsync
получает имя метода клиента для вызова и любых параметров.
Отправка сообщений клиентам
Чтобы выполнить вызовы к определенным клиентам, используйте свойства Clients
объекта. В следующем примере существует три метода концентратора:
SendMessage
отправляет сообщение всем подключенным клиентам с помощьюClients.All
.SendMessageToCaller
отправляет сообщение обратно вызывающей стороне с помощьюClients.Caller
.SendMessageToGroup
отправляет сообщение всем клиентам вSignalR Users
группе.
public async Task SendMessage(string user, string message)
=> await Clients.All.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.SendAsync("ReceiveMessage", user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
Строго типизированные центры
Недостаток использования SendAsync
заключается в том, что он использует строку для указания вызываемого метода клиента. При этом код остается открытым для ошибок среды выполнения, если имя метода пропущено или отсутствует в клиенте.
Альтернативой использованию SendAsync
является строго тип Hub класса с Hub<T>. В следующем примере ChatHub
метод клиента извлечен в интерфейс с именем IChatClient
:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Этот интерфейс можно использовать для рефакторинга предыдущего ChatHub
примера, чтобы быть строго типизированным:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
=> await Clients.All.ReceiveMessage(user, message);
public async Task SendMessageToCaller(string user, string message)
=> await Clients.Caller.ReceiveMessage(user, message);
public async Task SendMessageToGroup(string user, string message)
=> await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}
Использование Hub<IChatClient>
включает проверка компиляции клиентских методов. Это предотвращает проблемы, вызванные использованием строк, так как Hub<T>
может предоставлять доступ только к методам, определенным в интерфейсе. Использование строго типизированного Hub<T>
отключает возможность использования SendAsync
.
Примечание.
Суффикс Async
не удаляется из имен методов. Если метод клиента не определен с .on('MyMethodAsync')
именем, не используйте MyMethodAsync
его в качестве имени.
Изменение имени метода концентратора
По умолчанию имя метода концентратора сервера — это имя метода .NET. Чтобы изменить это поведение по умолчанию для определенного метода, используйте атрибут HubMethodName . Клиент должен использовать это имя вместо имени метода .NET при вызове метода:
[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
=> await Clients.User(user).SendAsync("ReceiveMessage", user, message);
Обработка событий для подключения
SignalR API Центров предоставляет OnConnectedAsync и OnDisconnectedAsync виртуальные методы для управления и отслеживания подключений. Переопределите виртуальный OnConnectedAsync
метод для выполнения действий, когда клиент подключается к центру, например добавление его в группу:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Переопределите виртуальный OnDisconnectedAsync
метод для выполнения действий при отключении клиента. Если клиент намеренно отключается, например путем вызова connection.stop()
, exception
параметр имеет значение null
. Однако если клиент отключается из-за ошибки, например сбоя сети, exception
параметр содержит исключение, описывающее сбой:
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync не нужно OnDisconnectedAsyncвызывать его, он автоматически обрабатывается для вас.
Обработка ошибок
Исключения, возникающие в методах концентратора, отправляются клиенту, который вызвал метод. В клиенте invoke
JavaScript метод возвращает JavaScript Promise
. Клиенты могут присоединить catch
обработчик к возвращаемого обещания или использовать/catch
try
для async
/await
обработки исключений:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Подключение не закрываются, когда концентратор создает исключение. По умолчанию SignalR возвращается универсальное сообщение об ошибке клиенту, как показано в следующем примере:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' on the server.
Непредвиденные исключения часто содержат конфиденциальную информацию, например имя сервера базы данных в исключении, активируется при сбое подключения к базе данных. SignalR не предоставляет эти подробные сообщения об ошибках по умолчанию в качестве меры безопасности. Дополнительные сведения о том, почему сведения об исключении подавляются, см . в разделе "Вопросы безопасности" в ASP.NET Core SignalR.
Если исключительное условие должно распространяться на клиент, используйте HubException класс. HubException
Если в методе концентратора создается исключение, SignalRотправляется клиенту все сообщение об исключении, не измененное:
public Task ThrowException()
=> throw new HubException("This error will be sent to the client!");
Примечание.
SignalR отправляет Message
клиенту только свойство исключения. Трассировка стека и другие свойства исключения недоступны клиенту.
Дополнительные ресурсы
Просмотрите или скачайте пример кода (описание процедуры скачивания)
Что такое SignalR концентратор
SignalR API Центров позволяет вызывать методы на подключенных клиентах с сервера. В коде сервера определяются методы, вызываемые клиентом. В клиентском коде определяются методы, вызываемые с сервера. SignalR заботится обо всем, что делает обмен данными между клиентами и серверами в режиме реального времени.
Настройка SignalR центров
По промежуточному SignalR слоям требуются некоторые службы, настроенные путем вызова AddSignalR:
services.AddSignalR();
При добавлении SignalR функций в приложение ASP.NET Core настройте SignalR маршруты путем вызова обратного Startup.Configure
вызова MapHub методаUseEndpoints:
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub");
});
Примечание.
ASP.NET сборки на SignalR стороне сервера теперь устанавливаются с помощью пакета SDK для .NET Core. Дополнительные сведения см SignalR . в сборках в общей платформе .
Создание и использование центров
Создайте концентратор, объявив класс, наследуемый от Hub, и добавьте в него открытые методы. Клиенты могут вызывать методы, определенные как public
:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Можно указать возвращаемый тип и параметры, включая сложные типы и массивы, как и в любом методе C#. SignalR обрабатывает сериализацию и десериализацию сложных объектов и массивов в параметрах и возвращаемых значениях.
Примечание.
Центры являются временными:
- Не сохраняйте состояние в свойстве в классе концентратора. Каждый вызов метода концентратора выполняется в новом экземпляре концентратора.
- Не создавайте экземпляр концентратора непосредственно с помощью внедрения зависимостей. Для отправки сообщений клиенту из другого места в приложении используется
IHubContext
. - Используйте
await
при вызове асинхронных методов, зависящих от центра, оставающегося в живых. Например, метод, напримерClients.All.SendAsync(...)
, может завершиться ошибкой, если он вызывается без вызоваawait
, а метод концентратора завершается доSendAsync
завершения.
Объект Context
Класс Hub имеет Context свойство, содержащее следующие свойства со сведениями о подключении:
Свойство | Description |
---|---|
ConnectionId | Возвращает уникальный идентификатор подключения, назначенный SignalR. Для каждого подключения существует один идентификатор подключения. |
UserIdentifier | Возвращает идентификатор пользователя. По умолчанию SignalR в качестве идентификатора пользователя используется ClaimTypes.NameIdentifier из ClaimsPrincipal связанного с подключением. |
User | Возвращает связанный ClaimsPrincipal с текущим пользователем. |
Items | Возвращает коллекцию ключей и значений, которую можно использовать для совместного использования данных в область этого подключения. Данные можно хранить в этой коллекции, и они будут сохраняться для подключения между различными вызовами методов концентратора. |
Features | Возвращает коллекцию функций, доступных в соединении. Сейчас эта коллекция не требуется в большинстве сценариев, поэтому она еще не описана. |
ConnectionAborted | CancellationToken Возвращает уведомление о прерывании подключения. |
Hub.Context также содержит следующие методы:
Метод | Description |
---|---|
GetHttpContext | HttpContext Возвращает значение для подключения или null если подключение не связано с HTTP-запросом. Для HTTP-подключений этот метод можно использовать для получения таких сведений, как заголовки HTTP и строки запроса. |
Abort | Прерывает подключение. |
Объект Client
Класс Hub имеет свойство, содержащее следующие свойства для обмена данными между сервером Clients и клиентом:
Свойство | Description |
---|---|
All | Вызывает метод для всех подключенных клиентов |
Caller | Вызывает метод на клиенте, который вызвал метод концентратора. |
Others | Вызывает метод для всех подключенных клиентов, кроме клиента, вызвавого метод |
Hub.Clients также содержит следующие методы:
Метод | Description |
---|---|
AllExcept | Вызывает метод для всех подключенных клиентов, кроме указанных подключений. |
Client | Вызывает метод для определенного подключенного клиента. |
Clients | Вызывает метод для определенных подключенных клиентов |
Group | Вызывает метод для всех подключений в указанной группе |
GroupExcept | Вызывает метод для всех подключений в указанной группе, за исключением указанных подключений. |
Groups | Вызывает метод для нескольких групп подключений |
OthersInGroup | Вызывает метод в группе подключений, за исключением клиента, вызывающего метод концентратора. |
User | Вызывает метод для всех подключений, связанных с конкретным пользователем |
Users | Вызывает метод для всех подключений, связанных с указанными пользователями |
Каждое свойство или метод в предыдущих таблицах возвращает объект с методом SendAsync
. Этот SendAsync
метод позволяет указать имя и параметры вызываемого метода клиента.
Отправка сообщений клиентам
Чтобы выполнить вызовы к определенным клиентам, используйте свойства Clients
объекта. В следующем примере существует три метода Концентратора:
SendMessage
отправляет сообщение всем подключенным клиентам с помощьюClients.All
.SendMessageToCaller
отправляет сообщение обратно вызывающей стороне с помощьюClients.Caller
.SendMessageToGroup
отправляет сообщение всем клиентам вSignalR Users
группе.
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToGroup(string user, string message)
{
return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}
Строго типизированные центры
Недостаток использования SendAsync
заключается в том, что он использует магическую строку для указания вызываемого метода клиента. При этом код остается открытым для ошибок среды выполнения, если имя метода пропущено или отсутствует в клиенте.
Альтернативой использованию SendAsync
является строго тип Hub с Hub<T>. В следующем примере клиентские ChatHub
методы были извлечены в интерфейс с именем IChatClient
.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Этот интерфейс можно использовать для рефакторинга предыдущего ChatHub
примера:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.ReceiveMessage(user, message);
}
}
Использование Hub<IChatClient>
включает проверка компиляции клиентских методов. Это предотвращает проблемы, вызванные использованием магических строк, так как Hub<T>
может предоставлять доступ только к методам, определенным в интерфейсе.
Использование строго типизированного Hub<T>
отключает возможность использования SendAsync
. Все методы, определенные в интерфейсе, по-прежнему могут быть определены как асинхронные. На самом деле, каждый из этих методов должен возвращать Task
. Так как это интерфейс, не используйте async
ключевое слово. Рассмотрим пример.
public interface IClient
{
Task ClientMethod();
}
Примечание.
Суффикс Async
не удаляется из имени метода. Если в качестве имени не определен .on('MyMethodAsync')
метод клиента, вам не следует использовать MyMethodAsync
его в качестве имени.
Изменение имени метода концентратора
По умолчанию имя метода концентратора сервера — это имя метода .NET. Однако атрибут HubMethodName можно использовать для изменения этого значения по умолчанию и вручную указать имя метода. Клиент должен использовать это имя вместо имени метода .NET при вызове метода:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Обработка событий для подключения
SignalR API Центров предоставляет OnConnectedAsync и OnDisconnectedAsync виртуальные методы для управления и отслеживания подключений. Переопределите виртуальный OnConnectedAsync
метод для выполнения действий, когда клиент подключается к Центру, например добавление его в группу:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Переопределите виртуальный OnDisconnectedAsync
метод для выполнения действий при отключении клиента. Если клиент намеренно отключается (например, вызывая connection.stop()
), exception
параметр будет отключен null
. Однако если клиент отключен из-за ошибки (например, сбой сети), exception
параметр будет содержать исключение, описывающее сбой:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync не нужно OnDisconnectedAsyncвызывать его, он автоматически обрабатывается для вас.
Предупреждение
Предупреждение системы безопасности. Предоставление ConnectionId
доступа может привести к вредоносной олицетворении, если SignalR сервер или версия клиента ASP.NET Core 2.2 или более ранней версии.
Обработка ошибок
Исключения, возникающие в методах концентратора, отправляются клиенту, который вызвал метод. В клиенте invoke
JavaScript метод возвращает JavaScript Promise
. Когда клиент получает ошибку с обработчиком, подключенным к обещанию, он catch
вызывается и передается в виде объекта JavaScript Error
:
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Если центр создает исключение, подключения не закрываются. По умолчанию SignalR возвращается универсальное сообщение об ошибке клиенту. Например:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Непредвиденные исключения часто содержат конфиденциальную информацию, например имя сервера базы данных в исключении, активируется при сбое подключения к базе данных. SignalR не предоставляет эти подробные сообщения об ошибках по умолчанию в качестве меры безопасности. Дополнительные сведения о том, почему сведения об исключении подавляются, см . в разделе "Вопросы безопасности" в ASP.NET Core SignalR.
Если у вас есть исключительное условие, которое вы хотите распространить на клиент, можно использовать HubException класс. Если вы создаете HubException
исключение из метода концентратора, SignalRотправьте клиенту все сообщение, не измененное:
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Примечание.
SignalR отправляет Message
клиенту только свойство исключения. Трассировка стека и другие свойства исключения недоступны клиенту.
Дополнительные ресурсы
Просмотрите или скачайте пример кода (описание процедуры скачивания)
Что такое SignalR концентратор
SignalR API Центров позволяет вызывать методы на подключенных клиентах с сервера. В коде сервера определяются методы, вызываемые клиентом. В клиентском коде определяются методы, вызываемые с сервера. SignalR заботится обо всем, что делает обмен данными между клиентами и серверами в режиме реального времени.
Настройка SignalR центров
По промежуточному SignalR слоям требуются некоторые службы, настроенные путем вызова AddSignalR:
services.AddSignalR();
При добавлении SignalR функций в приложение ASP.NET Core настройте SignalR маршруты, вызвав UseSignalR метод Startup.Configure
:
app.UseSignalR(route =>
{
route.MapHub<ChatHub>("/chathub");
});
Создание и использование центров
Создайте концентратор, объявив класс, наследуемый от Hub, и добавьте в него открытые методы. Клиенты могут вызывать методы, определенные как public
:
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Можно указать возвращаемый тип и параметры, включая сложные типы и массивы, как и в любом методе C#. SignalR обрабатывает сериализацию и десериализацию сложных объектов и массивов в параметрах и возвращаемых значениях.
Примечание.
Центры являются временными:
- Не сохраняйте состояние в свойстве в классе концентратора. Каждый вызов метода концентратора выполняется в новом экземпляре концентратора.
- Не создавайте экземпляр концентратора непосредственно с помощью внедрения зависимостей. Для отправки сообщений клиенту из другого места в приложении используется
IHubContext
. - Используйте
await
при вызове асинхронных методов, зависящих от центра, оставающегося в живых. Например, метод, напримерClients.All.SendAsync(...)
, может завершиться ошибкой, если он вызывается без вызоваawait
, а метод концентратора завершается доSendAsync
завершения.
Объект Context
Класс Hub имеет Context свойство, содержащее следующие свойства со сведениями о подключении:
Свойство | Description |
---|---|
ConnectionId | Возвращает уникальный идентификатор подключения, назначенный SignalR. Для каждого подключения существует один идентификатор подключения. |
UserIdentifier | Возвращает идентификатор пользователя. По умолчанию SignalR в качестве идентификатора пользователя используется ClaimTypes.NameIdentifier из ClaimsPrincipal связанного с подключением. |
User | Возвращает связанный ClaimsPrincipal с текущим пользователем. |
Items | Возвращает коллекцию ключей и значений, которую можно использовать для совместного использования данных в область этого подключения. Данные можно хранить в этой коллекции, и они будут сохраняться для подключения между различными вызовами методов концентратора. |
Features | Возвращает коллекцию функций, доступных в соединении. Сейчас эта коллекция не требуется в большинстве сценариев, поэтому она еще не описана. |
ConnectionAborted | CancellationToken Возвращает уведомление о прерывании подключения. |
Hub.Context также содержит следующие методы:
Метод | Description |
---|---|
GetHttpContext | HttpContext Возвращает значение для подключения или null если подключение не связано с HTTP-запросом. Для HTTP-подключений этот метод можно использовать для получения таких сведений, как заголовки HTTP и строки запроса. |
Abort | Прерывает подключение. |
Объект Client
Класс Hub имеет свойство, содержащее следующие свойства для обмена данными между сервером Clients и клиентом:
Свойство | Description |
---|---|
All | Вызывает метод для всех подключенных клиентов |
Caller | Вызывает метод на клиенте, который вызвал метод концентратора. |
Others | Вызывает метод для всех подключенных клиентов, кроме клиента, вызвавого метод |
Hub.Clients также содержит следующие методы:
Метод | Description |
---|---|
AllExcept | Вызывает метод для всех подключенных клиентов, кроме указанных подключений. |
Client | Вызывает метод для определенного подключенного клиента. |
Clients | Вызывает метод для определенных подключенных клиентов |
Group | Вызывает метод для всех подключений в указанной группе |
GroupExcept | Вызывает метод для всех подключений в указанной группе, за исключением указанных подключений. |
Groups | Вызывает метод для нескольких групп подключений |
OthersInGroup | Вызывает метод в группе подключений, за исключением клиента, вызывающего метод концентратора. |
User | Вызывает метод для всех подключений, связанных с конкретным пользователем |
Users | Вызывает метод для всех подключений, связанных с указанными пользователями |
Каждое свойство или метод в предыдущих таблицах возвращает объект с методом SendAsync
. Этот SendAsync
метод позволяет указать имя и параметры вызываемого метода клиента.
Отправка сообщений клиентам
Чтобы выполнить вызовы к определенным клиентам, используйте свойства Clients
объекта. В следующем примере существует три метода Концентратора:
SendMessage
отправляет сообщение всем подключенным клиентам с помощьюClients.All
.SendMessageToCaller
отправляет сообщение обратно вызывающей стороне с помощьюClients.Caller
.SendMessageToGroup
отправляет сообщение всем клиентам вSignalR Users
группе.
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}
public Task SendMessageToGroup(string user, string message)
{
return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}
Строго типизированные центры
Недостаток использования SendAsync
заключается в том, что он использует магическую строку для указания вызываемого метода клиента. При этом код остается открытым для ошибок среды выполнения, если имя метода пропущено или отсутствует в клиенте.
Альтернативой использованию SendAsync
является строго тип Hub с Hub<T>. В следующем примере клиентские ChatHub
методы были извлечены в интерфейс с именем IChatClient
.
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
Этот интерфейс можно использовать для рефакторинга предыдущего ChatHub
примера:
public class StronglyTypedChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
}
public Task SendMessageToCaller(string user, string message)
{
return Clients.Caller.ReceiveMessage(user, message);
}
}
Использование Hub<IChatClient>
включает проверка компиляции клиентских методов. Это предотвращает проблемы, вызванные использованием магических строк, так как Hub<T>
может предоставлять доступ только к методам, определенным в интерфейсе.
Использование строго типизированного Hub<T>
отключает возможность использования SendAsync
. Все методы, определенные в интерфейсе, по-прежнему могут быть определены как асинхронные. На самом деле, каждый из этих методов должен возвращать Task
. Так как это интерфейс, не используйте async
ключевое слово. Рассмотрим пример.
public interface IClient
{
Task ClientMethod();
}
Примечание.
Суффикс Async
не удаляется из имени метода. Если в качестве имени не определен .on('MyMethodAsync')
метод клиента, вам не следует использовать MyMethodAsync
его в качестве имени.
Изменение имени метода концентратора
По умолчанию имя метода концентратора сервера — это имя метода .NET. Однако атрибут HubMethodName можно использовать для изменения этого значения по умолчанию и вручную указать имя метода. Клиент должен использовать это имя вместо имени метода .NET при вызове метода:
[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
Обработка событий для подключения
SignalR API Центров предоставляет OnConnectedAsync и OnDisconnectedAsync виртуальные методы для управления и отслеживания подключений. Переопределите виртуальный OnConnectedAsync
метод для выполнения действий, когда клиент подключается к Центру, например добавление его в группу:
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
Переопределите виртуальный OnDisconnectedAsync
метод для выполнения действий при отключении клиента. Если клиент намеренно отключается (например, вызывая connection.stop()
), exception
параметр будет отключен null
. Однако если клиент отключен из-за ошибки (например, сбой сети), exception
параметр будет содержать исключение, описывающее сбой:
public override async Task OnDisconnectedAsync(Exception exception)
{
await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
await base.OnDisconnectedAsync(exception);
}
RemoveFromGroupAsync не нужно OnDisconnectedAsyncвызывать его, он автоматически обрабатывается для вас.
Предупреждение
Предупреждение системы безопасности. Предоставление ConnectionId
доступа может привести к вредоносной олицетворении, если SignalR сервер или версия клиента ASP.NET Core 2.2 или более ранней версии.
Обработка ошибок
Исключения, возникающие в методах концентратора, отправляются клиенту, который вызвал метод. В клиенте invoke
JavaScript метод возвращает JavaScript Promise
. Когда клиент получает ошибку с обработчиком, подключенным к обещанию, он catch
вызывается и передается в виде объекта JavaScript Error
:
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
Если центр создает исключение, подключения не закрываются. По умолчанию SignalR возвращается универсальное сообщение об ошибке клиенту. Например:
Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.
Непредвиденные исключения часто содержат конфиденциальную информацию, например имя сервера базы данных в исключении, активируется при сбое подключения к базе данных. SignalR не предоставляет эти подробные сообщения об ошибках по умолчанию в качестве меры безопасности. Дополнительные сведения о том, почему сведения об исключении подавляются, см . в разделе "Вопросы безопасности" в ASP.NET Core SignalR.
Если у вас есть исключительное условие, которое вы хотите распространить на клиент, можно использовать HubException класс. Если вы создаете HubException
исключение из метода концентратора, SignalRотправьте клиенту все сообщение, не измененное:
public Task ThrowException()
{
throw new HubException("This error will be sent to the client!");
}
Примечание.
SignalR отправляет Message
клиенту только свойство исключения. Трассировка стека и другие свойства исключения недоступны клиенту.
Дополнительные ресурсы
ASP.NET Core
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по