【SignalR學習系列】8. SignalR Hubs Api 詳解(.Net C# 客戶端)

創建一個 SignalR 鏈接

var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

 

配置 SignalR 鏈接

在 WPF 客戶端裏設置鏈接的最大值

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
ServicePointManager.DefaultConnectionLimit = 10; await hubConnection.Start();

 

設置 Query String 參數

var querystringData = new Dictionary<string, string>();
querystringData.Add("contosochatversion", "1.0");
var connection = new HubConnection("http://contoso.com/", querystringData);

讀取 query stringapi

public class StockTickerHub : Hub
{
    public override Task OnConnected()
    {
        var version = Context.QueryString["contosochatversion"];
        if (version != "1.0")
        {
            Clients.Caller.notifyWrongVersion();
        }
        return base.OnConnected();
    }
}

 

指定傳輸協議

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start(new LongPollingTransport());

能夠指定如下四種方式緩存

  • LongPollingTransport
  • ServerSentEventsTransport
  • WebSocketTransport (只有在 server and client 都使用 .NET 4.5的狀況下才能使用)
  • AutoTransport(自動選擇)

 

指定 Http Header 

hubConnection = new hubConnection("http://www.contoso.com/");
connection.Headers.Add("headername", "headervalue"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await connection.Start();

 

指定 Client 證書

hubConnection = new hubConnection("http://www.contoso.com/");
hubConnection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer")); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await connection.Start();

 

建立 Hub proxy

服務端服務器

public class StockTickerHub : Hub

客戶端異步

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

若是你的 Hub 類使用了 HubName 特性,那麼就須要使用 HubName 的值來調用。ide

服務端ui

[HubName("stockTicker")]
public class StockTickerHub : Hub

客戶端spa

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("stockTicker");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

若是使用 HubName 屢次調用 HubConnection.CreateHubProxy,那麼會獲得緩存的相同的 IHubProxy 對象。日誌

 

如何定義在 Server 端調用的 Client 方法

無參方法

Server 端code

public class StockTickerHub : Hub
{
    public void NotifyAllClients()
    {
         Clients.All.Notify();
    }
}

客戶端orm

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHub.On("notify", () =>
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += "Notified!\n";
    }, null)
);
await hubConnection.Start();

 

有參指定參數類型

Sever 端

public void BroadcastStockPrice(Stock stock)
{
    context.Clients.Others.UpdateStockPrice(stock);
}

用做參數的 Stock 類

public class Stock
{
    public string Symbol { get; set; } public decimal Price { get; set; } }

客戶端代碼

stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
    }, null)
);

 

有參,指定動態類型

server 端

public void BroadcastStockPrice(Stock stock)
{
    context.Clients.Others.UpdateStockPrice(stock);
}

用做參數的 Stock 類

public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

客戶端代碼

stockTickerHubProxy.On("UpdateStockPrice", stock => 
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
    }, null)
);

 

移除Handler

var updateStockPriceHandler = stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    Context.Post(delegate
    {
        textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
    }, null)
);

updateStockPriceHandler.Dispose();

 

從客戶端調用服務端方法

使用 HubProxy 的 Invoke 方法來調用服務端的方法。

服務端方法沒有返回值

public class StockTickerHub : Hub
{
    public void JoinGroup(string groupName)
    {
        Groups.Add(Context.ConnectionId, groupName); 
    }
}

客戶端調用服務器沒有返回值的方法

stockTickerHubProxy.Invoke("JoinGroup", "SignalRChatRoom");

 

服務端方法有返回值,而且有一個複雜類型的參數

public IEnumerable<Stock> AddStock(Stock stock)
{
    _stockTicker.AddStock(stock);
    return _stockTicker.GetAllStocks();
}

Stock 類

public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

客戶端調用有返回值和複雜類型參數的方法,.Net 4.5 裏使用異步方法

var stocks = await stockTickerHub.Invoke<IEnumerable<Stock>>("AddStock", new Stock() { Symbol = "MSFT" });
foreach (Stock stock in stocks)
{
    textBox.Text += string.Format("Symbol: {0} price: {1}\n", stock.Symbol, stock.Price);
}

 

如何處理鏈接的生命週期事件

SignalR 提供了下述你能夠捕獲的生命週期事件。

  • received: 當任何數據經過鏈接獲取到的時候執行。能夠獲得數據。
  • connectionSlow: 當客戶端檢測到緩慢或者不流暢的鏈接的時候執行。 
  • reconnecting: 當潛在的協議從新開始鏈接的時候執行。 
  • reconnected: 當潛在的協議以及從新創建鏈接的時候執行。
  • stateChanged: 當鏈接的狀態發生改變的時候執行。能夠提供一箇舊的和新的狀態(Connecting, Connected, Reconnecting, 或者 Disconnected)。
  • Closed: 當鏈接中斷之後執行。
hubConnection.ConnectionSlow += () => Console.WriteLine("Connection problems.");

 

捕獲異常

若是你不在服務端明確地打開詳細錯誤信息,那麼SignalR只會列出一些簡單的錯誤信息,你能夠經過下面的代碼開啓詳細錯誤信息記錄。

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true; App.MapSignalR(hubConfiguration);

給 connection 對象添加一個 error 處理事件。

hubConnection.Error += ex => Console.WriteLine("SignalR error: {0}", ex.Message);

用 try - catch 捕獲異常

try
{
    IEnumerable<Stock> stocks = await stockTickerHub.Invoke<IEnumerable<Stock>>("GetAllStocks");
    foreach (Stock stock in stocks)
    {
        Console.WriteLine("Symbol: {0} price: {1}", stock.Symbol, stock.Price);
    }
}
catch (Exception ex)
{
    Console.WriteLine("Error invoking GetAllStocks: {0}", ex.Message);
}

 

開啓客戶端日誌

var hubConnection = new HubConnection("http://www.contoso.com/");
hubConnection.TraceLevel = TraceLevels.All; hubConnection.TraceWriter = Console.Out;
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

 

參考連接:

https://docs.microsoft.com/zh-cn/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-net-client

相關文章
相關標籤/搜索