Использование фильтров концентратора в ASP.NET Core SignalR
Фильтры концентратора:
- Доступны в ASP.NET Core 5.0 или более поздней версии.
- Разрешить выполнение логики до и после вызова методов концентратора клиентами.
В этой статье приводятся рекомендации по написанию и использованию фильтров концентратора.
Настройка фильтров концентратора
Фильтры концентратора можно применять глобально или на один тип концентратора. Порядок добавления фильтров — это порядок выполнения фильтров. Глобальные фильтры концентратора выполняются до локальных фильтров концентратора.
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR(options =>
{
// Global filters will run first
options.AddFilter<CustomFilter>();
}).AddHubOptions<ChatHub>(options =>
{
// Local filters will run second
options.AddFilter<CustomFilter2>();
});
}
Фильтр концентратора можно добавить одним из следующих способов:
Добавьте фильтр по конкретному типу:
hubOptions.AddFilter<TFilter>();
Это будет разрешено из внедрения зависимостей (DI) или типа, активированного.
Добавьте фильтр по типу среды выполнения:
hubOptions.AddFilter(typeof(TFilter));
Это будет разрешено из di или типа активировано.
Добавление фильтра по экземпляру:
hubOptions.AddFilter(new MyFilter());
Этот экземпляр будет использоваться как одноэлементный. Все вызовы методов концентратора будут использовать один и тот же экземпляр.
Фильтры концентратора создаются и удаляются для каждого вызова концентратора. Если вы хотите сохранить глобальное состояние в фильтре или нет состояния, добавьте тип фильтра концентратора в di в качестве одного из вариантов для повышения производительности. Кроме того, добавьте фильтр в качестве экземпляра, если это возможно.
Создание фильтров концентратора
Создайте фильтр, объявив класс, наследуемый InvokeMethodAsync
от IHubFilter
и добавьте метод. Существует также OnConnectedAsync
и OnDisconnectedAsync
то, что может быть реализовано при необходимости для упаковки OnConnectedAsync
методов и OnDisconnectedAsync
концентраторов соответственно.
public class CustomFilter : IHubFilter
{
public async ValueTask<object> InvokeMethodAsync(
HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
{
Console.WriteLine($"Calling hub method '{invocationContext.HubMethodName}'");
try
{
return await next(invocationContext);
}
catch (Exception ex)
{
Console.WriteLine($"Exception calling '{invocationContext.HubMethodName}': {ex}");
throw;
}
}
// Optional method
public Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next)
{
return next(context);
}
// Optional method
public Task OnDisconnectedAsync(
HubLifetimeContext context, Exception exception, Func<HubLifetimeContext, Exception, Task> next)
{
return next(context, exception);
}
}
Фильтры очень похожи на ПО промежуточного слоя. Метод next
вызывает следующий фильтр. Последний фильтр вызовет метод концентратора. Фильтры также могут хранить результат ожидания next
и выполнения логики после вызова метода концентратора, прежде чем возвращать результат из next
.
Чтобы пропустить вызов метода концентратора в фильтре, создайте исключение типа HubException
вместо вызова next
. Клиент получит ошибку, если он ожидал результата.
Использование фильтров концентратора
При написании логики фильтра попробуйте сделать его универсальным с помощью атрибутов в методах концентратора вместо проверка имен методов концентратора.
Рассмотрим фильтр, который будет проверка аргумент метода концентратора для запрещенных фраз и замените любые фразы, на которые он находит***
.
В этом примере предполагается, что LanguageFilterAttribute
класс определен. Класс имеет свойство с именем FilterArgument
, которое можно задать при использовании атрибута.
Поместите атрибут в метод концентратора, имеющий строковый аргумент для очистки:
public class ChatHub { [LanguageFilter(filterArgument = 0)] public async Task SendMessage(string message, string username) { await Clients.All.SendAsync("SendMessage", $"{username} says: {message}"); } }
Определите фильтр концентратора для проверка атрибута и замените запрещенные фразы в аргументе метода концентратора следующим
***
образом:public class LanguageFilter : IHubFilter { // populated from a file or inline private List<string> bannedPhrases = new List<string> { "async void", ".Result" }; public async ValueTask<object> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next) { var languageFilter = (LanguageFilterAttribute)Attribute.GetCustomAttribute( invocationContext.HubMethod, typeof(LanguageFilterAttribute)); if (languageFilter != null && invocationContext.HubMethodArguments.Count > languageFilter.FilterArgument && invocationContext.HubMethodArguments[languageFilter.FilterArgument] is string str) { foreach (var bannedPhrase in bannedPhrases) { str = str.Replace(bannedPhrase, "***"); } var arguments = invocationContext.HubMethodArguments.ToArray(); arguments[languageFilter.FilterArgument] = str; invocationContext = new HubInvocationContext(invocationContext.Context, invocationContext.ServiceProvider, invocationContext.Hub, invocationContext.HubMethod, arguments); } return await next(invocationContext); } }
Зарегистрируйте фильтр концентратора в методе
Startup.ConfigureServices
. Чтобы избежать повторной инициализации списка запрещенных фраз для каждого вызова, фильтр концентратора регистрируется как одноэлементный:public void ConfigureServices(IServiceCollection services) { services.AddSignalR(hubOptions => { hubOptions.AddFilter<LanguageFilter>(); }); services.AddSingleton<LanguageFilter>(); }
Объект HubInvocationContext
Содержит HubInvocationContext
сведения о вызове текущего метода концентратора.
Свойство | Описание | Тип |
---|---|---|
Context |
Содержит HubCallerContext сведения о подключении. |
HubCallerContext |
Hub |
Экземпляр концентратора, используемого для вызова этого метода концентратора. | Hub |
HubMethodName |
Имя вызываемого метода концентратора. | string |
HubMethodArguments |
Список аргументов, передаваемых в метод концентратора. | IReadOnlyList<string> |
ServiceProvider |
Поставщик услуг область для вызова этого метода концентратора. | IServiceProvider |
HubMethod |
Сведения о методе концентратора. | MethodInfo |
Объект HubLifetimeContext
Содержит HubLifetimeContext
сведения о методах и OnDisconnectedAsync
методах концентратораOnConnectedAsync
.
Свойство | Описание | Тип |
---|---|---|
Context |
Содержит HubCallerContext сведения о подключении. |
HubCallerContext |
Hub |
Экземпляр концентратора, используемого для вызова этого метода концентратора. | Hub |
ServiceProvider |
Поставщик услуг область для вызова этого метода концентратора. | IServiceProvider |
Авторизация и фильтры
Авторизация атрибутов в методах концентратора, выполняемых до фильтров концентратора.
ASP.NET Core
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по