[鐵人賽Day20] - ASP.Net Core MVC 進化之路 - SignalR

SignalR是一套.Net提供的訊息即時同步的傳遞機制,

可以開發如聊天室、監控平台應用,

本文將介紹ASP.Net Core中SignalR的使用方式。

 

微軟在今年5月正式推出ASP.Net Core SignalR 1.0.0版本,

短短幾個月已經到1.0.4版了。

(圖片來源:https://github.com/aspnet/SignalR/releases)

 

SignalR可以用來解決需即時同步的Web服務程式,

官方提供的適用情境如下:

  • 需要來自伺服器的高頻率更新的應用程式。 範例包括遊戲、 社交網路、 投票、 拍賣、 GPS地圖應用程式。
  • 儀表板和監視平台:系統監控儀表板,立即銷售的更新,旅遊警示。
  • 共同作業平台:白板應用程式和小組會議軟體是共同作業應用程式的範例。
  • 需要被通知的應用程式: 社交網路平台、 電子郵件、 聊天室、 遊戲等。

 

SignalR是透過Client端的javascript與伺服器端的Signal Hub建立連線

傳輸方式有Long-Polling、WebSockets、Server-Sent events三種,

可在javascript建立connection時指定。

並由Signal Hub擔任控制中樞定義各個事件的邏輯控制,

最後將訊息結果推送到Client端。

示意圖如下:

 

以下參考官方教學文件實作一個簡易聊天程式,

筆者使用的SignalR版本為1.0.4,

VS2017須更新至15.8版以上才有這個版號。

 

部份步驟筆者會跳過,

如有需要完整操作流程的可以參考官方提供教學文件

 

首先在專案中按右鍵 > 加入 > 新增用戶端程式庫

 

接著選擇提供者[unpkg] > 輸入@aspnet/signalr@1 > 選擇版號(發文時為1.0.4版) > 選擇特定檔案 > 確定。

 

安裝後在wwwroot/lib/@aspnet/signalr裡面多了signalr.js的檔案。

 

接著在StartupConfigureServices()加入SignalR服務。

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

 

好了之後我們要來建立一個ChatHub中樞,

這邊要記得繼承 Hub 類別。

ChatHub.cs

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        var content = $"{user} 於{DateTime.Now.ToShortTimeString()}說:{message}";

        await Clients.All.SendAsync("ReceiveMessage", content);
    }
}

 

接著再回到StartupConfigure()註冊呼叫ChatHub的路由。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseSignalR(routes =>
    {
        routes.MapHub<ChatHub>("/chatHub");
    });

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

 

最後一步在前端使用javascript呼叫ChatHub。

index.cshtml


<h2>Index</h2>
<div class="container">
    <div class="row">&nbsp;</div>
    <div class="row">
        <div class="col-6">&nbsp;</div>
        <div class="col-6">
            User..........<input type="text" id="userInput" />
            <br />
            Message...<input type="text" id="messageInput" />
            <input type="button" id="sendButton" value="Send Message" />
        </div>
    </div>
    <div class="row">
        <div class="col-12">
            <hr />
        </div>
    </div>
    <div class="row">
        <div class="col-6">&nbsp;</div>
        <div class="col-6">
            <ul id="messagesList"></ul>
        </div>
    </div>
</div>
@section scripts
{
    <script src="~/lib/@@aspnet/signalr/dist/browser/signalr.js"></script>
    <script>
        
        var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

        connection.on("ReceiveMessage", function (content) {
            var li = document.createElement("li");
            li.textContent = content;
            document.getElementById("messagesList").appendChild(li);
        });

        connection.start().catch(function (err) {
            return console.error(err.toString());
        });

        document.getElementById("sendButton").addEventListener("click", function (event) {
            var user = document.getElementById("userInput").value;
            var message = document.getElementById("messageInput").value;
            connection.invoke("SendMessage", user, message).catch(function (err) {
                return console.error(err.toString());
            });
            event.preventDefault();
        });
    </script>
}

 

呼叫signalr.js那段路徑中有@符號(會被視為Razor保留字),

改用@@就可以了。

 

最後來測試一下。

 

也可以在其他頁面單純作呈現的效果(監控平台、儀表板應用等)

結語

筆者對於SignalR算是初心者Level,

但寫起來還蠻爽的,

這種簡單又好用的東西真的是要推一下!

 

如果介紹內容有誤的麻煩各位指正,

SignalR的介紹就到這邊。

 

參考

https://docs.microsoft.com/zh-tw/aspnet/core/signalr/introduction?view=aspnetcore-2.1

https://docs.microsoft.com/zh-tw/aspnet/core/signalr/hubs?view=aspnetcore-2.1

https://docs.microsoft.com/zh-tw/aspnet/core/tutorials/signalr?view=aspnetcore-2.1&tabs=visual-studio