Verwenden von Hubfiltern in ASP.NET Core SignalR
Hubfilter:
- Sind ab ASP.NET Core 5.0 verfügbar
- Lassen die Ausführung von Logik vor und nach Aufrufen von Hubmethoden durch Clients zu
Dieser Artikel enthält Anleitungen zum Schreiben und Verwenden von Hubfiltern.
Konfigurieren von Hubfiltern
Hubfilter können global oder basierend auf dem Hubtyp angewendet werden. Die Filter werden in der Reihenfolge hinzugefügt, in der sie ausgeführt werden. Globale werden vor lokalen Hubfiltern ausgeführt.
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>();
});
}
Ein Hubfilter kann auf eine der folgenden Weisen hinzugefügt werden:
Hinzufügen eines Filters nach konkretem Typ:
hubOptions.AddFilter<TFilter>();
Die Auflösung erfolgt über Dependency Injection (DI) oder aktivierten Typ.
Hinzufügen eines Filters nach Laufzeittyp:
hubOptions.AddFilter(typeof(TFilter));
Die Auflösung erfolgt über DI oder aktivierten Typ.
Hinzufügen eines Filters nach Instanz:
hubOptions.AddFilter(new MyFilter());
Diese Instanz wird wie ein Singleton verwendet. Alle Hubmethodenaufrufe verwenden dieselbe Instanz.
Hubfilter werden pro Hubaufruf erstellt und verworfen. Wenn Sie den globalen Zustand im Filter oder keinen Zustand speichern möchten, fügen Sie den Hubfiltertyp zu DI als Singleton hinzu, um die Leistung zu verbessern. Alternativ können Sie den Filter, sofern möglich, als Instanz hinzufügen.
Erstellen von Hubfiltern
Sie erstellen einen Filter, indem Sie eine Klasse deklarieren, die von IHubFilter
erbt, und die InvokeMethodAsync
-Methode hinzufügen. Es gibt auch OnConnectedAsync
und OnDisconnectedAsync
, die optional implementiert werden können, um die Hubmethoden OnConnectedAsync
bzw. OnDisconnectedAsync
zu umschließen.
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);
}
}
Filter sind Middleware sehr ähnlich. Die next
-Methode ruft den nächsten Filter auf. Der letzte Filter ruft die Hubmethode auf. Filter können auch das Ergebnis aus dem Warten auf next
speichern und Logik ausführen, nachdem die Hubmethode aufgerufen wurde, ehe das Ergebnis von next
zurückgegeben wird.
Um einen Hubmethodenaufruf in einem Filter zu überspringen, lösen Sie eine Ausnahme des Typs HubException
aus, anstatt next
aufzurufen. Der Client erhält eine Fehlermeldung, wenn er ein Ergebnis erwartet hat.
Verwenden von Hubfiltern
Wenn Sie die Filterlogik schreiben, versuchen Sie, sie generisch zu gestalten, indem Sie Attribute für Hubmethoden verwenden, anstatt auf Namen von Hubmethoden zu prüfen.
Betrachten wir einen Filter, der ein Argument der Hubmethode auf unzulässige Formulierungen prüft und alle gefundenen Formulierungen durch ***
ersetzt.
In diesem Beispiel wird davon ausgegangen, dass eine LanguageFilterAttribute
-Klasse definiert ist. Die Klasse verfügt über eine Eigenschaft namens FilterArgument
, die bei Verwendung des Attributs festgelegt werden kann.
Platzieren Sie das Attribut in der Hubmethode, die über ein zu bereinigende Zeichenfolgenargument verfügt:
public class ChatHub { [LanguageFilter(filterArgument = 0)] public async Task SendMessage(string message, string username) { await Clients.All.SendAsync("SendMessage", $"{username} says: {message}"); } }
Definieren Sie einen Hubfilter, um auf das Attribut zu prüfen, und ersetzen Sie unzulässige Formulierungen in einem Hubmethodenargument durch
***
: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); } }
Registrieren Sie den Hubfilter in der
Startup.ConfigureServices
-Methode. Um zu vermeiden, dass die Liste der unzulässigen Formulierungen für jeden Aufruf neu initialisiert wird, wird der Hubfilter als Singleton registriert:public void ConfigureServices(IServiceCollection services) { services.AddSignalR(hubOptions => { hubOptions.AddFilter<LanguageFilter>(); }); services.AddSingleton<LanguageFilter>(); }
Das HubInvocationContext-Objekt
HubInvocationContext
enthält Informationen für den aktuellen Hubmethodenaufruf.
Eigenschaft | Beschreibung des Dataflows | Typ |
---|---|---|
Context |
HubCallerContext enthält Informationen zur Verbindung. |
HubCallerContext |
Hub |
Die Instanz des Hubs, der für diesen Aufruf der Hubmethode verwendet wird. | Hub |
HubMethodName |
Der Name der aufgerufenen Hubmethode. | string |
HubMethodArguments |
Die Liste der Argumente, die an die Hubmethode übergeben werden. | IReadOnlyList<string> |
ServiceProvider |
Der bereichsbezogene Dienstanbieter für diesen Hubmethodenaufruf. | IServiceProvider |
HubMethod |
Die Informationen zur Hubmethode. | MethodInfo |
Das HubLifetimeContext-Objekt
HubLifetimeContext
enthält Informationen für die Hubmethoden OnConnectedAsync
und OnDisconnectedAsync
.
Eigenschaft | Beschreibung des Dataflows | Typ |
---|---|---|
Context |
HubCallerContext enthält Informationen zur Verbindung. |
HubCallerContext |
Hub |
Die Instanz des Hubs, der für diesen Hubmethodenaufruf verwendet wird. | Hub |
ServiceProvider |
Der bereichsbezogene Dienstanbieter für diesen Hubmethodenaufruf. | IServiceProvider |
Autorisierung und Filter
Autorisieren Sie Attribute für Hubmethoden, die vor Hubfiltern ausgeführt werden.
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für