原文:weblogs.asp.net/ricardopere…javascript
做者:Ricardo Pereshtml
轉載自:oopsguy.comjava
SignalR 是一個用於實現實時功能的 Microsoft .NET 庫。它使用了多種技術來實現服務器與客戶端間的雙向通訊,服務器能夠隨時將消息推送到鏈接的客戶端。node
如今你能夠在 ASP.NET Core 預發行版本中體驗它(譯者:根據原文的發佈時間)。我已經介紹過幾回 SignalR 了。web
你將須要安裝 Microsoft.AspNetCore.SignalR.Client 和 Microsoft.AspNetCore.SignalR 這兩個 Nuget 預發行包。此外,你還須要 NPM(Node 包管理器)。安裝 NPM 後,你須要獲取 @aspnet/signalr-client 包,以後再從 node_modules@aspnet\signalr-client\dist\browser 文件夾中獲取 signalr-client-1.0.0-alpha1-final.js 文件(版本可能不一樣),並將其放置在 wwwroot 文件夾下,以即可以從頁面引用到它。npm
在使用前,咱們須要在 ConfigureServices 中註冊必須的服務:服務器
services.AddSignalR();
複製代碼
咱們將實現一個簡單的聊天客戶端,所以要在 Configure 方法中註冊一個 ChatHub:app
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("chat");
});
複製代碼
注意:UseSignalR 必須在 UseMvc 以前調用!asp.net
若是你有不一樣的端點,能夠爲每一個 hub 執行此操做。async
在視圖或佈局文件中,添加對 signalr-client-1.0.0-alpha1-final.js 文件的引用:
<script src="libs/signalr-client/signalr-client-1.0.0-alpha1-final.js"></script>
複製代碼
該 hub 是一個繼承了 Hub 的類。你可在其中添加 JavaScript 可能用到的方法。咱們將實現一個 chat hub:
public class ChatHub : Hub
{
public async Task Send(string message) {
await this.Clients.All.InvokeAsync("Send", message);
}
}
複製代碼
如上所述,咱們有一個方法(Send),在本例中,它採用了單參數(message)。你不須要在廣播調用(InvokeAsync)上傳遞相同的參數,能夠發送任何你想要傳遞的參數。
回到客戶端部分,在引用 SignalR JavaScript 文件後添加以下代碼:
<script> var transportType = signalR.TransportType.WebSockets; //can also be ServerSentEvents or LongPolling var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information); var chatHub = new signalR.HttpConnection(`http://${document.location.host}/chat`, { transport: transportType, logger: logger }); var chatConnection = new signalR.HubConnection(chatHub, logger); chatConnection.onClosed = e => { console.log('connection closed'); }; chatConnection.on('Send', (message) => { console.log('received message'); }); chatConnection.start().catch(err => { console.log('connection error'); }); function send(message) { chatConnection.invoke('Send', message); } </script>
複製代碼
請注意:
因此,每當有人訪問此頁面並調用 JavaScript send函數時,它將調用 ChatHub 類上的 Send 方法。該類基本上會向全部鏈接的客戶端(Clients.All)廣播此消息。也能夠將消息發送到特定的組:
await this.Clients.Group("groupName").InvokeAsync("Send", message);
複製代碼
或特定客戶端:
await this.Clients.Client("id").InvokeAsync("Send", message);
複製代碼
你若是想啓用身份驗證,能夠添加一個由鏈接 ID 和 ClaimPrincipal 標識的用戶,以下所示:
public override Task OnConnectedAsync() {
this.Groups.AddAsync(this.Context.ConnectionId, "groupName");
return base.OnConnectedAsync();
}
複製代碼
OnConnectedAsync 在新用戶鏈接時將被調用。當有人斷開鏈接時,OnDisconnectedAsync 將被調用:
public override Task OnDisconnectedAsync(Exception exception) {
return base.OnDisconnectedAsync(exception);
}
複製代碼
若是在斷開鏈接時發生了異常,則 exception 參數將爲非空值。
只有當前用戶進行身份驗證時, Context 屬性纔會提供 ConnectionId 和 User 兩個屬性。ConnectionId 始終被設置爲同一個用戶,不會改變。 另外,假設你想經過定時器 hub 將定時器 tick 發送到全部鏈接的客戶端,則能夠在 Configure 方法中執行此操做:
TimerCallback callback = (x) => {
var hub = serviceProvider.GetService<IHubContext<TimerHub>>();
hub.Clients.All.InvokeAsync("Notify", DateTime.Now);
};
var timer = new Timer(callback);
timer.Change(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(10));
複製代碼
咱們啓動了一個 Timer,從那裏咱們獲得了一個定時器 hub 的引用,並使用當前時間戳調用其 Notify 方法。TimerHub 類只是這樣:
public class TimerHub : Hub
{
}
複製代碼
請注意,此類沒有公共方法,由於它不是由 JavaScript 調用,它僅用於從外部廣播消息(Timer 回調)。
最後,咱們還能夠將消息從外部發送到 hub。當使用控制器時,你須要注入一個 IHubContext 實例,你能夠在裏面發送消息到 hub,而後將其廣播:
private readonly IHubContext<ChatHub> _context;
[HttpGet("Send/{message}")]
public IActionResult Send(string message) {
//for everyone
this._context.Clients.All.InvokeAsync("Send", message);
//for a single group
this._context.Clients.Group("groupName").InvokeAsync("Send", message);
//for a single client
this._context.Clients.Client("id").InvokeAsync("Send", message);
return this.Ok();
}
複製代碼
須要注意的是,這與訪問 ChatHub 類不一樣,實現起來並不簡單,你須要使用 chat hub 的鏈接才行。
SignalR 還沒有發佈,仍可能會有一些變化。在之後的文章中,我將更詳細地介紹 SignalR,包括其可擴展性機制和一些更高級的使用場景。敬請期待!