Przewodnik interfejsu API centrów sygnałów ASP.NET — klient platformy .NET (sygnalizujący 1. x)

Fletcher Patryk, Tomasz Dykstra

Warning

Ta dokumentacja nie jest najnowsza dla najnowszej wersji usługi sygnalizującej. Zapoznaj się z tematem ASP.NET Core sygnalizujący.

Ten dokument zawiera wprowadzenie do korzystania z interfejsu API centrów dla programu sygnalizującego w wersji 2 na klientach platformy .NET, takich jak Windows Store (WinRT), WPF, Silverlight i aplikacje konsolowe.

Interfejs API centrów sygnałów umożliwia wykonywanie zdalnych wywołań procedur (RPC) z serwera do podłączonych klientów i od klientów do serwera programu. W polu kod serwera można zdefiniować metody, które mogą być wywoływane przez klientów, i wywoływanie metod uruchamianych na kliencie. W kodzie klienta należy zdefiniować metody, które mogą być wywoływane z serwera programu, i wywoływanie metod, które są uruchamiane na serwerze. Sygnalizujący, że wszystkie instalacje z klientem do serwera są obsługiwane.

Sygnalizujący oferuje również interfejs API niższego poziomu o nazwie połączeń trwałych. Aby zapoznać się z wprowadzeniem do sygnałów, centrów i połączeń trwałych lub samouczka, w którym pokazano, jak utworzyć kompletną aplikację sygnalizującą, zobacz sygnalizującer-wprowadzenie.

Omówienie

Ten dokument zawiera następujące sekcje:

Przykładowe projekty klienta platformy .NET można znaleźć w następujących zasobach:

Aby uzyskać dokumentację dotyczącą sposobu programowania serwera lub klientów JavaScript, zobacz następujące zasoby:

Łącza do tematów dotyczących odwołań do interfejsów API znajdują się w wersji programu .NET 4,5 interfejsu API. Jeśli używasz programu .NET 4, zobacz temat wersja interfejsu API w wersji .NET 4.

Konfiguracja klienta

Zainstaluj pakiet NuGet Microsoft. ASPNET. Signal. Client (nie pakiet Microsoft. ASPNET. signaler ). Ten pakiet obsługuje klientów WinRT, Silverlight, WPF, aplikacji konsolowych i Windows Phone dla programów .NET 4 i .NET 4,5.

Jeśli wersja usługi sygnalizująca, która jest zainstalowana na kliencie, różni się od wersji programu znajdującej się na serwerze, sygnał jest często możliwy do dostosowania do różnic. Na przykład gdy zostanie wydane polecenie sygnalizujące w wersji 2,0 i zostanie ono zainstalowane na serwerze, serwer będzie obsługiwał klientów z zainstalowanym systemem 1.1. x oraz klientami z zainstalowanym 2,0. Jeśli różnica między wersją na serwerze i wersją na kliencie jest zbyt duża, sygnalizujący zgłasza wyjątek InvalidOperationException, gdy klient próbuje nawiązać połączenie. Komunikat o błędzie to "You are using a version of the client that isn't compatible with the server. Client version X.X, server version X.X".

Jak nawiązać połączenie

Aby można było nawiązać połączenie, należy utworzyć obiekt HubConnection i utworzyć serwer proxy. Aby nawiązać połączenie, wywołaj metodę Start na obiekcie 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();

Note

W przypadku klientów JavaScript należy zarejestrować co najmniej jeden program obsługi zdarzeń przed wywołaniem metody Start w celu nawiązania połączenia. Nie jest to konieczne w przypadku klientów platformy .NET. W przypadku klientów JavaScript wygenerowany kod serwera proxy automatycznie tworzy serwery proxy dla wszystkich centrów istniejących na serwerze, a procedura rejestrowania programu obsługi wskazuje, które centra, których Klient zamierza używać. Jednak dla klienta platformy .NET można ręcznie utworzyć centra proxy, dlatego moduł sygnalizujący zakłada, że będziesz używać dowolnego centrum, dla którego tworzysz serwer proxy.

Przykładowy kod używa domyślnego adresu URL "/SignalR", aby nawiązać połączenie z usługą sygnalizującej. Aby uzyskać informacje na temat sposobu określania innego podstawowego adresu URL, zobacz Przewodnik interfejsu API centrów ASP.NET Signals-Server-The/SIGNALR URL.

Metoda Start jest wykonywana asynchronicznie. Aby upewnić się, że kolejne wiersze kodu nie są wykonywane, dopóki połączenie nie zostanie nawiązane, użyj await w metodzie asynchronicznej ASP.NET 4,5 lub .Wait() w metodzie synchronicznej. Nie należy używać .Wait() w kliencie WinRT.

await connection.Start();
connection.Start().Wait();

Klasa HubConnection jest bezpieczna wątkowo.

Połączenia między domenami z klientów Silverlight

Informacje o sposobie włączania połączeń między domenami z klientów Silverlight można znaleźć w temacie udostępnianie usługi w granicach domen.

Jak skonfigurować połączenie

Przed nawiązaniem połączenia można określić jedną z następujących opcji:

  • Limit jednoczesnych połączeń.
  • Parametry ciągu zapytania.
  • Metoda transportu.
  • Nagłówki HTTP.
  • Certyfikaty klienta.

Jak ustawić maksymalną liczbę jednoczesnych połączeń w klientach WPF

W przypadku klientów WPF może zajść potrzeba zwiększenia maksymalnej liczby jednoczesnych połączeń z wartością domyślną 2. Zalecana wartość to 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();

Aby uzyskać więcej informacji, zobacz ServicePointManager. DefaultConnectionLimit.

Jak określić parametry ciągu zapytania

Jeśli chcesz wysłać dane do serwera podczas łączenia się z klientem, możesz dodać parametry ciągu zapytania do obiektu połączenia. Poniższy przykład pokazuje, jak ustawić parametr ciągu zapytania w kodzie klienta.

var querystringData = new Dictionary<string, string>();
querystringData.Add("contosochatversion", "1.0");
var connection = new HubConnection("http://contoso.com/", querystringData);

Poniższy przykład pokazuje, jak odczytać parametr ciągu zapytania w kodzie serwera.

public class StockTickerHub : Hub
{
    public override Task OnConnected()
    {
        var version = Context.QueryString["contosochatversion"];
        if (version != "1.0")
        {
            Clients.Caller.notifyWrongVersion();
        }
        return base.OnConnected();
    }
}

Jak określić metodę transportu

W ramach procesu łączenia klient sygnalizujący zwykle negocjuje z serwerem, aby określić najlepszy transport obsługiwany przez serwer i klienta. Jeśli wiesz już, którego transportu chcesz użyć, możesz pominąć ten proces negocjacji. Aby określić metodę transportu, przekaż obiekt transportu do metody startowej. Poniższy przykład pokazuje, jak określić metodę transportu w kodzie klienta.

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

Przestrzeń nazw Microsoft. ASPNET. Signal. Client. Transports zawiera następujące klasy, których można użyć do określenia transportu.

Transport ForeverFrame nie jest uwzględniony na tej liście, ponieważ jest używany tylko przez przeglądarki.

Aby uzyskać informacje na temat sprawdzania metody transportu w kodzie serwera, zobacz Przewodnik interfejsu API centrów ASP.NET Signals-Server — jak uzyskać informacje o kliencie z właściwości Context. Aby uzyskać więcej informacji na temat transportów i rezerw, zobacz wprowadzenie do sygnałów-Transports and fallbacks.

Jak określić nagłówki HTTP

Aby ustawić nagłówki HTTP, użyj właściwości Headers w obiekcie Connection. Poniższy przykład pokazuje, jak dodać nagłówek 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();

Jak określić certyfikaty klienta

Aby dodać certyfikaty klienta, użyj metody AddClientCertificate w obiekcie 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();

Jak utworzyć serwer proxy centrum

W celu zdefiniowania metod na kliencie, które mogą być wywoływane przez koncentrator z serwera, i aby wywołać metody w centrum na serwerze, Utwórz serwer proxy dla centrum, wywołując CreateHubProxy w obiekcie Connection. Ciąg przekazany do CreateHubProxy jest nazwą klasy centrum lub nazwą określoną przez atrybut HubName, jeśli został on użyty na serwerze. Przy dopasowywaniu nazwy nie jest uwzględniana wielkość liter.

Klasa centrum na serwerze

public class StockTickerHub : Hub

Utwórz serwer proxy klienta dla klasy centrum

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

Jeśli dekorować klasę centrów z atrybutem HubName, Użyj tej nazwy.

Klasa centrum na serwerze

[HubName("stockTicker")]
public class StockTickerHub : Hub

Utwórz serwer proxy klienta dla klasy centrum

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

Obiekt serwera proxy jest bezpieczny wątkowo. W rzeczywistości w przypadku wywołania HubConnection.CreateHubProxy wiele razy z tą samą hubNamemożna uzyskać ten sam buforowany obiekt IHubProxy.

Jak zdefiniować metody na kliencie, które mogą być wywoływane przez serwer

Aby zdefiniować metodę, którą może wywołać serwer, użyj metody On serwera proxy, aby zarejestrować procedurę obsługi zdarzeń.

W dopasowaniu nazw metod nie jest rozróżniana wielkość liter. Na przykład Clients.All.UpdateStockPrice na serwerze wykona updateStockPrice, updatestockpricelub UpdateStockPrice na kliencie.

Różne platformy klienckie mają różne wymagania dotyczące sposobu pisania kodu metody w celu zaktualizowania interfejsu użytkownika. Przykłady przedstawiono dla klientów WinRT (Windows Store .NET). Przykłady aplikacji WPF, Silverlight i konsoli znajdują się w osobnej sekcji w dalszej części tego tematu.

Metody bez parametrów

Jeśli obsługiwana metoda nie ma parametrów, użyj nieogólnego przeciążenia metody On:

Kod serwera wywołujący metodę klienta bez parametrów

public class StockTickerHub : Hub
{
    public void NotifyAllClients()
    {
         Clients.All.Notify();
    }
}

Kod klienta WinRT dla metody wywoływanej z serwera bez parametrów (Zobacz przykłady WPF i Silverlight w dalszej części tego tematu)

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

Metody z parametrami, Określanie typów parametrów

Jeśli obsługiwana metoda ma parametry, określ typy parametrów jako typy ogólne metody On. Istnieją ogólne przeciążenia metody On, aby umożliwić określenie maksymalnie 8 parametrów (4 w Windows Phone 7). W poniższym przykładzie jeden parametr jest wysyłany do metody UpdateStockPrice.

Kod serwera wywołujący metodę klienta z parametrem

public void BroadcastStockPrice(Stock stock)
{
    context.Clients.Others.UpdateStockPrice(stock);
}

Klasa giełdowa użyta dla parametru

public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

Kod klienta WinRT dla metody wywoływanej z serwera z parametrem (Zobacz przykłady WPF i Silverlight w dalszej części tego tematu)

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

Metody z parametrami, określając dynamiczne obiekty parametrów

Alternatywą dla określania parametrów jako typów ogólnych metody On można określić parametry jako obiekty dynamiczne:

Kod serwera wywołujący metodę klienta z parametrem

public void BroadcastStockPrice(Stock stock)
{
    context.Clients.Others.UpdateStockPrice(stock);
}

Klasa giełdowa użyta dla parametru

public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

Kod klienta WinRT dla metody wywoływanej z serwera z parametrem przy użyciu obiektu dynamicznego dla parametru (Zobacz przykłady WPF i Silverlight w dalszej części tego tematu)

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

Jak usunąć procedurę obsługi

Aby usunąć procedurę obsługi, wywołaj jej metodę Dispose.

Kod klienta dla metody wywoływanej z serwera

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

Kod klienta do usunięcia programu obsługi

updateStockPriceHandler.Dispose();

Jak wywoływać metody serwera z klienta

Aby wywołać metodę na serwerze, użyj metody Invoke w serwerze proxy centrum.

Jeśli metoda serwera nie ma zwracanej wartości, użyj nieogólnego przeciążenia metody Invoke.

Kod serwera dla metody, która nie ma wartości zwracanej

public class StockTickerHub : Hub
{
    public void JoinGroup(string groupName)
    {
        Groups.Add(Context.ConnectionId, groupName); 
    }
}

Kod klienta wywołujący metodę, która nie ma wartości zwracanej

stockTickerHubProxy.Invoke("JoinGroup", hubConnection.ConnectionID, "SignalRChatRoom");

Jeśli metoda serwera ma wartość zwracaną, określ zwracany typ jako typ ogólny metody Invoke.

Kod serwera dla metody, która ma wartość zwracaną i przyjmuje parametr typu złożonego

public IEnumerable<Stock> AddStock(Stock stock)
{
    _stockTicker.AddStock(stock);
    return _stockTicker.GetAllStocks();
}

Klasa giełdowa użyta dla parametru i wartości zwracanej

public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

Kod klienta wywołujący metodę, która ma wartość zwracaną i przyjmuje parametr typu złożonego, w metodzie asynchronicznej 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);
}

Kod klienta wywołujący metodę, która ma wartość zwracaną i pobiera parametr typu złożonego, w metodzie synchronicznej

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

Metoda Invoke wykonuje asynchroniczne i zwraca obiekt Task. Jeśli nie określisz await ani .Wait(), następnym wierszem kodu zostanie wykonane przed wykonaniem metody wywoływanej.

Jak obsługiwać zdarzenia okresu istnienia połączenia

Program sygnalizujący udostępnia następujące zdarzenia okresu istnienia połączenia, które można obsłużyć:

  • Received: wywoływane po odebraniu dowolnego danych w połączeniu. Dostarcza odebrane dane.
  • ConnectionSlow: wywoływane, gdy klient wykrywa powolne lub często porzucane połączenie.
  • Reconnecting: uruchamiany, gdy podstawowy transport zacznie ponownie nawiązać połączenie.
  • Reconnected: wywoływane, gdy podstawowy transport został połączony ponownie.
  • StateChanged: występuje, gdy zmieni się stan połączenia. Zapewnia poprzedni stan i nowy stan. Aby uzyskać informacje o wartościach stanu połączenia, zobacz Wyliczenie ConnectionState.
  • Closed: wywoływane, gdy połączenie zostało rozłączone.

Na przykład, jeśli chcesz wyświetlać komunikaty ostrzegawcze dla błędów, które nie są krytyczne, ale powodują sporadyczne problemy z połączeniem, takie jak spowolnienie lub częste usuwanie połączenia, obsłuż zdarzenie ConnectionSlow.

hubConnection.ConnectionSlow += () => Console.WriteLine("Connection problems.");

Aby uzyskać więcej informacji, zobacz Omówienie i obsługa zdarzeń okresu istnienia połączenia w programie sygnalizującym.

Jak obsłużyć błędy

Jeśli nie włączysz jawnie szczegółowych komunikatów o błędach na serwerze, obiekt wyjątku zwracany przez sygnalizujący po wystąpieniu błędu zawiera minimalne informacje o błędzie. Na przykład jeśli wywołanie newContosoChatMessage nie powiedzie się, komunikat o błędzie w obiekcie Error zawiera "There was an error invoking Hub method 'contosoChatHub.newContosoChatMessage'." wysyłanie szczegółowych komunikatów o błędach do klientów w środowisku produkcyjnym nie jest zalecane ze względów bezpieczeństwa, ale jeśli chcesz włączyć szczegółowe komunikaty o błędach w celu rozwiązywania problemów, użyj następującego kodu na serwerze.

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
RouteTable.Routes.MapHubs(hubConfiguration);

Aby obsłużyć błędy, które wywołuje program sygnalizujący, można dodać procedurę obsługi dla zdarzenia Error w obiekcie Connection.

hubConnection.Error += ex => Console.WriteLine("SignalR error: {0}", ex.Message);

Aby obsłużyć błędy wywołań metod, zawiń kod w bloku 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);
}

Jak włączyć rejestrowanie po stronie klienta

Aby włączyć rejestrowanie po stronie klienta, należy ustawić właściwości TraceLevel i TraceWriter w obiekcie Connection.

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

Przykłady kodu aplikacji WPF, Silverlight i konsoli dla metod klienta wywoływanych przez serwer

Przykłady kodu pokazane wcześniej w celu zdefiniowania metod klienta, które mogą być wywoływane przez serwer, mają zastosowanie do klientów WinRT. W poniższych przykładach przedstawiono odpowiedni kod dla klientów WPF, Silverlight i aplikacji konsolowych.

Metody bez parametrów

Kod klienta WPF dla metody wywoływanej z serwera bez parametrów

stockTickerHub.On<Stock>("notify", () =>
    Dispatcher.InvokeAsync(() =>
        {
            SignalRTextBlock.Text += string.Format("Notified!");
        })
);

Kod klienta Silverlight dla metody wywoływanej z serwera bez parametrów

stockTickerHub.On<Stock>("notify", () =>
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += "Notified!";
    }, null)
);

Kod klienta aplikacji konsolowej dla metody wywoływanej z serwera bez parametrów

stockTickerHubProxyProxy.On("Notify", () => Console.WriteLine("Notified!"));

Metody z parametrami, Określanie typów parametrów

Kod klienta WPF dla metody wywoływanej z serwera z parametrem

stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    Dispatcher.InvokeAsync(() =>
        {
            textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
        })
);

Kod klienta Silverlight dla metody wywoływanej z serwera z parametrem

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

Kod klienta aplikacji konsolowej dla metody wywoływanej z serwera z parametrem

stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    Console.WriteLine("Symbol {0} Price {1}", stock.Symbol, stock.Price));

Metody z parametrami, określając dynamiczne obiekty parametrów

Kod klienta WPF dla metody wywoływanej z serwera z parametrem przy użyciu obiektu dynamicznego dla parametru

stockTickerHubProxy.On("UpdateStockPrice", stock => 
    Dispatcher.InvokeAsync(() =>
        {
            textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
        })
);

Kod klienta Silverlight dla metody wywoływanej z serwera z parametrem przy użyciu obiektu dynamicznego dla parametru

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

Kod klienta aplikacji konsolowej dla metody wywoływanej z serwera z parametrem przy użyciu obiektu dynamicznego dla parametru

stockTickerHubProxy.On("UpdateStockPrice", stock => 
    Console.WriteLine("Symbol {0} Price {1}", stock.Symbol, stock.Price));