Guida api ASP.NET Hub SignalR - Client .NET (C#)
Avviso
Questa documentazione non è per la versione più recente di SignalR. Esaminare ASP.NET Core SignalR.
Questo documento fornisce un'introduzione all'uso dell'API Hubs per SignalR versione 2 nei client .NET, ad esempio Windows Store (WinRT), WPF, Silverlight e applicazioni console.
L'API Hub SignalR consente di effettuare chiamate di routine remote da un server a client connessi e da client al server. Nel codice del server si definiscono i metodi che possono essere chiamati dai client e si chiamano i metodi eseguiti nel client. Nel codice client si definiscono metodi che possono essere chiamati dal server e si chiamano i metodi eseguiti nel server. SignalR si occupa di tutti gli impianti idraulici da client a server.
SignalR offre anche un'API di livello inferiore denominata Connessioni persistenti. Per un'introduzione a SignalR, Hub e Connessioni persistenti o per un'esercitazione che illustra come creare un'applicazione SignalR completa, vedere SignalR - Introduzione.
Versioni software usate in questo argomento
- Visual Studio 2017
- .NET 4.5
- SignalR versione 2
Versioni precedenti di questo argomento
Per informazioni sulle versioni precedenti di SignalR, vedere Versioni precedenti di SignalR.
Domande e commenti
Lasciare commenti e suggerimenti su come è piaciuta questa esercitazione e ciò che è possibile migliorare nei commenti nella parte inferiore della pagina. Se si hanno domande che non sono direttamente correlate all'esercitazione, è possibile pubblicarli nel forum ASP.NET SignalR o StackOverflow.com.
Panoramica
Questo documento contiene le seguenti sezioni:
Per un esempio di progetti client .NET, vedere le risorse seguenti:
- gustavo-armenta /SignalR-Samples in GitHub.com (esempi di app winRT, Silverlight, app console).
- DamianEdwards/SignalR-MoveShapeDemo/MoveShape.Desktop in GitHub.com (esempio WPF).
- SignalR/ Microsoft.AspNet.SignalR.Client.Samples in GitHub.com (esempio di app console).
Per la documentazione su come programmare i client server o JavaScript, vedere le risorse seguenti:
I collegamenti agli argomenti di riferimento per le API sono alla versione .NET 4.5 dell'API. Se si usa .NET 4, vedere la versione .NET 4 degli argomenti dell'API.
Configurazione client
Installare il pacchetto NuGet Microsoft.AspNet.SignalR.Client (non il pacchetto Microsoft.AspNet.SignalR ). Questo pacchetto supporta client WinRT, Silverlight, WPF, applicazione console e Windows Phone per .NET 4 e .NET 4.5.
Se la versione di SignalR disponibile nel client è diversa dalla versione disponibile nel server, SignalR è spesso in grado di adattarsi alla differenza. Ad esempio, un server che esegue SignalR versione 2 supporta i client che hanno installato 1.1.x e client che hanno installato la versione 2. Se la differenza tra la versione nel server e la versione del client è troppo grande o se il client è più recente del server, SignalR genera un'eccezione quando il client tenta di stabilire una InvalidOperationException
connessione. Il messaggio di errore è "You are using a version of the client that isn't compatible with the server. Client version X.X, server version X.X
".
Come stabilire una connessione
Prima di poter stabilire una connessione, è necessario creare un oggetto e creare un HubConnection
proxy. Per stabilire la connessione, chiamare il Start
metodo sull'oggetto HubConnection
.
using (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();
}
Nota
Per i client JavaScript è necessario registrare almeno un gestore eventi prima di chiamare il Start
metodo per stabilire la connessione. Non è necessario per i client .NET. Per i client JavaScript, il codice proxy generato crea automaticamente proxy per tutti gli hub esistenti nel server e la registrazione di un gestore è come indicare quali hub intende usare il client. Tuttavia, per un client .NET si creano manualmente proxy hub, quindi SignalR presuppone che si usi qualsiasi hub per cui si crea un proxy.
Il codice di esempio usa l'URL "/signalr" predefinito per connettersi al servizio SignalR. Per informazioni su come specificare un URL di base diverso, vedere ASP.NET Guida api hub SignalR - Server - URL /signalr.
Il Start
metodo viene eseguito in modo asincrono. Per assicurarsi che le righe successive di codice non vengano eseguite finché non viene stabilita la connessione, usare await
in un metodo asincrono ASP.NET 4.5 o .Wait()
in un metodo sincrono. Non usare .Wait()
in un client WinRT.
await connection.Start();
connection.Start().Wait();
Connessioni tra domini dai client Silverlight
Per informazioni su come abilitare le connessioni tra domini dai client Silverlight, vedere Rendere disponibile un servizio tra limiti di dominio.
Come configurare la connessione
Prima di stabilire una connessione, è possibile specificare una delle opzioni seguenti:
- Limite di connessioni simultanee.
- Parametri stringa di query.
- Metodo di trasporto.
- Intestazioni HTTP.
- Certificati client.
Come impostare il numero massimo di connessioni simultanee nei client WPF
Nei client WPF potrebbe essere necessario aumentare il numero massimo di connessioni simultanee dal valore predefinito 2. Il valore consigliato è 10.
using (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();
}
Per altre informazioni, vedere ServicePointManager.DefaultConnectionLimit.
Come specificare i parametri della stringa di query
Se si desidera inviare dati al server quando il client si connette, è possibile aggiungere parametri stringa di query all'oggetto di connessione. Nell'esempio seguente viene illustrato come impostare un parametro stringa di query nel codice client.
var querystringData = new Dictionary<string, string>();
querystringData.Add("contosochatversion", "1.0");
var connection = new HubConnection("http://contoso.com/", querystringData);
Nell'esempio seguente viene illustrato come leggere un parametro stringa di query nel codice del server.
public class StockTickerHub : Hub
{
public override Task OnConnected()
{
var version = Context.QueryString["contosochatversion"];
if (version != "1.0")
{
Clients.Caller.notifyWrongVersion();
}
return base.OnConnected();
}
}
Come specificare il metodo di trasporto
Come parte del processo di connessione, un client SignalR normalmente negozia con il server per determinare il trasporto migliore supportato da server e client. Se si conosce già quale trasporto si vuole usare, è possibile ignorare questo processo di negoziazione. Per specificare il metodo di trasporto, passare un oggetto trasporto al metodo Start. Nell'esempio seguente viene illustrato come specificare il metodo di trasporto nel codice client.
using (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());
}
Lo spazio dei nomi Microsoft.AspNet.SignalR.Client.Transports include le classi seguenti che è possibile usare per specificare il trasporto.
- LongPollingTransport
- ServerSentEventsTransport
- WebSocketTransport (disponibile solo quando entrambi i server e i client usano .NET 4.5).
- AutoTransport (sceglie automaticamente il trasporto migliore supportato sia dal client che dal server. Si tratta del trasporto predefinito. Passando questo elemento al
Start
metodo ha lo stesso effetto di non passare nulla.
Il trasporto ForeverFrame non è incluso in questo elenco perché viene usato solo dai browser.
Per informazioni su come controllare il metodo di trasporto nel codice del server, vedere ASP.NET Guida API hub SignalR - Server - Come ottenere informazioni sul client dalla proprietà Context. Per altre informazioni sui trasporti e sui fallback, vedere Introduzione a SignalR - Trasporti e fallback.
Come specificare le intestazioni HTTP
Per impostare le intestazioni HTTP, usare la Headers
proprietà nell'oggetto di connessione. Nell'esempio seguente viene illustrato come aggiungere un'intestazione HTTP.
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();
Come specificare i certificati client
Per aggiungere certificati client, usare il AddClientCertificate
metodo nell'oggetto connection.
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();
Come creare il proxy hub
Per definire i metodi nel client che un hub può chiamare dal server e richiamare i metodi in un hub nel server, creare un proxy per l'hub chiamando CreateHubProxy
sull'oggetto connessione. La stringa passata a CreateHubProxy
è il nome della classe Hub o il nome specificato dall'attributo HubName
se è stato usato nel server. La corrispondenza dei nomi non prevede alcuna distinzione tra maiuscole e minuscole.
Classe hub nel server
public class StockTickerHub : Hub
Creare il proxy client per la classe Hub
using (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();
}
Se si decorare la classe Hub con un HubName
attributo, usare tale nome.
Classe hub nel server
[HubName("stockTicker")]
public class StockTickerHub : Hub
Creare il proxy client per la classe Hub
using (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();
}
Se si chiama HubConnection.CreateHubProxy
più volte con lo stesso oggetto , si ottiene lo stesso hubName
oggetto memorizzato IHubProxy
nella cache.
Come definire i metodi nel client che il server può chiamare
Per definire un metodo che il server può chiamare, usare il metodo del On
proxy per registrare un gestore eventi.
La corrispondenza dei nomi dei metodi è senza distinzione tra maiuscole e minuscole. Ad esempio, Clients.All.UpdateStockPrice
nel server verrà eseguito updateStockPrice
, updatestockprice
o UpdateStockPrice
nel client.
Diverse piattaforme client hanno requisiti diversi per la scrittura del codice del metodo per aggiornare l'interfaccia utente. Gli esempi illustrati sono per i client WinRT (Windows Store .NET). Gli esempi di applicazioni WPF, Silverlight e console vengono forniti in una sezione separata più avanti in questo argomento.
Metodi senza parametri
Se il metodo che si sta gestendo non dispone di parametri, usare l'overload non generico del On
metodo:
Metodo client di chiamata del codice server senza parametri
public class StockTickerHub : Hub
{
public void NotifyAllClients()
{
Clients.All.Notify();
}
}
Codice client WinRT per il metodo chiamato dal server senza parametri (vedere esempi WPF e Silverlight più avanti in questo argomento)
using (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();
}
Metodi con parametri, specificando i tipi di parametri
Se il metodo gestito include parametri, specificare i tipi dei parametri come tipi generici del On
metodo. Esistono overload generici del On
metodo per consentire di specificare fino a 8 parametri (4 su Windows Phone 7). Nell'esempio seguente viene inviato un parametro al UpdateStockPrice
metodo.
Metodo client di chiamata del codice server con un parametro
public void BroadcastStockPrice(Stock stock)
{
context.Clients.Others.UpdateStockPrice(stock);
}
Classe Stock usata per il parametro
public class Stock
{
public string Symbol { get; set; }
public decimal Price { get; set; }
}
Codice client WinRT per un metodo chiamato dal server con un parametro (vedere esempi WPF e Silverlight più avanti in questo argomento)
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)
);
Metodi con parametri, specificando oggetti dinamici per i parametri
In alternativa, specificare parametri come tipi generici del On
metodo, è possibile specificare parametri come oggetti dinamici:
Metodo client di chiamata del codice server con un parametro
public void BroadcastStockPrice(Stock stock)
{
context.Clients.Others.UpdateStockPrice(stock);
}
Classe Stock usata per il parametro
public class Stock
{
public string Symbol { get; set; }
public decimal Price { get; set; }
}
Codice client WinRT per un metodo chiamato dal server con un parametro, usando un oggetto dinamico per il parametro (vedere esempi WPF e Silverlight più avanti in questo argomento)
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)
);
Come rimuovere un gestore
Per rimuovere un gestore, chiamare il Dispose
relativo metodo.
Codice client per un metodo chiamato dal server
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)
);
Codice client per rimuovere il gestore
updateStockPriceHandler.Dispose();
Come chiamare i metodi del server dal client
Per chiamare un metodo nel server, usare il Invoke
metodo nel proxy hub.
Se il metodo server non ha alcun valore restituito, usare l'overload non generico del Invoke
metodo.
Codice server per un metodo senza valore restituito
public class StockTickerHub : Hub
{
public void JoinGroup(string groupName)
{
Groups.Add(Context.ConnectionId, groupName);
}
}
Codice client che chiama un metodo senza valore restituito
stockTickerHubProxy.Invoke("JoinGroup", "SignalRChatRoom");
Se il metodo server ha un valore restituito, specificare il tipo restituito come tipo generico del Invoke
metodo.
Codice server per un metodo con un valore restituito e accetta un parametro di tipo complesso
public IEnumerable<Stock> AddStock(Stock stock)
{
_stockTicker.AddStock(stock);
return _stockTicker.GetAllStocks();
}
Classe Stock usata per il parametro e il valore restituito
public class Stock
{
public string Symbol { get; set; }
public decimal Price { get; set; }
}
Codice client che chiama un metodo che ha un valore restituito e accetta un parametro di tipo complesso, in un metodo asincrono ASP.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);
}
Codice client che chiama un metodo con un valore restituito e accetta un parametro di tipo complesso, in un metodo sincrono
var stocks = stockTickerHub.Invoke<IEnumerable<Stock>>("AddStock", new Stock() { Symbol = "MSFT" }).Result;
foreach (Stock stock in stocks)
{
textBox.Text += string.Format("Symbol: {0} price: {1}\n", stock.Symbol, stock.Price);
}
Il Invoke
metodo esegue in modo asincrono e restituisce un Task
oggetto. Se non si specifica await
o .Wait()
, la riga di codice successiva verrà eseguita prima del completamento dell'esecuzione del metodo richiamato.
Come gestire gli eventi di durata della connessione
SignalR fornisce gli eventi di durata della connessione seguenti che è possibile gestire:
Received
: generato quando vengono ricevuti dati sulla connessione. Fornisce i dati ricevuti.ConnectionSlow
: generato quando il client rileva una connessione lenta o frequente.Reconnecting
: generato quando il trasporto sottostante inizia a riconnettersi.Reconnected
: generato quando il trasporto sottostante è stato riconnesso.StateChanged
: generato quando lo stato della connessione cambia. Fornisce lo stato precedente e il nuovo stato. Per informazioni sui valori dello stato della connessione, vedere Enumerazione ConnectionState.Closed
: generato quando la connessione è disconnessa.
Ad esempio, se si desidera visualizzare messaggi di avviso per gli errori che non sono irreversibili, ma causano problemi di connessione intermittenti, ad esempio lentezza o frequente eliminazione della connessione, gestire l'evento ConnectionSlow
.
hubConnection.ConnectionSlow += () => Console.WriteLine("Connection problems.");
Per altre informazioni, vedere Informazioni e gestione degli eventi di durata della connessione in SignalR.
Come gestire gli errori
Se non si abilitano in modo esplicito i messaggi di errore dettagliati nel server, l'oggetto eccezione restituito da SignalR dopo un errore contiene informazioni minime sull'errore. Ad esempio, se una chiamata a ha esito negativo, il messaggio di errore nell'oggetto errore contiene "There was an error invoking Hub method 'contosoChatHub.newContosoChatMessage'.
" Invio di messaggi di errore dettagliati ai newContosoChatMessage
client nell'ambiente di produzione non è consigliato per motivi di sicurezza, ma se si desidera abilitare messaggi di errore dettagliati per scopi di risoluzione dei problemi, usare il codice seguente nel server.
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
App.MapSignalR(hubConfiguration);
Per gestire gli errori generati da SignalR, è possibile aggiungere un gestore per l'evento nell'oggetto Error
di connessione.
hubConnection.Error += ex => Console.WriteLine("SignalR error: {0}", ex.Message);
Per gestire gli errori dalle chiamate al metodo, eseguire il wrapping del codice in un blocco 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);
}
Come abilitare la registrazione lato client
Per abilitare la registrazione lato client, impostare le TraceLevel
proprietà e TraceWriter
nell'oggetto di connessione.
using (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();
}
Esempi di codice dell'applicazione WPF, Silverlight e console per i metodi client che il server può chiamare
Gli esempi di codice illustrati in precedenza per definire i metodi client che il server può chiamare si applicano ai client WinRT. Gli esempi seguenti mostrano il codice equivalente per i client dell'applicazione WPF, Silverlight e console.
Metodi senza parametri
Codice client WPF per il metodo chiamato dal server senza parametri
stockTickerHub.On<Stock>("notify", () =>
Dispatcher.InvokeAsync(() =>
{
SignalRTextBlock.Text += string.Format("Notified!");
})
);
Codice client Silverlight per il metodo chiamato dal server senza parametri
stockTickerHub.On<Stock>("notify", () =>
// Context is a reference to SynchronizationContext.Current
Context.Post(delegate
{
textBox.Text += "Notified!";
}, null)
);
Codice client dell'applicazione console per il metodo chiamato dal server senza parametri
stockTickerHubProxyProxy.On("Notify", () => Console.WriteLine("Notified!"));
Metodi con parametri, specificando i tipi di parametri
Codice client WPF per un metodo chiamato dal server con un parametro
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock =>
Dispatcher.InvokeAsync(() =>
{
textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
})
);
Codice client Silverlight per un metodo chiamato dal server con un parametro
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)
);
Codice client dell'applicazione console per un metodo chiamato dal server con un parametro
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock =>
Console.WriteLine("Symbol {0} Price {1}", stock.Symbol, stock.Price));
Metodi con parametri, specificando oggetti dinamici per i parametri
Codice client WPF per un metodo chiamato dal server con un parametro, usando un oggetto dinamico per il parametro
stockTickerHubProxy.On("UpdateStockPrice", stock =>
Dispatcher.InvokeAsync(() =>
{
textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
})
);
Codice client Silverlight per un metodo chiamato dal server con un parametro, usando un oggetto dinamico per il parametro
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)
);
Codice client dell'applicazione console per un metodo chiamato dal server con un parametro, usando un oggetto dinamico per il parametro
stockTickerHubProxy.On("UpdateStockPrice", stock =>
Console.WriteLine("Symbol {0} Price {1}", stock.Symbol, stock.Price));