[譯] 在 ASP.NET Core 中使用 SignalR

原文:weblogs.asp.net/ricardopere…javascript

做者:Ricardo Pereshtml

轉載自:oopsguy.comjava

介紹

SignalR 是一個用於實現實時功能的 Microsoft .NET 庫。它使用了多種技術來實現服務器與客戶端間的雙向通訊,服務器能夠隨時將消息推送到鏈接的客戶端。node

如今你能夠在 ASP.NET Core 預發行版本中體驗它(譯者:根據原文的發佈時間)。我已經介紹過幾回 SignalR 了。web

安裝

你將須要安裝 Microsoft.AspNetCore.SignalR.ClientMicrosoft.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 是一個繼承了 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>
複製代碼

請注意:

  1. 建立指向當前 URL 的鏈接後,連接添加了 chat 後綴,這與在 MapHub 中註冊的一致
  2. 它使用特定的傳輸方式進行初始化(本例中是 WebSockets),但這不是必需的,也就是說,你可讓 SignalR 本身採用合適的方式。對於某些操做系統(如 Windows 7),好比你可能沒法使用 WebSockets,所以你必須選擇 LongPollingServerSentEvents
  3. 須要經過調用 start 來初始化鏈接
  4. handler 的 Send 方法與 ChatHubSend 方法有相同的單個參數(message)

因此,每當有人訪問此頁面並調用 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 屬性纔會提供 ConnectionIdUser 兩個屬性。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

最後,咱們還能夠將消息從外部發送到 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,包括其可擴展性機制和一些更高級的使用場景。敬請期待!

相關文章
相關標籤/搜索