pusher / pusher-websocket-dotnet

Pusher Channels Client Library for .NET
MIT License
111 stars 113 forks source link

Blazor WASM unable to connect #146

Closed silentdevnull closed 1 year ago

silentdevnull commented 1 year ago

Hello,

I'm trying to connect with the dotnet pusher client in blazor wasm. I'm getting the following error.

I have a working version in react using the pusher-js library so I know settings work.

System.Net.Sockets is not supported on this platform.

Code:

protected override async Task OnInitializedAsync()
    {
        var pusher = new Pusher("KEY", new PusherOptions
        {
            Cluster = "us2",
            Encrypted = true
        });
        pusher.ConnectionStateChanged += StateChanged;
        pusher.Error += ErrorHandler;

        void StateChanged(object sender, ConnectionState state)
        {
            Console.WriteLine("Connection state: " + state.ToString());
        }

        void ErrorHandler(object sender, PusherException error)
        {
            Console.WriteLine("Pusher error: " + error.ToString());
            Console.WriteLine("Pusher Error Message: " + error.Message.ToString());
        }

        try
        {
            await pusher.ConnectAsync().ConfigureAwait(false);
    // pusher.State will be ConnectionState.Connected
        }
        catch(Exception error)
        {
    // Handle error
        }
    }

Browser Console output.

Pusher error: PusherClient.OperationException: An unexpected error was detected when performing the operation 'Pusher.ConnectAsync': blazor.webassembly.js:1 System.Net.Sockets is not supported on this platform. blazor.webassembly.js:1 ---> System.PlatformNotSupportedException: System.Net.Sockets is not supported on this platform. blazor.webassembly.js:1 at System.Net.Sockets.SocketAsyncEventArgs..ctor() blazor.webassembly.js:1 at SuperSocket.ClientEngine.ConnectAsyncExtension.CreateSocketAsyncEventArgs(EndPoint remoteEndPoint, ConnectedCallback callback, Object state) blazor.webassembly.js:1 at SuperSocket.ClientEngine.ConnectAsyncExtension.ConnectAsync(EndPoint remoteEndPoint, EndPoint localEndPoint, ConnectedCallback callback, Object state) blazor.webassembly.js:1 at SuperSocket.ClientEngine.TcpClientSession.Connect(EndPoint remoteEndPoint) blazor.webassembly.js:1 at WebSocket4Net.WebSocket.Open() blazor.webassembly.js:1 at PusherClient.Connection.b__21_0() blazor.webassembly.js:1 at System.Threading.Tasks.Task.InnerInvoke() blazor.webassembly.js:1 at System.Threading.Tasks.Task.<>c.<.cctor>b__273_0(Object obj) blazor.webassembly.js:1 at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) blazor.webassembly.js:1 --- End of stack trace from previous location --- blazor.webassembly.js:1 at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) blazor.webassembly.js:1 at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) blazor.webassembly.js:1 --- End of stack trace from previous location --- blazor.webassembly.js:1 at PusherClient.Connection.ConnectAsync() blazor.webassembly.js:1 at PusherClient.Pusher.ConnectAsync() blazor.webassembly.js:1 at LotusBot.Pages.KickBot.OnInitializedAsync() in C:\source\LotusBot\LotusBotApp\src\LotusBot\Pages\KickBot.razor:line 50 blazor.webassembly.js:1 --- End of inner exception stack trace --- blazor.webassembly.js:1 Pusher Error Message: An unexpected error was detected when performing the operation 'Pusher.ConnectAsync': blazor.webassembly.js:1 Syst

benw-pusher commented 1 year ago

It appears Blazor does not support websockets, see https://stackoverflow.com/questions/61906292/how-can-i-use-socket-in-blazor-client-side.

silentdevnull commented 1 year ago

Blazor wasm does support web sockets and has been support since blazor 3.2.0 wasm beta 1 (if I remember correctly).

I have a few different production projects using web sockets in blazor wasm to send and receive messages.

This is a old demo of them supporting websockets with a echo back service.

@page "/"
@using System.Net.WebSockets
@using System.Text
@using System.Threading
@implements IDisposable
<PageTitle>Index</PageTitle>

<h1>Echo test</h1>
<h3>State: @_webSocket.State</h3>

@if (_webSocket.State == WebSocketState.Open)
{
    <form @onsubmit="@SendMessageAsync">
        Message: <input @bind="@_message" />
        <button type="submit">Send</button>
    </form>

    <pre>@_log</pre>
}

@code {
    CancellationTokenSource _disposalTokenSource = new CancellationTokenSource();
    ClientWebSocket _webSocket = new ClientWebSocket();
    string _message = "Hello, websocket!";
    string _log = "";

    protected override async Task OnInitializedAsync()
    {
        await _webSocket.ConnectAsync(new Uri("wss://ws.postman-echo.com/raw"), _disposalTokenSource.Token);
        _ = ReceiveLoop();
    }

    async Task SendMessageAsync()
    {
        _log += $"Sending: {_message}\n";
        var dataToSend = new ArraySegment<byte>(Encoding.UTF8.GetBytes(_message));
        await _webSocket.SendAsync(dataToSend, WebSocketMessageType.Text, true, _disposalTokenSource.Token);
    }

    async Task ReceiveLoop()
    {
        var buffer = new ArraySegment<byte>(new byte[1024]);
        while (!_disposalTokenSource.IsCancellationRequested)
        {
            var received = await _webSocket.ReceiveAsync(buffer, _disposalTokenSource.Token);
            if (buffer.Array != null)
            {
                var receivedAsText = Encoding.UTF8.GetString(buffer.Array, 0, received.Count);
                _log += $"Received: {receivedAsText}\n";
            }
            StateHasChanged();
        }
    }

    public void Dispose()
    {
        _disposalTokenSource.Cancel();
        _ = _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Bye", CancellationToken.None);
    }
}