How to consume an SSE endpoint with HttpClient in C#

By Tan Lee Published on Mar 04, 2025  208
You can consume a Server-Sent Events (SSE) endpoint using HttpClient in C# by reading the event stream asynchronously.

Server-Sent Events (SSE) enable a client to receive real-time updates from the server over a one-way connection. Instead of the client repeatedly requesting new data, the server automatically pushes messages to the client whenever new information is available. This approach reduces unnecessary requests and improves efficiency compared to traditional polling.

SSE Client for Receiving Stock Price Updates

This example listens for stock price updates from an SSE endpoint.

using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        HttpClient client = new HttpClient();
        client.Timeout = TimeSpan.FromSeconds(5);  // Set timeout to avoid hanging
        
        string stockSymbol = "AAPL";
        string url = $"http://localhost:9000/stockpriceupdates/{stockSymbol}";

        while (true)
        {
            try
            {
                Console.WriteLine("Connecting to SSE endpoint...");
                
                using (var streamReader = new StreamReader(await client.GetStreamAsync(url)))
                {
                    while (!streamReader.EndOfStream)
                    {
                        var message = await streamReader.ReadLineAsync();
                        Console.WriteLine($"Received stock update: {message}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
                Console.WriteLine("Retrying in 5 seconds...");
                await Task.Delay(TimeSpan.FromSeconds(5));  // Simple retry logic
            }
        }
    }
}

In this example:

  • The client continuously listens for new stock price updates.
  • If the connection is lost, it waits for 5 seconds before retrying.
  • StreamReader reads the incoming messages from the stream line by line.

Handling Reconnection More Effectively

For better reliability, use Polly (a resilience library) for retries:

using Polly;
using Polly.Retry;

RetryPolicy retryPolicy = Policy
    .Handle<HttpRequestException>()
    .Or<TaskCanceledException>()
    .WaitAndRetryForeverAsync(retryAttempt => TimeSpan.FromSeconds(5));

await retryPolicy.ExecuteAsync(async () =>
{
    using (var streamReader = new StreamReader(await client.GetStreamAsync(url)))
    {
        while (!streamReader.EndOfStream)
        {
            var message = await streamReader.ReadLineAsync();
            Console.WriteLine($"Received stock update: {message}");
        }
    }
});

For example, How to consume an SSE endpoint using HttpClient to receive real-time weather updates instead of stock prices.

using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        HttpClient client = new HttpClient();
        client.Timeout = TimeSpan.FromSeconds(5);
        string city = "NewYork";
        string url = $"http://localhost:9000/weatherupdates/{city}";

        while (true)
        {
            try
            {
                Console.WriteLine("Establishing connection to weather updates...");
                using (var streamReader = new StreamReader(await client.GetStreamAsync(url)))
                {
                    while (!streamReader.EndOfStream)
                    {
                        var message = await streamReader.ReadLineAsync();
                        Console.WriteLine($"Received weather update: {message}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
                Console.WriteLine("Retrying in 5 seconds...");
                await Task.Delay(TimeSpan.FromSeconds(5));
            }
        }
    }
}

This console application continuously listens for real-time weather updates for a specific city. If the connection drops, it retries every 5 seconds.