這次利用官網介紹的IUserId Provider
來替換掉單一使用者群組
當初為了向某位多開視窗的使用者也可以正確發送、接收訊息,採用了單一使用者群組的方式實作,但是這樣子會發現程式碼需要在 OnConnected 的時候做一些事情,而且是每一個 Hub 都要這樣做,所以今天改用 IUserIdProvider 的方式處理
原先 Hub 推訊息的部分Clients.Group(userId).Received($"{msg} at {DateTime.Now:f}");
,是依據我們給的 UserId 去找到該 Group,然後傳送給這個 Group 裡面所有的 Client;現在我們改用Clients.User(userId).Received(msg);
,直接將訊息送給使用者,但是要用Clients.Usre(userId)
之前,我們還必須要先告訴 SignalR,怎麼樣取得使用者 ID
自訂 UserIdProvider
依照文件,繼承IUserIdProvider
,實作介面方法,裡面撰寫如何取得使用者 ID 的邏輯,此處依照先前作法,仍舊是從 QueryString 取得 client 傳來的使用者唯一識別碼
需要注意的是使用者識別碼有區分大小寫
public class CustomUserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
// 從QueryString中取得ID作為使用者的識別名稱
var id = request.QueryString["id"];
return string.IsNullOrWhiteSpace(id) ? string.Empty : id;
}
}
註冊自訂的 Provider
直接在startup.cs
裡面註冊即可
public class Startup
{
public void Configuration(IAppBuilder app)
{
// 註冊自訂的使用者ID Provider規則
var idProvider = new CustomUserIdProvider();
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration { };
map.RunSignalR(hubConfiguration);
});
}
}
順便列出 Hub 的程式碼
public abstract class BaseHub : Hub<IClient>
{
/// <summary>
/// 傳遞訊息給某人
/// </summary>
/// <param name="userId">要傳遞的對象</param>
/// <param name="msg">訊息內容</param>
public void SendPrivateMsg(string userId, string msg)
{
//透過使用者ID來針對該使用者相關聯的連接發送訊息
//此處Clients.User()必須要先註冊自訂的IUserIdProvider,讓SignalR知道怎麼取得使用者Id
Clients.User(userId).Received($"{msg} at {DateTime.Now:f} By User");
}
/// <summary>
/// 傳送訊息給Hub的所有人
/// </summary>
/// <param name="msg">The MSG.</param>
public void Send(string msg)
{
Clients.All.Received($"{msg} at {DateTime.Now:f} By All");
}
}
[HubName("v4hub")]
public class V4Hub : BaseHub
{
}
嗯,沒錯,v4 測試版本的 Hub 程式碼直接就是繼承就好了,東西都在父類別,而且也不用再去 override,如果有多個 Hub,就直接繼承。因為我上一個版本也沒有重構…現在也懶得回頭重構了
細節有需要的請直接參考 GitHub