Senden von Nachrichten von außerhalb eines Hubs
Der SignalR-Hub ist die zentrale Abstraktion zum Senden von Nachrichten an Clients, die mit dem SignalR-Server verbunden sind. Es ist auch möglich, Nachrichten von anderen Stellen in Ihrer App zu senden, indem Sie den IHubContext
-Dienst verwenden. In diesem Artikel wird erklärt, wie Sie auf SignalRIHubContext
zugreifen, um Benachrichtigungen an Clients von außerhalb eines Hubs zu senden.
Hinweis
IHubContext
dient zum Senden von Benachrichtigungen an Clients, aber wird nicht zum Aufrufen von Methoden in Hub
verwendet.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Abrufen einer Instanz von IHubContext
In ASP.NET Core SignalR können Sie über Dependency Injection (DI) auf eine Instanz von IHubContext
zugreifen. Sie können eine Instanz von IHubContext
in einen Controller, eine Middleware oder einen anderen DI-Dienst einfügen. Mithilfe dieser Instanz können Sie Nachrichten an Clients senden.
Einfügen einer Instanz von IHubContext
in einen Controller
Sie können eine Instanz von IHubContext
in einen Controller einfügen, indem Sie sie Ihrem Konstruktor hinzufügen:
public class HomeController : Controller
{
private readonly IHubContext<NotificationHub> _hubContext;
public HomeController(IHubContext<NotificationHub> hubContext)
{
_hubContext = hubContext;
}
}
Mit Zugriff auf eine Instanz von IHubContext
rufen Sie Clientmethoden auf, als ob Sie sich auf dem Hub selbst befänden:
public async Task<IActionResult> Index()
{
await _hubContext.Clients.All.SendAsync("Notify", $"Home page loaded at: {DateTime.Now}");
return View();
}
Abrufen einer Instanz von IHubContext
in Middleware
Greifen Sie innerhalb der Middlewarepipeline wie folgt auf IHubContext
zu:
app.Use(async (context, next) =>
{
var hubContext = context.RequestServices
.GetRequiredService<IHubContext<ChatHub>>();
//...
if (next != null)
{
await next.Invoke();
}
});
Hinweis
Wenn Clientmethoden von außerhalb der Hub
-Klasse aufgerufen werden, ist dem Aufruf kein Aufrufer zugeordnet. Daher ist kein Zugriff auf die Eigenschaften ConnectionId
, Caller
und Others
möglich.
Apps, die einen Benutzer der Verbindungs-ID zuordnen und diese Zuordnung beibehalten müssen, haben folgende Möglichkeiten:
- Beibehalten der Zuordnung einzelner oder mehrerer Verbindungen als Gruppen. Weitere Informationen finden Sie unter Gruppen in SignalR.
- Beibehalten von Verbindungs- und Benutzerinformationen über einen Singletondienst. Weitere Informationen finden Sie unter Einfügen von Diensten in einen Hub. Der Singletondienst kann eine beliebige Speichermethode verwenden, z. B.:
- In-Memory-Speicher in einem Wörterbuch.
- Permanenten externer Speicher. Beispielsweise eine Datenbank oder Azure Table Storage unter Verwendung des NuGet-Pakets Azure.Data.Tables.
- Übergeben der Verbindungs-ID zwischen Clients.
Abrufen einer Instanz von IHubContext
von IHost
Der Zugriff auf IHubContext
vom Webhost aus ist nützlich für die Integration mit Bereichen außerhalb von ASP.NET Core, z. B. unter Verwendung von Dependency Injection-Frameworks von Drittanbietern:
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var hubContext = host.Services.GetService(typeof(IHubContext<ChatHub>));
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => {
webBuilder.UseStartup<Startup>();
});
}
Einfügen einer stark typisierten HubContext-Instanz
Um eine stark typisierte HubContext-Instanz einzufügen, stellen Sie sicher, dass Ihr Hub von Hub<T>
erbt. Fügen Sie sie mithilfe der IHubContext<THub, T>
-Schnittstelle statt mit IHubContext<THub>
ein.
public class ChatController : Controller
{
public IHubContext<ChatHub, IChatClient> _strongChatHubContext { get; }
public ChatController(IHubContext<ChatHub, IChatClient> chatHubContext)
{
_strongChatHubContext = chatHubContext;
}
public async Task SendMessage(string user, string message)
{
await _strongChatHubContext.Clients.All.ReceiveMessage(user, message);
}
}
Weitere Informationen finden Sie unter Stark typisierte Hubs.
Verwenden von IHubContext
in generischem Code
Eine eingefügte IHubContext<THub>
-Instanz kann ohne Angabe eines generischen Hub
-Typs in IHubContext
umgewandelt werden.
class MyHub : Hub
{ }
class MyOtherHub : Hub
{ }
app.Use(async (context, next) =>
{
var myHubContext = context.RequestServices
.GetRequiredService<IHubContext<MyHub>>();
var myOtherHubContext = context.RequestServices
.GetRequiredService<IHubContext<MyOtherHub>>();
await CommonHubContextMethod((IHubContext)myHubContext);
await CommonHubContextMethod((IHubContext)myOtherHubContext);
await next.Invoke();
}
async Task CommonHubContextMethod(IHubContext context)
{
await context.Clients.All.SendAsync("clientMethod", new Args());
}
Diese Möglichkeit ist in folgenden Situationen nützlich:
- Schreiben von Bibliotheken, die keinen Verweis auf den spezifischen
Hub
-Typ aufweisen, den die App verwendet. - Schreiben von Code, der generisch ist und auf mehrere verschiedene
Hub
-Implementierungen angewendet werden kann