Building Real-Time Applications with SignalR and C#

Real-time communication is becoming increasingly important in modern web applications. Whether you’re building a chat application, live dashboard, or collaborative tool, you need a way to push data from server to client instantly. SignalR, Microsoft’s real-time communication framework, makes this incredibly easy with just a few lines of code.

What is SignalR?

SignalR is a framework for building real-time web applications. It enables bi-directional communication between web servers and clients, allowing you to push content to connected clients instantly. Here’s what makes SignalR powerful:

  • Server Requirements: Must run on ASP.NET Core
  • Client Flexibility: Supports browsers, services, console apps, and more
  • Transport Flexibility: Automatically chooses the best transport (WebSockets, Server-Sent Events, or Long Polling)
  • Scalability: Can handle millions of concurrent connections
  • Ease of Use: Minimal code required to get started

Setting Up a SignalR Server

Let’s start by creating a simple SignalR server that broadcasts messages to all connected clients:

async Task Main()
{
    var builder = WebApplication.CreateBuilder();
    builder.Services.AddSignalR();

    var app = builder.Build();
    app.MapHub<RefreshHub>("/refreshHub");
    app.MapGet("/", () => Results.Content(html, "text/html"));

    var t = app.RunAsync();

    while (true)
    {
        var hc = (IHubContext<RefreshHub>)app.Services.GetRequiredService(typeof(IHubContext<RefreshHub>));
        await hc.Clients.All.SendAsync("event_name", arg1: "SignalR Server", arg2: $"learning SignalR!");
        Thread.Sleep(1000);
    }
}

public class RefreshHub : Hub
{
    public override async Task OnConnectedAsync()
    {
        Console.WriteLine($"Client connected: {Context.ConnectionId}");
        await base.OnConnectedAsync();
    }

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

Creating a Browser Client

The browser client is incredibly simple to set up. We just need to include the SignalR JavaScript library and write a few lines of connection code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>LearningLINQPad.com SignalR</title>
  </head>
  <body>
    <div id="root"><ol id="items"></ol></div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.0/signalr.min.js"></script>

    <script>
      var connection = new signalR.HubConnectionBuilder()
        .withUrl("/refreshHub")
        .build();

      connection.on("event_name", function (user, message) {
        const items = document.getElementById("items");
        const li = document.createElement("li");
        li.textContent = message;
        items.appendChild(li);
      });

      connection
        .start()
        .then(function () {
          console.log("Connected to SignalR hub");
        })
        .catch(function (err) {
          return console.error(err.toString());
        });
    </script>
  </body>
</html>

Creating a Console Client

For console applications, you’ll need to add the Microsoft.AspNetCore.SignalR.Client package. Here’s how to create a robust console client:

// Create our connection with the SignalR server
var connection = new HubConnectionBuilder()
    .WithUrl("http://localhost:5000/refreshHub")
    .Build();

// Handle incoming messages
connection.On<string, string>("event_name", (user, message) =>
{
    Console.WriteLine($"Message from {user}: {message}");
});

// Handle connection closure with automatic reconnection
connection.Closed += async (error) =>
{
    Console.WriteLine($"Connection closed: {error?.Message}");
    await Task.Delay(5000); // Wait before reconnecting
    await connection.StartAsync(); // Attempt to reconnect
    Console.WriteLine("Reconnected to hub.");
};

// Start the connection
await connection.StartAsync();
Console.WriteLine("Connected to SignalR hub.");

// Send a message to all clients
await connection.InvokeAsync("SendMessage", "C# Client", "Hello from C# console app!");

Util.ReadLine();

await connection.StopAsync();

Key Features of SignalR

1. Automatic Transport Selection

SignalR automatically chooses the best transport method:

  • WebSockets: Best performance, bi-directional communication
  • Server-Sent Events: Good for server-to-client communication
  • Long Polling: Fallback for older browsers

2. Connection Management

  • Automatic reconnection handling
  • Connection state monitoring
  • Client grouping and targeting

3. Scalability

  • Can handle millions of concurrent connections
  • Built-in support for Redis backplane for horizontal scaling
  • Efficient message routing

Testing with LINQPad

LINQPad makes it easy to test SignalR applications. You can:

  • Run the server in one LINQPad script
  • Test different client implementations
  • Debug connection issues
  • Experiment with different message patterns

LINQPad showing ASP.NET Core server with SignalR and one hub

Browser showing messages coming from SignalR server using WebSockets

LINQPad showing how to use SignalR client packages in a console app

Download LINQPad Today

Get started with the most powerful .NET Rapid Progress Tool (RPT) available.

Get LINQPad Premium

Powerful .NET acceleration. Code at the speed of thought.

Best Practices

  1. Error Handling: Always implement proper error handling for connections
  2. Reconnection Logic: Implement automatic reconnection for production apps
  3. Message Validation: Validate messages on both client and server
  4. Resource Management: Properly dispose of connections
  5. Security: Implement authentication and authorization as needed

Real-World Use Cases

SignalR is perfect for:

  • Chat Applications: Real-time messaging between users
  • Live Dashboards: Real-time data updates
  • Collaborative Tools: Live editing and collaboration
  • Gaming: Real-time game state updates
  • Notifications: Push notifications to web clients

Conclusion

SignalR makes real-time communication incredibly simple. With just a few lines of code, you can create applications that handle millions of concurrent connections. The framework’s flexibility and ease of use make it an excellent choice for any real-time application.

LINQPad provides the perfect environment for experimenting with SignalR, allowing you to quickly test different implementations and see how real-time communication works in practice.


Want to learn more about LINQPad and how it can supercharge your development workflow? Check out my comprehensive LINQPad course where I cover everything from basic queries to advanced scenarios like the ones shown here.

C# SignalR Real-Time WebSockets ASP.NET Core LINQPad Web Development