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

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:

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.

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 hubNameoggetto 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, updatestockpriceo 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));