先介紹一下我的程式碼環境:
Microsoft Visual Studio Community 2019
第一部分先參考微軟官方教程使用建立SignalR網站專案 教程:使用 SignalR 2 進行實時聊天 | Microsoft Learn
這裡說幾個注意事項:參照本部分微軟教程過程中我遇到幾項問題,
在建立ChatHub類的時候,VS會自動安裝幾個類庫,在我的系統環境下,有幾個報錯,具體報錯沒有截圖,主要原因是第三方引用程式包版本不對應,下面是我的packages.config檔案對應版本
1 <?xml version="1.0" encoding="utf-8"?> 2 <packages> 3 <package id="jQuery" version="3.7.1" targetFramework="net462" /> 4 <package id="Microsoft.AspNet.SignalR" version="2.2.2" targetFramework="net462" /> 5 <package id="Microsoft.AspNet.SignalR.Core" version="2.2.2" targetFramework="net462" /> 6 <package id="Microsoft.AspNet.SignalR.Core.zh-Hans" version="2.2.2" targetFramework="net462" /> 7 <package id="Microsoft.AspNet.SignalR.JS" version="2.2.2" targetFramework="net462" /> 8 <package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.2.2" targetFramework="net462" /> 9 <package id="Microsoft.AspNet.SignalR.SystemWeb.zh-Hans" version="2.2.2" targetFramework="net462" /> 10 <package id="Microsoft.AspNet.SignalR.zh-Hans" version="2.2.2" targetFramework="net462" /> 11 <package id="Microsoft.Owin" version="4.2.0" targetFramework="net462" /> 12 <package id="Microsoft.Owin.Host.SystemWeb" version="4.2.0" targetFramework="net462" /> 13 <package id="Microsoft.Owin.Host.SystemWeb.zh-Hans" version="4.2.0" targetFramework="net462" /> 14 <package id="Microsoft.Owin.Security" version="4.2.0" targetFramework="net462" /> 15 <package id="Microsoft.Owin.Security.zh-Hans" version="4.2.0" targetFramework="net462" /> 16 <package id="Microsoft.Owin.zh-Hans" version="4.2.0" targetFramework="net462" /> 17 <package id="Microsoft.Web.Infrastructure" version="2.0.1" targetFramework="net462" /> 18 <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" /> 19 <package id="Owin" version="1.0" targetFramework="net462" /> 20 </packages>
- 在 Visual Studio 中,建立 ASP.NET Web 應用程式。
- 在 “新建 ASP.NET 專案 - SignalRChat ”視窗中,選擇“ 空 ”並選擇“ 確定”。
- 在“解決方案資源管理器”中,右鍵單擊專案並選擇“新增新>項”。
- 在 “新增新項 - SignalRChat”中,選擇“ 已安裝>的 Visual C#>Web>SignalR ”,然後選擇“ SignalR Hub 類 (v2) ”。
- 將類命名為 ChatHub 並將其新增到專案中。
此步驟建立 ChatHub.cs 類檔案,並向專案新增一組支援 SignalR 的指令碼檔案和程式集引用。 - 將新的 ChatHub.cs 類檔案中的程式碼替換為以下程式碼:
using System; using System.Web; using Microsoft.AspNet.SignalR; namespace SignalRChat { public class ChatHub : Hub { public void Send(string name, string message) { // Call the broadcastMessage method to update clients. Clients.All.broadcastMessage(name, message); }
public void Hello(string name,string message)
{
Clients.All.broadcastMessage("Hello:"+name, message);
}}
}
這個是另一類,MyHub.cs類,為下面第二部分程式碼執行提供
public class MyHub : Hub { public void Send(string name, string message) { Clients.All.broadcastMessage("my:"+name, message); } }
- 在“解決方案資源管理器”中,右鍵單擊專案並選擇“新增新>項”。
- 在 “新增新項 - SignalRChat ”中,選擇 “已安裝>的 Visual C#>Web ”,然後選擇“ OWIN 啟動類”。
- 將類命名為 Startup 並將其新增到專案中。
- 將 Startup 類中的預設程式碼替換為以下程式碼:
1 using Microsoft.Owin; 2 using Owin; 3 [assembly: OwinStartup(typeof(SignalRChat.Startup))] 4 namespace SignalRChat 5 { 6 public class Startup 7 { 8 public void Configuration(IAppBuilder app) 9 { 10 // Any connection or hub wire up and configuration should go here 11 app.MapSignalR(); 12 } 13 } 14 }
- 在“解決方案資源管理器”中,右鍵單擊專案並選擇“新增>HTML 頁面”。
- 將新頁 索引 命名為 ,然後選擇“ 確定”。
- 在“解決方案資源管理器”中,右鍵單擊建立的 HTML 頁面,然後選擇“設定為起始頁”。
- 將 HTML 頁中的預設程式碼替換為以下程式碼:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>SignalR Simple Chat</title> 5 <style type="text/css"> 6 .container { 7 background-color: #99CCFF; 8 border: thick solid #808080; 9 padding: 20px; 10 margin: 20px; 11 } 12 </style> 13 </head> 14 <body> 15 <div class="container"> 16 <input type="text" id="message" /> 17 <input type="button" id="sendmessage" value="Send" /> 18 <input type="hidden" id="displayname" /> 19 <ul id="discussion"> 20 </ul> 21 </div> 22 <!--Script references. --> 23 <!--Reference the jQuery library. --> 24 <script src="Scripts/jquery-3.1.1.min.js" ></script> 25 <!--Reference the SignalR library. --> 26 <script src="Scripts/jquery.signalR-2.2.1.min.js"></script> 27 <!--Reference the autogenerated SignalR hub script. --> 28 <script src="signalr/hubs"></script> 29 <!--Add script to update the page and send messages.--> 30 <script type="text/javascript"> 31 $(function () { 32 // Declare a proxy to reference the hub. 33 var chat = $.connection.chatHub; 34 // Create a function that the hub can call to broadcast messages. 35 chat.client.broadcastMessage = function (name, message) { 36 // Html encode display name and message. 37 var encodedName = $('<div />').text(name).html(); 38 var encodedMsg = $('<div />').text(message).html(); 39 // Add the message to the page. 40 $('#discussion').append('<li><strong>' + encodedName 41 + '</strong>: ' + encodedMsg + '</li>'); 42 }; 43 // Get the user name and store it to prepend to messages. 44 $('#displayname').val(prompt('Enter your name:', '')); 45 // Set initial focus to message input box. 46 $('#message').focus(); 47 // Start the connection. 48 $.connection.hub.start().done(function () { 49 $('#sendmessage').click(function () { 50 // Call the Send method on the hub. 51 chat.server.send($('#displayname').val(), $('#message').val()); 52 // Clear text box and reset focus for next comment. 53 $('#message').val('').focus(); 54 }); 55 }); 56 }); 57 </script> 58 </body> 59 </html>
-
檢查程式碼塊中的指令碼引用是否與專案中的指令碼檔案版本相對應。
原始程式碼塊中的指令碼引用:
1 <!--Script references. --> 2 <!--Reference the jQuery library. --> 3 <script src="Scripts/jquery-3.1.1.min.js" ></script> 4 <!--Reference the SignalR library. --> 5 <script src="Scripts/jquery.signalR-2.2.1.min.js"></script>
- 如果不匹配,請更新 .html 檔案。
- 在選單欄中,選擇“全部儲存檔案>”。
執行示例
-
在工具欄中,開啟 “指令碼除錯 ”,然後選擇“播放”按鈕以在除錯模式下執行示例。
-
瀏覽器開啟時,輸入聊天標識的名稱。
-
從瀏覽器複製 URL,開啟其他兩個瀏覽器,然後將 URL 貼上到位址列中。
-
在每個瀏覽器中,輸入唯一的名稱。
-
現在,新增批註並選擇“ 傳送”。 在其他瀏覽器中重複此操作。 批註實時顯示。
備註
此簡單的聊天應用程式不維護伺服器上的討論上下文。 中心向所有當前使用者廣播註釋。 稍後加入聊天的使用者將看到從加入時新增的訊息。
瞭解聊天應用程式如何在三種不同瀏覽器中執行。 當 Tom、Anand 和 Susan 傳送訊息時,所有瀏覽器都會實時更新:
以上是SignalR在web環境下實現簡單的聊天,程式碼基本上都是微軟直接實現的,沒有什麼改動
第二部分WPF透過SignalR通訊
基於上面第一部分專案,我的專案執行地址是:http://localhost:11733
在VS中建立WPF應用(.NET Framework)
我的建立名稱:
修改MainWindow.xaml檔案程式碼如下:
<Window x:Class="SignalRWpf.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SignalRWpf" mc:Ignorable="d" Title="同步聊天" Height="450" Width="800"> <Grid> <TextBox Name="name1" HorizontalAlignment="Left" Height="23" Margin="105,17,0,0" TextWrapping="Wrap" Text="請修改這裡為聊天名" VerticalAlignment="Top" Width="120"/> <TextBox Name="textbox1" HorizontalAlignment="Left" Height="23" Margin="105,53,0,0" TextWrapping="Wrap" Text="傳送輸入內容" VerticalAlignment="Top" Width="120"/> <Button Content="Send" HorizontalAlignment="Left" Margin="245,53,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/> <Button Content="Hello" HorizontalAlignment="Left" Margin="341,53,0,0" VerticalAlignment="Top" Width="75" Click="Button1_Click"/> <Button Content="MySend" HorizontalAlignment="Left" Margin="441,53,0,0" VerticalAlignment="Top" Width="75" Click="My_Click"/> <Label Name="label1" Content="" HorizontalAlignment="Left" Margin="22,103,0,0" VerticalAlignment="Top"/> </Grid> </Window>
修改MainWindow.xaml.cs檔案程式碼如下
1 using Microsoft.AspNet.SignalR.Client; 2 using System.Windows; 3 4 namespace SignalRWpf 5 { 6 /// <summary> 7 /// MainWindow.xaml 的互動邏輯 8 /// </summary> 9 public partial class MainWindow : Window 10 { 11 HubConnection connection; 12 IHubProxy hub; 13 IHubProxy myhub; 14 string url = "http://localhost:11733"; 15 public MainWindow() 16 { 17 InitializeComponent(); 18 connection = new HubConnection(url); 19 //類名必須與服務端一致 20 hub = connection.CreateHubProxy("ChatHub"); 21 hub.On<string, string>("broadcastMessage", Send); 22 23 myhub = connection.CreateHubProxy("MyHub"); 24 myhub.On<string, string>("broadcastMessage", Send); 25 26 connection.Start().Wait(); 27 } 28 29 private void Button_Click(object sender, RoutedEventArgs e) 30 { 31 hub.Invoke("Send", name1.Text, textbox1.Text); 32 textbox1.Text = ""; 33 } 34 private void Send(string name,string message) 35 { 36 37 // 將結果賦值給UI 38 Dispatcher.Invoke(() => 39 { 40 this.label1.Content += "\n"+name + " " + message; 41 }); 42 } 43 private void My_Click(object sender, RoutedEventArgs e) 44 { 45 myhub.Invoke("Send", name1.Text, textbox1.Text); 46 textbox1.Text = ""; 47 } 48 private void Button1_Click(object sender, RoutedEventArgs e) 49 { 50 hub.Invoke("Hello", name1.Text, textbox1.Text); 51 textbox1.Text = ""; 52 } 53 } 54 }
下面是最終效果展示