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:

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.

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