SignalrR transport from WASM

98 Views Asked by At

I have a hosted .net 7 Blazor WASM project, that uses a SignalR connection with the host. The communication is established, and it works. So far so good. What I have noticed, is that although a WebSocket connection is established, the communication is still using long-poll + calls. Not even SSE. This is the dev environment, with both the client and the server running on the same machine - so nothing is blocking WS. One detail: the AccessTokenProvider is set for the connection options.

Why is this? Is this somehow related to the dev env or WASM? Or is this what I should expect for the prod as well?

[Update 23-12-27] Following @JasonPan's advice, I added client side logging. The result: enter image description here (btw: browser is Edge... not supporting SSE???) Error expanded: enter image description here

Server side log:

enter image description here

From what I see, the connection is not refused, only challenged . And the actual WS connection has the token requested.

enter image description here

This is the client code:

enter image description here

And server:

enter image description here

enter image description here

enter image description here

enter image description here

1

There are 1 best solutions below

5
On

I have test it and haven't facing this issue. So please kindly check via steps below.

1. Check you Server side setting, if there any longpolling settings like below

 app.MapHub<YourHub>("/yourHub", options =>
 {
     options.Transports = HttpTransportType.LongPolling;
 });

2. Check your client side settings, if has some code like below

hubConnection = new HubConnectionBuilder()
    .WithUrl("https://localhost:7262/mainHub?uid=jason_WASM&sid=test&api-key=112233", options =>
    {
        options.Transports = HttpTransportType.LongPolling;
    })
    .Build();

3. Check where your SignalR Server is deployed?

If you deploy IIS on Windows 10/11, the default number of websocket connections is 10, so you may experience an over-the-limit connection.

My Test Result

SignalR.razor

@page "/signalr"

<PageTitle>SignalR</PageTitle>

@inject IJSRuntime JSRuntime
@using Microsoft.AspNetCore.SignalR.Client
@implements IDisposable

<div>
    <input type="text" @bind="userToSend" placeholder="User Name" />
    <input type="text" @bind="messageToSend" placeholder="Message" />
    <button @onclick="SendMessage">Send Message</button>
</div>

@if (messages != null)
{
    <ul>
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
}

@code {
    private HubConnection hubConnection;
    private List<string> messages = new List<string>();
    private string userToSend;
    private string messageToSend;

    protected override async Task OnInitializedAsync()
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl("https://localhost:44310/mainHub?uid=jason_WASM&sid=test&api-key=112233", options =>
            {
                // Configure options here if needed
            }).ConfigureLogging(logging =>
            {
                logging.SetMinimumLevel(LogLevel.Debug);
                logging.AddProvider(new BrowserConsoleLoggerProvider(JSRuntime));
            })
            .Build();

        hubConnection.On<string, string>("Chat_ReceiveMessage", (user, message) =>
        {
            var formattedMessage = $"{user}: {message}";
            messages.Add(formattedMessage);
            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

    private async Task SendMessage()
    {
        if (hubConnection != null && hubConnection.State == HubConnectionState.Connected)
        {
            await hubConnection.SendAsync("Chat_SendMessageToAll", userToSend, messageToSend);
        }
    }

    public bool IsConnected => hubConnection?.State == HubConnectionState.Connected;

    public void Dispose()
    {
        _ = hubConnection?.DisposeAsync();
    }
}

BrowserConsoleLogger.cs

using Microsoft.JSInterop;

namespace BlazorWASM
{
    public class BrowserConsoleLogger : ILogger
    {
        private readonly string _categoryName;
        private readonly IJSRuntime _jsRuntime;

        public BrowserConsoleLogger(string categoryName, IJSRuntime jsRuntime)
        {
            _categoryName = categoryName;
            _jsRuntime = jsRuntime;
        }

        public IDisposable BeginScope<TState>(TState state) => null;

        public bool IsEnabled(LogLevel logLevel) => true;

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            var message = $"{logLevel}: {_categoryName}[{eventId.Id}] {formatter(state, exception)}";
            _jsRuntime.InvokeVoidAsync("console.log", message);
        }
    }
}

BrowserConsoleLoggerProvider.cs

using Microsoft.JSInterop;

namespace BlazorWASM
{
    public class BrowserConsoleLoggerProvider : ILoggerProvider
    {
        private readonly IJSRuntime _jsRuntime;

        public BrowserConsoleLoggerProvider(IJSRuntime jsRuntime)
        {
            _jsRuntime = jsRuntime;
        }

        public ILogger CreateLogger(string categoryName)
        {
            return new BrowserConsoleLogger(categoryName, _jsRuntime);
        }

        public void Dispose() { }
    }
}

Then you can check which protocol used in browser develop tools Concole windows.

enter image description here