Usar filtros de hub no ASP.NET Core SignalR
Filtros de hub:
- Estão disponíveis no ASP.NET Core 5.0 ou posterior.
- Permitem que a lógica seja executada antes e depois que os métodos de hub são invocados pelos clientes.
Esse artigo fornece diretrizes para escrever e usar filtros de hub.
Configurar filtros de hub
Os filtros de hub podem ser aplicados globalmente ou por tipo de hub. A ordem na qual os filtros são adicionados é a ordem na qual os filtros são executados. Os filtros de hub global são executados antes dos filtros de hub local.
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>();
});
}
Um filtro de hub pode ser adicionado de uma das seguintes maneiras:
Adicione um filtro por tipo concreto:
hubOptions.AddFilter<TFilter>();
Isso será resolvido por meio da injeção de dependência (DI) ou do tipo ativado.
Adicione um filtro por tipo de runtime:
hubOptions.AddFilter(typeof(TFilter));
Isso será resolvido a partir do DI ou do tipo ativado.
Adicione um filtro por instância:
hubOptions.AddFilter(new MyFilter());
Essa instância será usada como um banco de dados individual. Todas as invocações de método de hub usarão a mesma instância.
Os filtros de hub são criados e descartados por invocação de hub. Se você quiser armazenar o estado global no filtro ou nenhum estado, adicione o tipo de filtro de hub à DI como um banco de dados individual para obter um melhor desempenho. Como alternativa, adicione o filtro como uma instância se puder.
Criar filtros de hub
Crie um filtro declarando uma classe que herda de IHubFilter
e adicione o método InvokeMethodAsync
. Há também OnConnectedAsync
e OnDisconnectedAsync
que, opcionalmente, podem ser implementados para encapsular os métodos de hub OnConnectedAsync
e OnDisconnectedAsync
, respectivamente.
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);
}
}
Os filtros são muito semelhantes ao middleware. O método next
invoca o próximo filtro. O filtro final invocará o método hub. Os filtros também podem armazenar o resultado da lógica de espera next
e da lógica de execução após o método de hub ter sido chamado antes de retornar o resultado de next
.
Para ignorar uma invocação de método de hub em um filtro, gere uma exceção do tipo HubException
em vez de chamar next
. O cliente receberá um erro se esperava um resultado.
Usar filtros de hub
Ao escrever a lógica de filtro, tente torná-la genérica usando atributos em métodos de hub em vez de verificar nomes de método de hub.
Considere um filtro que verificará um argumento de método de hub para frases proibidas e substituirá todas as frases encontradas por ***
.
Para esse exemplo, suponha que uma classe LanguageFilterAttribute
seja definida. A classe tem uma propriedade chamada FilterArgument
que pode ser definida ao usar o atributo .
Coloque o atributo no método de hub que tem um argumento de cadeia de caracteres a ser limpo:
public class ChatHub { [LanguageFilter(filterArgument = 0)] public async Task SendMessage(string message, string username) { await Clients.All.SendAsync("SendMessage", $"{username} says: {message}"); } }
Defina um filtro de hub para marcar para o atributo e substitua frases proibidas em um argumento de método de hub por
***
: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); } }
Registre o filtro de hub no método
Startup.ConfigureServices
. Para evitar a reinicialização da lista de frases proibidas para cada invocação, o filtro de hub é registrado como um banco de dados individual:public void ConfigureServices(IServiceCollection services) { services.AddSignalR(hubOptions => { hubOptions.AddFilter<LanguageFilter>(); }); services.AddSingleton<LanguageFilter>(); }
O objeto HubInvocationContext
O HubInvocationContext
contém informações para a invocação do método de hub atual.
Propriedade | Descrição | Type |
---|---|---|
Context |
O HubCallerContext contém informações sobre a conexão. |
HubCallerContext |
Hub |
A instância do Hub que está sendo usada para essa invocação de método de hub. | Hub |
HubMethodName |
O nome do método de hub que está sendo invocado. | string |
HubMethodArguments |
A lista de argumentos que estão sendo passados para o método hub. | IReadOnlyList<string> |
ServiceProvider |
O provedor de serviços com escopo para essa invocação de método de hub. | IServiceProvider |
HubMethod |
As informações do método de hub. | MethodInfo |
O objeto HubLifetimeContext
O HubLifetimeContext
contém informações para os OnConnectedAsync
métodos de hub e OnDisconnectedAsync
.
Propriedade | Descrição | Type |
---|---|---|
Context |
O HubCallerContext contém informações sobre a conexão. |
HubCallerContext |
Hub |
A instância do Hub que está sendo usada para essa invocação de método de hub. | Hub |
ServiceProvider |
O provedor de serviços com escopo para essa invocação de método de hub. | IServiceProvider |
Autorização e filtros
A autorização de atributos em métodos de hub é executa antes dos filtros de hub.
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de