[ASP.NET Core][SignalR] 即時對話聊天室教學 #CH1
SignalR 是 ASP.NET 實現網頁雙向溝通的一種方式,傳統的網頁是單向溝通,只能由客戶端主動發送訊息至伺服器端,而雙向溝通就可以由伺服器端主動發送訊息至客戶端,可以解決網頁即時同步的問題。
SignalR 應用的場景非常多,舉凡需要即時同步的場合都適用,例如遊戲、股價、聊天室、投票、拍賣、監控等等,如果學會此技能,就可在網頁上做出更豐富的變化。
SignalR 提供網頁雙向傳輸協定 WebSocket 的簡化方式,讓開發者可以快速完成雙向溝通網頁。
這篇文章將會教學基礎 SignalR 使用方式,範例環境是 ASP.NET Core 6.0 ,在網頁上製作聊天對話的功能。
Contents
建立專案
開啟 Visual Studio,在新增專案範本時,要選擇「ASP.NET Core Web 應用程式」或是「ASP.NET Core Web 應用程式 (Model-View-Controller)」都是可以的,而我通常是選擇有 MVC 的專案範本
輸入專案名稱、路徑。
架構選擇「.NET 6.0」版本,按下「建立」就會建立此專案。
新增 SignalR 用戶端程式庫
SignalR 前端需要 JavaScript 的類別庫才能運作,而後端的 SignalR 已包含在 ASP.NET Core 共用架構中。
這裡要先下載最新版的 signalr.js 到我們的專案內。
在「方案總管」中,以滑鼠右鍵按一下專案,然後選取「加入 > 用戶端程式庫」。
針對提供者選取「unpkg」
針對「程式庫」輸入「@microsoft/signalr@latest」
選取「選擇特定檔案」,展開「dist/browser」資料夾,然後勾選「browser」。
將「目標位置」設定為「wwwroot/js/signalr/」
安裝之後,在你的專案目錄下就會找到這些檔案。
建立 SignalR Hub 類別
SignalR 的 Hub 類別可以處理網頁上用戶端與伺服器端之間的溝通橋樑。
在專案的目錄中新增目錄,名稱為「Hubs」。
然後在「Hubs」目錄下新增新類別,名稱為「ChatHub」。
然後在 ChatHub 類別貼上以下程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
using Microsoft.AspNetCore.SignalR; using Newtonsoft.Json; namespace CoreMVC_SignalR_Chat.Hubs { public class ChatHub : Hub { // 用戶連線 ID 列表 public static List<string> ConnIDList = new List<string>(); /// <summary> /// 連線事件 /// </summary> /// <returns></returns> public override async Task OnConnectedAsync() { if (ConnIDList.Where(p => p == Context.ConnectionId).FirstOrDefault() == null) { ConnIDList.Add(Context.ConnectionId); } // 更新連線 ID 列表 string jsonString = JsonConvert.SerializeObject(ConnIDList); await Clients.All.SendAsync("UpdList", jsonString); // 更新個人 ID await Clients.Client(Context.ConnectionId).SendAsync("UpdSelfID", Context.ConnectionId); // 更新聊天內容 await Clients.All.SendAsync("UpdContent", "新連線 ID: " + Context.ConnectionId); await base.OnConnectedAsync(); } /// <summary> /// 離線事件 /// </summary> /// <param name="ex"></param> /// <returns></returns> public override async Task OnDisconnectedAsync(Exception ex) { string id = ConnIDList.Where(p => p == Context.ConnectionId).FirstOrDefault(); if (id != null) { ConnIDList.Remove(id); } // 更新連線 ID 列表 string jsonString = JsonConvert.SerializeObject(ConnIDList); await Clients.All.SendAsync("UpdList", jsonString); // 更新聊天內容 await Clients.All.SendAsync("UpdContent", "已離線 ID: " + Context.ConnectionId); await base.OnDisconnectedAsync(ex); } /// <summary> /// 傳遞訊息 /// </summary> /// <param name="user"></param> /// <param name="message"></param> /// <param name="id"></param> /// <returns></returns> public async Task SendMessage(string selfID, string message, string sendToID) { if (string.IsNullOrEmpty(sendToID)) { await Clients.All.SendAsync("UpdContent", selfID + " 說: " + message); } else { // 接收人 await Clients.Client(sendToID).SendAsync("UpdContent", selfID + " 私訊向你說: " + message); // 發送人 await Clients.Client(Context.ConnectionId).SendAsync("UpdContent", "你向 " + sendToID + " 私訊說: " + message); } } } } |
方法 OnConnectedAsync()
是每一個用戶連線後,都會觸發的事件,在這事件裡面可以更新用戶列表。
而方法 OnDisconnectedAsync()
則是每一個用戶離線會觸發的事件。
設定 SignalR
開啟 Program.cs 檔案,這裡要啟用 SignalR 服務,然後註冊 Hub 路由。
在 Program.cs 的 var app = builder.Build();
語法之前,加入此語法:
//加入 SignalR
builder.Services.AddSignalR();
在 app.Run();
語法之前,加入此語法:
//加入 Hub
app.MapHub<ChatHub>("/chatHub");
SignalR 用戶端程式碼
接著就要編寫前端的程式碼,我們範例就直接寫在首頁上教學。
開啟 \Views\Home\Index.cshtml 檔案,可以清除原有全部程式碼,然後貼上以下語法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
<h1>即時聊天範例</h1> <div class="row"> <div class="col-8"> <h4>個人 ID: <span id="SelfID"></span></h4> <div class="mb-3"> <label for="message" class="form-label">發送訊息</label> <input type="text" class="form-control" id="message"> </div> <div class="mb-3"> <label for="sendToID" class="form-label">指定 ID</label> <input type="text" class="form-control" id="sendToID"> </div> <button type="button" class="btn btn-primary" id="sendButton">傳送訊息</button> </div> <div class="col-4"> <h4>連線 ID 列表</h4> <ul class="list-group" id="IDList"> </ul> </div> </div> <div class="row mt-3"> <div class="col-12"> <h3>聊天內容</h3> <ul class="list-group" id="Content"> </ul> </div> </div> @section scripts{ <script src="~/js/signalr/dist/browser/signalr.js"></script> <script> var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build(); //與Server建立連線 connection.start().then(function () { console.log("Hub 連線完成"); }).catch(function (err) { alert('連線錯誤: ' + err.toString()); }); // 更新連線 ID 列表事件 connection.on("UpdList", function (jsonList) { var list = JSON.parse(jsonList); $("#IDList li").remove(); for(i=0; i<list.length; i++) { $("#IDList").append($("<li></li>").attr("class", "list-group-item").text(list[i])); } }); // 更新用戶個人連線 ID 事件 connection.on("UpdSelfID", function (id) { $('#SelfID').html(id); }); // 更新聊天內容事件 connection.on("UpdContent", function (msg) { $("#Content").append($("<li></li>").attr("class", "list-group-item").text(msg)); }); //傳送訊息 $('#sendButton').on('click', function() { let selfID = $('#SelfID').html(); let message = $('#message').val(); let sendToID = $('#sendToID').val(); connection.invoke("SendMessage", selfID, message, sendToID).catch(function (err) { alert('傳送錯誤: ' + err.toString()); }); }); </script> } |
這裡簡單製作了聊天室的畫面,每一位連線到 SignalR 的用戶,都會得到一組 ID,我們範例就將此 ID 做為用戶名稱,在實務專案時,可以將此 ID 隱藏在背後傳遞。
測試專案
做到這裡就可以按 F5 測試一下專案,初次進入聊天室,我們將用戶 ID 顯示在畫面上。
當有第二個用戶進入時,會同步更新連線 ID 列表。
在傳送訊息時,未輸入指定 ID 時為所有人都收到,當輸入指定 ID 時,則為私人訊息。
你也可以試試看,學會 SignalR 就可以讓網頁互動性更豐富,這是一個簡單基本的 SignalR 即時聊天室教學,分享給你。
範例下載
下一篇教學文章
相關學習文章
- [ASP.NET Core MVC + Vue3] 統一欄位格式定義及驗證設計範例 – 後端驗證 #CH1
- [ASP.NET Core MVC + Vue3 + Dapper] 前後台網站公告範例 – 後台查詢頁面教學 #CH1
- [ASP.NET MVC] 使用 AOP 驗證系統功能執行權限
如果你在學習上有不懂的地方,需要諮詢服務,可以參考站長服務,我想辨法解決你的問題
如果文章內容有過時、不適用或錯誤的地方,幫我在下方留言通知我一下,謝謝
請問ID是怎麼產生的?如過要多個1對1聊天室是會建立多個連線?~
ID 是 SignalR 自動產生的隨機號喔