Guia de API dos Hubs do ASP.NET SignalR – Cliente .NET (C#)
Aviso
Esta documentação não é para a versão mais recente do SignalR. Dê uma olhada em ASP.NET Core SignalR.
Este documento fornece uma introdução ao uso da API de Hubs para SignalR versão 2 em clientes .NET, como aplicativos da Windows Store (WinRT), WPF, Silverlight e console.
A API dos Hubs signalr permite que você faça RPCs (chamadas de procedimento remoto) de um servidor para clientes conectados e de clientes para o servidor. No código do servidor, você define métodos que podem ser chamados por clientes e chama métodos executados no cliente. No código do cliente, você define métodos que podem ser chamados do servidor e chama métodos executados no servidor. O SignalR cuida de todo o encanamento cliente-servidor para você.
O SignalR também oferece uma API de nível inferior chamada Conexões Persistentes. Para obter uma introdução ao SignalR, hubs e conexões persistentes ou para um tutorial que mostra como criar um aplicativo SignalR completo, consulte SignalR - Introdução.
Versões de software usadas neste tópico
- Visual Studio 2017
- .NET 4.5
- SignalR versão 2
Versões anteriores deste tópico
Para obter informações sobre versões anteriores do SignalR, consulte Versões mais antigas do SignalR.
Perguntas e comentários
Deixe comentários sobre como você gostou deste tutorial e o que poderíamos melhorar nos comentários na parte inferior da página. Se você tiver perguntas que não estão diretamente relacionadas ao tutorial, poderá postá-las no fórum do ASP.NET SignalR ou StackOverflow.com.
Visão geral
Este documento contém as seguintes seções:
Para obter um exemplo de projetos de cliente .NET, consulte os seguintes recursos:
- gustavo-armenta / SignalR-Samples no GitHub.com (WinRT, Silverlight, exemplos de aplicativo de console).
- DamianEdwards / SignalR-MoveShapeDemo / MoveShape.Desktop no GitHub.com (exemplo do WPF).
- SignalR / Microsoft.AspNet.SignalR.Client.Samples no GitHub.com (exemplo de aplicativo de console).
Para obter a documentação sobre como programar o servidor ou clientes JavaScript, consulte os seguintes recursos:
Os links para tópicos de Referência de API são para a versão do .NET 4.5 da API. Se você estiver usando o .NET 4, consulte a versão do .NET 4 dos tópicos da API.
Configuração do cliente
Instale o pacote NuGet Microsoft.AspNet.SignalR.Client (não o pacote Microsoft.AspNet.SignalR ). Esse pacote dá suporte a clientes WinRT, Silverlight, WPF, console e Windows Phone para .NET 4 e .NET 4.5.
Se a versão do SignalR que você tem no cliente for diferente da versão que você tem no servidor, o SignalR geralmente poderá se adaptar à diferença. Por exemplo, um servidor que executa o SignalR versão 2 dará suporte a clientes que têm o 1.1.x instalado, bem como clientes que têm a versão 2 instalada. Se a diferença entre a versão no servidor e a versão no cliente for muito grande ou se o cliente for mais recente que o servidor, o SignalR gerará uma exceção InvalidOperationException
quando o cliente tentar estabelecer uma conexão. A mensagem de erro é "You are using a version of the client that isn't compatible with the server. Client version X.X, server version X.X
".
Como estabelecer uma conexão
Antes de estabelecer uma conexão, você precisa criar um HubConnection
objeto e criar um proxy. Para estabelecer a conexão, chame o Start
método no HubConnection
objeto .
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();
}
Observação
Para clientes JavaScript, você precisa registrar pelo menos um manipulador de eventos antes de chamar o Start
método para estabelecer a conexão. Isso não é necessário para clientes .NET. Para clientes JavaScript, o código proxy gerado cria automaticamente proxies para todos os Hubs que existem no servidor e registrar um manipulador é como você indica quais Hubs seu cliente pretende usar. No entanto, para um cliente .NET, você cria proxies do Hub manualmente, portanto, o SignalR pressupõe que você usará qualquer Hub para o qual você criará um proxy.
O código de exemplo usa a URL padrão "/signalr" para se conectar ao serviço do SignalR. Para obter informações sobre como especificar uma URL base diferente, consulte ASP.NET Guia de API dos Hubs do SignalR – Servidor – A URL /signalr.
O Start
método é executado de forma assíncrona. Para garantir que as linhas de código subsequentes não sejam executadas até que a conexão seja estabelecida, use await
em um método assíncrono ASP.NET 4.5 ou .Wait()
em um método síncrono. Não use .Wait()
em um cliente WinRT.
await connection.Start();
connection.Start().Wait();
Conexões entre domínios de clientes silverlight
Para obter informações sobre como habilitar conexões entre domínios de clientes silverlight, consulte Tornando um serviço disponível entre limites de domínio.
Como configurar a conexão
Antes de estabelecer uma conexão, você pode especificar qualquer uma das seguintes opções:
- Limite de conexões simultâneas.
- Parâmetros de cadeia de caracteres de consulta.
- O método de transporte.
- Cabeçalhos HTTP.
- Certificados de cliente.
Como definir o número máximo de conexões simultâneas em clientes do WPF
Em clientes WPF, talvez seja necessário aumentar o número máximo de conexões simultâneas de seu valor padrão de 2. O valor recomendado é 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();
}
Para obter mais informações, consulte ServicePointManager.DefaultConnectionLimit.
Como especificar parâmetros de cadeia de caracteres de consulta
Se você quiser enviar dados para o servidor quando o cliente se conectar, poderá adicionar parâmetros de cadeia de caracteres de consulta ao objeto de conexão. O exemplo a seguir mostra como definir um parâmetro de cadeia de caracteres de consulta no código do cliente.
var querystringData = new Dictionary<string, string>();
querystringData.Add("contosochatversion", "1.0");
var connection = new HubConnection("http://contoso.com/", querystringData);
O exemplo a seguir mostra como ler um parâmetro de cadeia de caracteres de consulta no código do servidor.
public class StockTickerHub : Hub
{
public override Task OnConnected()
{
var version = Context.QueryString["contosochatversion"];
if (version != "1.0")
{
Clients.Caller.notifyWrongVersion();
}
return base.OnConnected();
}
}
Como especificar o método de transporte
Como parte do processo de conexão, um cliente SignalR normalmente negocia com o servidor para determinar o melhor transporte com suporte pelo servidor e pelo cliente. Se você já souber qual transporte deseja usar, poderá ignorar esse processo de negociação. Para especificar o método de transporte, passe um objeto de transporte para o método Start. O exemplo a seguir mostra como especificar o método de transporte no código do cliente.
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());
}
O namespace Microsoft.AspNet.SignalR.Client.Transports inclui as seguintes classes que você pode usar para especificar o transporte.
- LongPollingTransport
- ServerSentEventsTransport
- WebSocketTransport (disponível somente quando o servidor e o cliente usam o .NET 4.5.)
- AutoTransport (Escolhe automaticamente o melhor transporte com suporte do cliente e do servidor. Esse é o transporte padrão. Passar isso para o
Start
método tem o mesmo efeito que não passar nada.)
O transporte ForeverFrame não está incluído nesta lista porque é usado apenas por navegadores.
Para obter informações sobre como marcar o método de transporte no código do servidor, consulte ASP.NET Guia de API dos Hubs do SignalR – Servidor – Como obter informações sobre o cliente da propriedade Context. Para obter mais informações sobre transportes e fallbacks, consulte Introdução ao SignalR – Transportes e Fallbacks.
Como especificar cabeçalhos HTTP
Para definir cabeçalhos HTTP, use a Headers
propriedade no objeto de conexão. O exemplo a seguir mostra como adicionar um cabeçalho 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();
Como especificar certificados de cliente
Para adicionar certificados de cliente, use o AddClientCertificate
método no objeto de conexão.
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();
Como criar o proxy do Hub
Para definir métodos no cliente que um Hub pode chamar do servidor e invocar métodos em um Hub no servidor, crie um proxy para o Hub chamando CreateHubProxy
no objeto de conexão. A cadeia de caracteres para a CreateHubProxy
qual você passa é o nome da classe Hub ou o nome especificado pelo HubName
atributo se um foi usado no servidor. A correspondência de nome não diferencia maiúsculas de minúsculas.
Classe hub no servidor
public class StockTickerHub : Hub
Criar proxy de cliente para a 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 você decorar sua classe hub com um HubName
atributo , use esse nome.
Classe hub no servidor
[HubName("stockTicker")]
public class StockTickerHub : Hub
Criar proxy de cliente para a 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 você chamar HubConnection.CreateHubProxy
várias vezes com o mesmo hubName
, obterá o mesmo objeto armazenado em IHubProxy
cache.
Como definir métodos no cliente que o servidor pode chamar
Para definir um método que o servidor pode chamar, use o método do On
proxy para registrar um manipulador de eventos.
A correspondência de nome de método não diferencia maiúsculas de minúsculas. Por exemplo, Clients.All.UpdateStockPrice
no servidor executará updateStockPrice
, updatestockprice
ou UpdateStockPrice
no cliente.
Diferentes plataformas de cliente têm requisitos diferentes de como você escreve o código de método para atualizar a interface do usuário. Os exemplos mostrados são para clientes WinRT (Windows Store .NET). Exemplos de aplicativo de console, Silverlight e WPF são fornecidos em uma seção separada mais adiante neste tópico.
Métodos sem parâmetros
Se o método que você está tratando não tiver parâmetros, use a sobrecarga não genérica do On
método :
Método de cliente de chamada de código de servidor sem parâmetros
public class StockTickerHub : Hub
{
public void NotifyAllClients()
{
Clients.All.Notify();
}
}
Código do cliente WinRT para o método chamado do servidor sem parâmetros (consulte exemplos do WPF e do Silverlight mais adiante neste tópico)
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();
}
Métodos com parâmetros, especificando os tipos de parâmetro
Se o método que você está tratando tiver parâmetros, especifique os tipos dos parâmetros como os tipos genéricos do On
método . Há sobrecargas genéricas do On
método para permitir que você especifique até 8 parâmetros (4 em Windows Phone 7). No exemplo a seguir, um parâmetro é enviado para o UpdateStockPrice
método .
Método de cliente de chamada de código de servidor com um parâmetro
public void BroadcastStockPrice(Stock stock)
{
context.Clients.Others.UpdateStockPrice(stock);
}
A classe Stock usada para o parâmetro
public class Stock
{
public string Symbol { get; set; }
public decimal Price { get; set; }
}
Código do cliente WinRT para um método chamado do servidor com um parâmetro (consulte exemplos do WPF e do Silverlight mais adiante neste tópico)
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)
);
Métodos com parâmetros, especificando objetos dinâmicos para os parâmetros
Como alternativa à especificação de parâmetros como tipos genéricos do On
método , você pode especificar parâmetros como objetos dinâmicos:
Método de cliente de chamada de código de servidor com um parâmetro
public void BroadcastStockPrice(Stock stock)
{
context.Clients.Others.UpdateStockPrice(stock);
}
A classe Stock usada para o parâmetro
public class Stock
{
public string Symbol { get; set; }
public decimal Price { get; set; }
}
Código do cliente WinRT para um método chamado do servidor com um parâmetro , usando um objeto dinâmico para o parâmetro (consulte exemplos do WPF e do Silverlight mais adiante neste tópico)
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)
);
Como remover um manipulador
Para remover um manipulador, chame seu Dispose
método .
Código do cliente para um método chamado do servidor
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)
);
Código do cliente para remover o manipulador
updateStockPriceHandler.Dispose();
Como chamar métodos de servidor do cliente
Para chamar um método no servidor, use o Invoke
método no proxy do Hub.
Se o método de servidor não tiver nenhum valor retornado, use a sobrecarga não genérica do Invoke
método .
Código do servidor para um método que não tem nenhum valor retornado
public class StockTickerHub : Hub
{
public void JoinGroup(string groupName)
{
Groups.Add(Context.ConnectionId, groupName);
}
}
Código do cliente chamando um método que não tem valor retornado
stockTickerHubProxy.Invoke("JoinGroup", "SignalRChatRoom");
Se o método de servidor tiver um valor retornado, especifique o tipo de retorno como o tipo genérico do Invoke
método .
Código do servidor para um método que tem um valor retornado e usa um parâmetro de tipo complexo
public IEnumerable<Stock> AddStock(Stock stock)
{
_stockTicker.AddStock(stock);
return _stockTicker.GetAllStocks();
}
A classe Stock usada para o parâmetro e o valor retornado
public class Stock
{
public string Symbol { get; set; }
public decimal Price { get; set; }
}
Código do cliente que chama um método que tem um valor retornado e usa um parâmetro de tipo complexo, em um método assíncrono 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);
}
Código do cliente chamando um método que tem um valor retornado e usa um parâmetro de tipo complexo, em um método síncrono
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);
}
O Invoke
método é executado de forma assíncrona e retorna um Task
objeto . Se você não especificar await
ou .Wait()
, a próxima linha de código será executada antes que o método invocado termine de ser executado.
Como lidar com eventos de tempo de vida da conexão
O SignalR fornece os seguintes eventos de tempo de vida de conexão que você pode manipular:
Received
: gerado quando todos os dados são recebidos na conexão. Fornece os dados recebidos.ConnectionSlow
: gerado quando o cliente detecta uma conexão lenta ou com frequência.Reconnecting
: gerado quando o transporte subjacente começa a se reconectar.Reconnected
: gerado quando o transporte subjacente é reconectado.StateChanged
: gerado quando o estado da conexão é alterado. Fornece o estado antigo e o novo estado. Para obter informações sobre valores de estado de conexão, consulte Enumeração ConnectionState.Closed
: gerado quando a conexão é desconectada.
Por exemplo, se você quiser exibir mensagens de aviso para erros que não são fatais, mas causam problemas intermitentes de conexão, como lentidão ou remoção frequente da conexão, manipule o ConnectionSlow
evento.
hubConnection.ConnectionSlow += () => Console.WriteLine("Connection problems.");
Para obter mais informações, consulte Noções básicas e tratamento de eventos de tempo de vida da conexão no SignalR.
Como lidar com erros
Se você não habilitar explicitamente mensagens de erro detalhadas no servidor, o objeto de exceção retornado pelo SignalR após um erro conterá informações mínimas sobre o erro. Por exemplo, se uma chamada para newContosoChatMessage
falhar, a mensagem de erro no objeto de erro contém "There was an error invoking Hub method 'contosoChatHub.newContosoChatMessage'.
" Enviar mensagens de erro detalhadas para clientes em produção não é recomendado por motivos de segurança, mas se você quiser habilitar mensagens de erro detalhadas para fins de solução de problemas, use o código a seguir no servidor.
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
App.MapSignalR(hubConfiguration);
Para lidar com erros gerados pelo SignalR, você pode adicionar um manipulador para o Error
evento no objeto de conexão.
hubConnection.Error += ex => Console.WriteLine("SignalR error: {0}", ex.Message);
Para lidar com erros de invocações de método, encapsule o código em um bloco 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);
}
Como habilitar o log do lado do cliente
Para habilitar o log do lado do cliente, defina as TraceLevel
propriedades e TraceWriter
no objeto de conexão.
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();
}
Exemplos de código de aplicativo WPF, Silverlight e console para métodos de cliente que o servidor pode chamar
Os exemplos de código mostrados anteriormente para definir métodos de cliente que o servidor pode chamar se aplicam a clientes WinRT. Os exemplos a seguir mostram o código equivalente para clientes de aplicativo WPF, Silverlight e console.
Métodos sem parâmetros
Código do cliente WPF para o método chamado do servidor sem parâmetros
stockTickerHub.On<Stock>("notify", () =>
Dispatcher.InvokeAsync(() =>
{
SignalRTextBlock.Text += string.Format("Notified!");
})
);
Código do cliente Silverlight para o método chamado do servidor sem parâmetros
stockTickerHub.On<Stock>("notify", () =>
// Context is a reference to SynchronizationContext.Current
Context.Post(delegate
{
textBox.Text += "Notified!";
}, null)
);
Código do cliente do aplicativo de console para o método chamado do servidor sem parâmetros
stockTickerHubProxyProxy.On("Notify", () => Console.WriteLine("Notified!"));
Métodos com parâmetros, especificando os tipos de parâmetro
Código do cliente WPF para um método chamado do servidor com um parâmetro
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock =>
Dispatcher.InvokeAsync(() =>
{
textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
})
);
Código do cliente Silverlight para um método chamado do servidor com um parâmetro
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)
);
Código do cliente do aplicativo de console para um método chamado do servidor com um parâmetro
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock =>
Console.WriteLine("Symbol {0} Price {1}", stock.Symbol, stock.Price));
Métodos com parâmetros, especificando objetos dinâmicos para os parâmetros
Código do cliente WPF para um método chamado do servidor com um parâmetro , usando um objeto dinâmico para o parâmetro
stockTickerHubProxy.On("UpdateStockPrice", stock =>
Dispatcher.InvokeAsync(() =>
{
textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
})
);
Código do cliente Silverlight para um método chamado do servidor com um parâmetro , usando um objeto dinâmico para o parâmetro
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)
);
Código do cliente do aplicativo de console para um método chamado do servidor com um parâmetro , usando um objeto dinâmico para o parâmetro
stockTickerHubProxy.On("UpdateStockPrice", stock =>
Console.WriteLine("Symbol {0} Price {1}", stock.Symbol, stock.Price));