SignalR ハブは、SignalR サーバーに接続されているクライアントにメッセージを送信するための中核となる抽象化です。 また、IHubContext
サービスを使ってアプリ内の他の場所からメッセージを送信することもできます。 この記事では、SignalRIHubContext
にアクセスしてハブの外部からクライアントに通知を送信する方法について説明します。
注
IHubContext
はクライアントに通知を送信するためのものであり、Hub
に対してメソッドを呼び出すためには使われません。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
IHubContext
のインスタンスを取得する
ASP.NET Core SignalR では、依存関係の挿入を介して IHubContext
のインスタンスにアクセスできます。 コントローラーやミドルウェアなどの DI サービスに IHubContext
のインスタンスを挿入することができます。 そのインスタンスを使ってクライアントにメッセージを送信します。
コントローラーに IHubContext
のインスタンスを挿入する
コントローラーに IHubContext
のインスタンスを挿入するには、コンストラクターに追加します。
public class HomeController : Controller
{
private readonly IHubContext<NotificationHub> _hubContext;
public HomeController(IHubContext<NotificationHub> hubContext)
{
_hubContext = hubContext;
}
}
IHubContext
のインスタンスにアクセスして、そのハブ内からのようにクライアント メソッドを呼び出します。
public async Task<IActionResult> Index()
{
await _hubContext.Clients.All.SendAsync("Notify", $"Home page loaded at: {DateTime.Now}");
return View();
}
ミドルウェアで IHubContext
のインスタンスを取得する
次のように、ミドルウェア パイプライン内で IHubContext
にアクセスします。
app.Use(async (context, next) =>
{
var hubContext = context.RequestServices
.GetRequiredService<IHubContext<ChatHub>>();
//...
if (next != null)
{
await next.Invoke();
}
});
注
Hub
クラスの外部からクライアント メソッドを呼び出す場合、その呼び出しに関連付けられた呼び出し元はありません。 そのため、ConnectionId
、Caller
、Others
のプロパティにはアクセスできません。
ユーザーを接続 ID にマップし、そのマッピングを保持する必要があるアプリは、次のいずれかを実行できます。
- 単一または複数の接続のマッピングをグループとして保持します。 詳細については、「 SignalRのグループ」を参照してください。
- シングルトン サービスを介して接続とユーザー情報を保持します。 詳細については、「ハブにサービスを挿入する」を参照してください。 シングルトン サービスでは、次のような任意のストレージ方法を使用できます。
- ディクショナリ内のメモリ内ストレージ。
- 永続的な外部ストレージ。 たとえば、データベースや Azure.Data.Tables NuGet パッケージを使用する Azure Table Storage などです。
- クライアント間で接続 ID を渡します。
IHost から IHubContext
のインスタンスを取得する
Web ホストから IHubContext
にアクセスする方法は、サードパーティの依存関係の挿入フレームワークを使うなど、ASP.NET Core の外部にある領域と統合する場合に便利です。
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>();
});
}
厳密に型指定された HubContext を挿入する
厳密に型指定された HubContext を挿入するには、ハブが Hub<T>
から継承されていることを確認します。
IHubContext<THub, T>
ではなく IHubContext<THub>
インターフェイスを使って挿入します。
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);
}
}
詳細については、「厳密に型指定されたハブ」を参照してください。
ジェネリック コードで IHubContext
を使う
挿入された IHubContext<THub>
インスタンスは、ジェネリック IHubContext
型が指定されていなくても Hub
にキャストできます。
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());
}
これは、次の場合に便利です。
- アプリに使われている特定の
Hub
型への参照を持たないライブラリを書く。 - 複数の異なる
Hub
の実装に適用できる汎用的なコードを書く。
その他のリソース
ASP.NET Core