ASP.NET Guida api di Hub SignalR - Client .NET (SignalR 1.x)
di Patrick Fletcher, Tom Dykstra
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 SignalR Hubs consente di effettuare chiamate di procedura remota da un server ai client connessi e dai 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 i metodi che possono essere chiamati dal server e si chiamano i metodi eseguiti nel server. SignalR si occupa automaticamente di tutte le operazioni di idraulica da client a server.
SignalR offre anche un'API di livello inferiore denominata Connessioni persistenti. Per un'introduzione a SignalR, Hub e Connessioni permanenti o per un'esercitazione che illustra come compilare un'applicazione SignalR completa, vedere SignalR - Introduzione.
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 console WinRT, Silverlight).
- 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 il server o i client JavaScript, vedere le risorse seguenti:
I collegamenti agli argomenti di riferimento sulle 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 i client WinRT, Silverlight, WPF, console e Windows Phone per .NET 4 e .NET 4.5.
Se la versione di SignalR presente nel client è diversa dalla versione presente nel server, SignalR è spesso in grado di adattarsi alla differenza. Ad esempio, quando Viene rilasciata la versione 2.0 di SignalR e la si installa nel server, il server supporterà i client in cui è installata la versione 1.1.x e i client in cui è installata la versione 2.0. Se la differenza tra la versione nel server e la versione nel client è troppo grande, SignalR genera un'eccezione InvalidOperationException
quando il client tenta di stabilire una 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 HubConnection
oggetto e creare un proxy. Per stabilire la connessione, chiamare il Start
metodo sull'oggetto HubConnection
.
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. Questa operazione non è necessaria per i client .NET. Per i client JavaScript, il codice proxy generato crea automaticamente proxy per tutti gli hub presenti nel server e la registrazione di un gestore indica quali hub il client intende usare. 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 predefinito "/signalr" 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 di codice successive 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();
La classe HubConnection
è thread-safe.
Connessioni tra domini da client Silverlight
Per informazioni su come abilitare le connessioni tra domini dai client Silverlight, vedere Rendere disponibile un servizio attraverso i limiti del dominio.
Come configurare la connessione
Prima di stabilire una connessione, è possibile specificare una delle opzioni seguenti:
- Limite di connessioni simultanee.
- Parametri della 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.
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 della stringa di query all'oggetto connessione. Nell'esempio seguente viene illustrato come impostare un parametro della 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 della 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 negozia normalmente con il server per determinare il trasporto migliore supportato sia dal server che dal client. Se si conosce già il trasporto che si desidera utilizzare, è 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.
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 sia il server che il client usano .NET 4.5).
- AutoTransport (sceglie automaticamente il trasporto migliore supportato sia dal client che dal server. Si tratta del trasporto predefinito. Il passaggio di 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 Introduction to SignalR - Transports and Fallbacks .For more information about transports and fallbacks, see Introduction to SignalR - Transports and Fallbacks.
Come specificare le intestazioni HTTP
Per impostare le intestazioni HTTP, utilizzare la Headers
proprietà sull'oggetto 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, utilizzare il AddClientCertificate
metodo sull'oggetto connessione.
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 sul client che un hub può chiamare dal server e per 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 ne è stato usato uno nel server. La corrispondenza dei nomi non prevede alcuna distinzione tra maiuscole e minuscole.
Classe Hub nel server
public class StockTickerHub : Hub
Creare un proxy client per la classe 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();
Se si decora la classe Hub con un HubName
attributo , usare tale nome.
Classe Hub nel server
[HubName("stockTicker")]
public class StockTickerHub : Hub
Creare un proxy client per la classe Hub
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();
L'oggetto proxy è thread-safe. Infatti, se si chiama HubConnection.CreateHubProxy
più volte con lo stesso hubName
, si ottiene lo stesso oggetto memorizzato nella IHubProxy
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 non fa 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 relativi ai 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 gestito non dispone di parametri, usare l'overload non generico del On
metodo :
Codice server che chiama il metodo client 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 di WPF e Silverlight più avanti in questo argomento)
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 parametro
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 .
Codice del server che chiama il metodo client con un parametro
public void BroadcastStockPrice(Stock stock)
{
context.Clients.Others.UpdateStockPrice(stock);
}
Classe Stock utilizzata 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 di 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 alla specifica dei parametri come tipi generici del On
metodo, è possibile specificare parametri come oggetti dinamici:
Codice del server che chiama il metodo client con un parametro
public void BroadcastStockPrice(Stock stock)
{
context.Clients.Others.UpdateStockPrice(stock);
}
Classe Stock utilizzata 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 di 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 relativo Dispose
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, utilizzare 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", hubConnection.ConnectionID, "SignalRChatRoom");
Se il metodo server ha un valore restituito, specificare il tipo restituito come tipo generico del Invoke
metodo.
Codice server per un metodo che ha un valore restituito e accetta un parametro di tipo complesso
public IEnumerable<Stock> AddStock(Stock stock)
{
_stockTicker.AddStock(stock);
return _stockTicker.GetAllStocks();
}
Classe Stock utilizzata 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 con 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 che ha 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 viene eseguito 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 la riconnessione.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 è stata 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 rilascio frequente della connessione, gestire l'evento ConnectionSlow
.
hubConnection.ConnectionSlow += () => Console.WriteLine("Connection problems.");
Per altre informazioni, vedere Understanding and Handling Connection Lifetime Events in SignalR.For more information, see Understanding and Handling Connection Lifetime Events in SignalR.
Come gestire gli errori
Se non si abilitano in modo esplicito 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 newContosoChatMessage
non riesce, il messaggio di errore nell'oggetto errore contiene "There was an error invoking Hub method 'contosoChatHub.newContosoChatMessage'.
" L'invio di messaggi di errore dettagliati ai client nell'ambiente di produzione non è consigliato per motivi di sicurezza, ma se si desidera abilitare messaggi di errore dettagliati a scopo di risoluzione dei problemi, usare il codice seguente nel server.
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
RouteTable.Routes.MapHubs(hubConfiguration);
Per gestire gli errori generati da SignalR, è possibile aggiungere un gestore per l'evento Error
nell'oggetto 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
sull'oggetto connessione.
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 la definizione dei metodi client che il server può chiamare si applicano ai client WinRT. Gli esempi seguenti illustrano 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 parametro
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));