從中樞外部傳送訊息

SignalR 中樞是核心抽象概念,用於將訊息傳送給連線至 SignalR 伺服器的用戶端。 您也可以使用 IHubContext 服務,從應用程式中的其他位置傳送訊息。 本文說明如何存取 SignalRIHubContext,以從中樞外部將通知傳送給用戶端。

注意

IHubContext 用於將通知傳送給用戶端,其不會用於在 Hub 上呼叫方法。

檢視或下載範例程式碼(如何下載)

取得 IHubContext 的執行個體

在 ASP.NET Core SignalR 中,您可以透過相依性插入來存取 IHubContext 的執行個體。 您可以將 IHubContext 執行個體插入控制器、中介軟體或其他 DI 服務。 使用執行個體將訊息傳送至用戶端。

在控制器中插入 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 類別外部呼叫用戶端方法時,沒有與引動過程相關聯的呼叫端。 因此,無法存取 ConnectionIdCallerOthers 屬性。

需要將使用者對應至連線識別碼並保存該對應的應用程式可以執行下列其中一個動作:

  • 將單一或多個連線的對應保存為群組。 如需詳細資訊,請參閱 SignalR 中的群組
  • 透過單一資料庫服務保留連線和使用者資訊。 如需詳細資訊,請參閱將服務插入中樞。 單一資料庫服務可使用任何儲存體方法,例如:
    • 字典中的記憶體內部儲存體。
    • 永久的外部儲存體。 例如,使用 Azure.Data.Tables NuGet 套件的資料庫或 Azure 資料表儲存體。
  • 在用戶端之間傳遞連線識別碼。

從 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 實作的程式碼

其他資源