HttpClient.GetStreamAsync hangs when consuming .NET 10 Server-Sent Events from Blazor WebAssembly

2 weeks ago 17
ARTICLE AD BOX

I am experimenting with the new .NET 10 built-in Server Sent Events (Results.ServerSentEvents) on my ASP.NET Core Web API backend.

The backend endpoint works correctly:

The request arrives

The SSE connection is established

The server immediately starts streaming data

However, from a Blazor WebAssembly frontend, the client never receives any data.

The call to HttpClient.GetStreamAsync() simply hangs forever.

Client code

using var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Add("SessionId", SessionId.ToString()); var url = $"/ssehost/connect/{WebUtility.UrlEncode(ServiceId.Value)}"; using var stream = await httpClient.GetStreamAsync(url, Cts.Token); // <- Hangs forever using var streamReader = new StreamReader(stream); var buffer = new StringBuilder(); var chunk = new char[1024]; while (!Cts.IsCancellationRequested) { var read = await streamReader.ReadAsync(chunk.AsMemory(0, chunk.Length), Cts.Token); if (read <= 0) break; buffer.Append(chunk, 0, read); while (TryExtractFrame(buffer, out var frame)) { ParseFrame(frame); } }

The backend endpoint is implemented using:

[ApiController] [Route("ssehost")] public class SseHostController( IServerAuthenticationService authenticationService, SseHostCollection sseHostCollection, FabricClient fabricClient) : ControllerBase { [HttpGet("connect/{serviceId}")] public async Task<IResult> Connect( [FromRoute] string serviceId, [FromHeader] Guid sessionId) { await authenticationService.InitializeAsync(sessionId); var userIdString = await authenticationService.GetUserId(); var sseHost = new SseHost( sseHostCollection, fabricClient, new SseServiceId(serviceId), new UserId(userIdString), new SessionId(sessionId.ToString())); return Results.ServerSentEvents(sseHost.GetStrings()); } }

No exceptions are thrown.

Why does HttpClient.GetStreamAsync() hang forever when consuming Server-Sent Events in Blazor WebAssembly, and how can this be fixed?

Read Entire Article