SignalR HubContext
Nguồn: SignalR HubContext
SignalR hub (trung tâm) là abstraction (lớp trừu tượng) cốt lõi để gửi tin nhắn đến các client đã kết nối với server SignalR. Ngoài ra, bạn cũng có thể gửi tin nhắn từ các vị trí khác trong ứng dụng bằng dịch vụ IHubContext. Bài viết này giải thích cách truy cập IHubContext của SignalR để gửi thông báo đến client từ bên ngoài hub.
Lưu ý: IHubContext được dùng để gửi thông báo đến client, không phải để gọi các phương thức trên Hub.
Lấy một instance của IHubContext
Trong ASP.NET Core SignalR, bạn có thể truy cập một instance của IHubContext thông qua dependency injection (DI - tiêm phụ thuộc). Bạn có thể inject (tiêm) một instance của IHubContext vào controller, middleware (phần mềm trung gian) hoặc dịch vụ DI khác. Sử dụng instance đó để gửi tin nhắn đến client.
Inject một instance của IHubContext vào controller
Bạn có thể inject một instance của IHubContext vào một controller bằng cách thêm nó vào constructor (hàm khởi tạo):
public class HomeController : Controller
{
private readonly IHubContext<NotificationHub> _hubContext;
public HomeController(IHubContext<NotificationHub> hubContext)
{
_hubContext = hubContext;
}
}Với quyền truy cập vào một instance của IHubContext, bạn gọi các phương thức client như thể đang ở trong hub:
public async Task<IActionResult> Index()
{
await _hubContext.Clients.All.SendAsync("Notify", $"Home page loaded at: {DateTime.Now}");
return View();
}Lấy một instance của IHubContext trong middleware
Truy cập IHubContext trong pipeline middleware như sau:
app.Use(async (context, next) =>
{
var hubContext = context.RequestServices
.GetRequiredService<IHubContext<ChatHub>>();
//...
if (next != null)
{
await next.Invoke();
}
});Lưu ý: Khi các phương thức client được gọi từ bên ngoài class Hub, không có caller (người gọi) nào được liên kết với lời gọi. Do đó, không có quyền truy cập vào các thuộc tính ConnectionId, Caller và Others.
Các ứng dụng cần ánh xạ người dùng với connection ID và duy trì ánh xạ đó có thể thực hiện một trong những cách sau:
- Duy trì ánh xạ của một hoặc nhiều kết nối dưới dạng nhóm. Xem thêm Groups in SignalR. - Lưu giữ thông tin kết nối và người dùng thông qua một singleton service. Xem thêm Inject services into a hub. Singleton service có thể sử dụng bất kỳ phương thức lưu trữ nào, chẳng hạn: - Lưu trữ trong bộ nhớ (in-memory) trong một dictionary. - Lưu trữ bên ngoài vĩnh viễn, ví dụ database hoặc Azure Table storage. - Truyền connection ID giữa các client.
Lấy một instance của IHubContext từ IHost
Truy cập IHubContext từ web host hữu ích khi tích hợp với các khu vực bên ngoài ASP.NET Core, ví dụ sử dụng framework dependency injection bên thứ ba:
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>();
});
}Inject một strongly-typed HubContext (HubContext có kiểu mạnh)
Để inject một strongly-typed HubContext, đảm bảo Hub của bạn kế thừa từ Hub<T>. Inject nó bằng interface IHubContext<THub, T> thay vì 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);
}
}Xem thêm Sử dụng strongly typed hubs để biết thêm thông tin.
Sử dụng IHubContext trong code chung (generic code)
Một instance IHubContext<THub> được inject có thể được cast (chuyển đổi kiểu) sang IHubContext không có kiểu generic Hub được chỉ định.
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());
}Điều này hữu ích khi:
- Viết các thư viện không có tham chiếu đến kiểu
Hubcụ thể mà ứng dụng đang sử dụng. - Viết code chung có thể áp dụng cho nhiều triển khai
Hubkhác nhau.