In .NET 9 I've created a default Blazor Web app project and added a SignalR hub that is used for sending notifications between clients.
When one session increments the value for /counter
, all sessions are notified of this and updates their displayed value. This all works.
What I don't understand is why in the browser developer tools, there's no connection to the configured Hub URL. There is only the standard Blazor server websocket to /_blazor
.
The code-behind for Counter.razor
is updated like this:
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private HubConnection _hubConnection;
public async ValueTask DisposeAsync()
{
await _hubConnection.DisposeAsync();
}
protected override async Task OnInitializedAsync()
{
_hubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri(CounterHub.HubUrl))
.Build();
_hubConnection.On<CounterNotification>(CounterHub.CounterUpdatedMethod, HandleCounterUpdated);
await _hubConnection.StartAsync();
}
private void HandleCounterUpdated(CounterNotification notification)
{
currentCount = notification.Counter;
InvokeAsync(StateHasChanged);
}
private async Task IncrementCount()
{
await CounterHubContext.Clients.All.SendAsync(CounterHub.CounterUpdatedMethod, new CounterNotification(currentCount + 1));
}
}
CounterHub.cs
is implemented like this:
public class CounterHub : Hub
{
public const string HubUrl = "/counter-notifications";
public const string CounterUpdatedMethod = "CounterUpdated";
public override Task OnConnectedAsync()
{
Console.WriteLine("{0} connected", Context.ConnectionId);
return base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? e)
{
Console.WriteLine("{0} disconnected", Context.ConnectionId);
await base.OnDisconnectedAsync(e);
}
}
CounterNotification.cs
looks like this:
public record CounterNotification(int Counter)
{
public CounterNotification() : this(0) { }
}
It's all hooked up in Program.cs
with the additions of these lines:
builder.Services.AddSignalR();
builder.Services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
["application/octet-stream"]);
});
app.UseResponseCompression();
app.MapHub<CounterHub>(CounterHub.HubUrl);
With this, I would expect to see a websocket open up to /counter-notifications
. But there's nothing. What's going on? Is the default Blazor websocket connection reused for the custom SignalR?
With this, I would expect to see a websocket open up to /counter-notifications. But there's nothing. What's going on?
You won't see the connection just because the client is the blazor app instead of your browser,the browser didn't connect to /counter-notifications
directly
public class CounterHub : Hub
{
public const string HubUrl = "/counter-notifications";
public const string CounterUpdatedMethod = "CounterUpdated";
public override Task OnConnectedAsync()
{
Console.WriteLine("/counter-notifications-{0} connected", Context.ConnectionId);
return base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? e)
{
Console.WriteLine("{0} disconnected", Context.ConnectionId);
await base.OnDisconnectedAsync(e);
}
}