ASP.NET Core SignalR .NET Client

The ASP.NET Core SignalR .NET client library lets you communicate with SignalR hubs from .NET apps.

Note

Xamarin has special requirements for Visual Studio version. For more information, see SignalR Client 2.1.1 in Xamarin.

View or download sample code (how to download)

The code sample in this article is a WPF app that uses the ASP.NET Core SignalR .NET client.

Install the SignalR .NET client package

The Microsoft.AspNetCore.SignalR.Client package is needed for .NET clients to connect to SignalR hubs. To install the client library, run the following command in the Package Manager Console window:

Install-Package Microsoft.AspNetCore.SignalR.Client

Connect to a hub

To establish a connection, create a HubConnectionBuilder and call Build. The hub URL, protocol, transport type, log level, headers, and other options can be configured while building a connection. Configure any required options by inserting any of the HubConnectionBuilder methods into Build. Start the connection with StartAsync.

using System;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.AspNetCore.SignalR.Client;

namespace SignalRChatClient
{
    public partial class MainWindow : Window
    {
        HubConnection connection;
        public MainWindow()
        {
            InitializeComponent();

            connection = new HubConnectionBuilder()
                .WithUrl("http://localhost:53353/ChatHub")
                .Build();

            connection.Closed += async (error) =>
            {
                await Task.Delay(new Random().Next(0,5) * 1000);
                await connection.StartAsync();
            };
        }

        private async void connectButton_Click(object sender, RoutedEventArgs e)
        {
            connection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                this.Dispatcher.Invoke(() =>
                {
                   var newMessage = $"{user}: {message}";
                   messagesList.Items.Add(newMessage);
                });
            });

            try
            {
                await connection.StartAsync();
                messagesList.Items.Add("Connection started");
                connectButton.IsEnabled = false;
                sendButton.IsEnabled = true;
            }
            catch (Exception ex)
            {
                messagesList.Items.Add(ex.Message);
            }
        }

        private async void sendButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                await connection.InvokeAsync("SendMessage", 
                    userTextBox.Text, messageTextBox.Text);
            }
            catch (Exception ex)
            {                
                messagesList.Items.Add(ex.Message);                
            }
        }
    }
}

Handle lost connection

Use the Closed event to respond to a lost connection. For example, you might want to automate reconnection.

The Closed event requires a delegate that returns a Task, which allows async code to run without using async void. To satisfy the delegate signature in a Closed event handler that runs synchronously, return Task.CompletedTask:

connection.Closed += (error) => {
    // Do your close logic.
    return Task.CompletedTask;
};

The main reason for the async support is so you can restart the connection. Starting a connection is an async action.

In a Closed handler that restarts the connection, consider waiting for some random delay to prevent overloading the server, as shown in the following example:

connection.Closed += async (error) =>
{
    await Task.Delay(new Random().Next(0,5) * 1000);
    await connection.StartAsync();
};

Call hub methods from client

InvokeAsync calls methods on the hub. Pass the hub method name and any arguments defined in the hub method to InvokeAsync. SignalR is asynchronous, so use async and await when making the calls.

await connection.InvokeAsync("SendMessage", 
    userTextBox.Text, messageTextBox.Text);

The InvokeAsync method returns a Task which completes when the server method returns. The return value, if any, is provided as the result of the Task. Any exceptions thrown by the method on the server produce a faulted Task. Use await syntax to wait for the server method to complete and try...catch syntax to handle errors.

The SendAsync method returns a Task which completes when the message has been sent to the server. No return value is provided since this Task doesn't wait until the server method completes. Any exceptions thrown on the client while sending the message produce a faulted Task. Use await and try...catch syntax to handle send errors.

Note

If you're using Azure SignalR Service in Serverless mode, you cannot call hub methods from a client. For more information, see the SignalR Service documentation.

Call client methods from hub

Define methods the hub calls using connection.On after building, but before starting the connection.

connection.On<string, string>("ReceiveMessage", (user, message) =>
{
    this.Dispatcher.Invoke(() =>
    {
       var newMessage = $"{user}: {message}";
       messagesList.Items.Add(newMessage);
    });
});

The preceding code in connection.On runs when server-side code calls it using the SendAsync method.

public async Task SendMessage(string user, string message)
{
    await Clients.All.SendAsync("ReceiveMessage", user,message);
}

Error handling and logging

Handle errors with a try-catch statement. Inspect the Exception object to determine the proper action to take after an error occurs.

try
{
    await connection.InvokeAsync("SendMessage", 
        userTextBox.Text, messageTextBox.Text);
}
catch (Exception ex)
{                
    messagesList.Items.Add(ex.Message);                
}

Additional resources