[SignalR] 利用 ASP.NET SignalR 建立雙向及時通訊

當需要雙向及時通訊,SingalR 則是我的選項之一,它算是非常容易上手的框架。
小朱前輩寫了一些基礎概念的文章,有興趣的可以前往看一下:
https://www.dotblogs.com.tw/regionbbs/Search?q=signalr

開發環境

  • VS 2019
  • .NET Framework 4.8
  • Windows 10
  • SignalR  2.4.1

架構

由下圖得知 Client1 發送一個訊息給 SignalR Hub,SignalR Hub 將訊息推播給所有訂閱的 Client

下圖出自:https://www.pubnub.com/learn/glossary/what-is-signalr/

What is SignalR? | PubNub

伺服器

安裝套件

Install-Package Microsoft.AspNet.SignalR -version 2.4.1

 

實作 Hub

BroadcastHub:Hub Name,用戶端訂閱位置

Clients 的成員幾乎都是 dynamic 型別,由這些方法幫我們建立用戶端溝通

Clients.All:通知所有用戶端。

Clients.Clients(ConnectionIds):通知特定用戶端。

ShowMessage:通知有訂閱 ShowMessage 方法的用戶端,對用戶端而言他是 Event Name。

namespace Server.SignalR
{
    public class BroadcastHub : Hub
    {
        public void Broadcast(string name, string country)
        {
            this.Clients.All.ShowMessage(name, country);
        }
    }
}

 

註冊路由

將 Hub 的 Pipeline 注入到 OWIN

[assembly: OwinStartup(typeof(Startup))]
namespace Server
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

 

取出 Hub

從 OWIN 的 Pipeline 取出 Hub 

var context = GlobalHost.ConnectionManager.GetHubContext<BroadcastHub>();

 

取出 Hub 後,通知有註冊 ShowMessage 方法的用戶端,如下範例:

 

[HttpPost]
[Route("")]
public IHttpActionResult Post(string name, string country, string connectionIds)
{
    var context = GlobalHost.ConnectionManager.GetHubContext<BroadcastHub>();
    if (string.IsNullOrWhiteSpace(connectionIds))
    {
        context.Clients
               .All
               .ShowMessage(name, country);
    }
    else
    {
        //不支援多筆
        context.Clients
               .Clients(new List<string>
               {
                   connectionIds
               })
               .ShowMessage(name, country);
    }
 
    return new ResponseMessageResult(new HttpResponseMessage(HttpStatusCode.Accepted));
}

當,connectionIds 沒有內容的時候推播給所有的訂閱者,反之,推播特定訂閱者;ConnectionId 則是建立 Hub 後,得到的 Id。

 

用戶端

安裝套件

Install-Package Microsoft.AspNet.SignalR.Client -version 2.4.1

訂閱通知

HubConnection:建立連線,傳入服務的位置,當 Hub 建立後可以得到HubConnection.ConnectionId

HubConnection.CreateHubProxy:建立 Hub,傳入Hub Name,也就是伺服器端的 BroadcastHub 類別

IHubProxy.On:訂閱,因為在伺服器端寫了 Clients.All.ShowMessageShowMessage 對用戶端而言叫做 Event Name

public partial class Form1 : Form
{
    private readonly string        _hubName    = "BroadcastHub";
    private readonly string        _signalrUrl = @"https://localhost:44342/";
    private readonly HubConnection _hubConnection;
    private readonly IHubProxy     _hubProxy;
 
    public Form1()
    {
        this.InitializeComponent();
 
        this._hubConnection = new HubConnection(this._signalrUrl);
        this._hubProxy = this._hubConnection.CreateHubProxy(this._hubName);
        this._hubProxy.On("ShowMessage",
                          (string name, string country) =>
                          {
                              this.Messages_TextBox
                                  .InvokeIfNecessary(() =>
                                                     {
                                                         var msg =
                                                             $"Hi, My name is {name}, I come from {country}\r\n";
                                                         this.Messages_TextBox
                                                             .AppendText(msg);
                                                         Console.WriteLine(msg);
                                                     });
                          });
 
        this._hubConnection.Start().Wait();
    }
}

 

發送訊息

除了可以接收訊息之外,也可以發訊息

IHubProxy.Invoke:呼叫遠端方法,也就是伺服器端的 BroadcastHub 類別裡的 Broadcast 方法

public partial class Form1 : Form
{
    private readonly string        _actionName = "Broadcast";
    private async void SendMessageButton_Click(object sender, EventArgs e)
    {
        await this._hubProxy.Invoke(this._actionName,
                                    this.Name_TextBox.Text,
                                    this.Conutry_TextBox.Text);
    }
}

 

範例專案

https://github.com/yaochangyu/sample.dotblog/tree/master/SignalR

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo