65.9K
CodeProject is changing. Read more.
Home

.NET Core Razor pages (MVC) SignalR Client Error Message "connection disconnected with error 'websocket is not in the Open state'" Handling

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2 votes)

Mar 19, 2024

CPOL

1 min read

viewsIcon

4429

SignalR JavaScript client error: "websocket not in Open state" resolved

Introduction

It's quite a common issue to face a thrown error by SignalR JavaScript client "websocket is not in the Open state". Although it may be due to different reasons, one of them is described here.

Background

Researching on the internet for hours and chatting with ChatGPT didn't end up with a solution for my scenario. Finally, I resolved the problem by lots of analyzing, debugging, creating prototype projects, etc. So here is one of the reasons of "websocket is not in the Open state" error message.

Using the Code

Usually, you have the following code in JavaScript side of the Razor pages to implement SignalR client:

<script src="~/js/signalr/dist/browser/signalr.js"></script>

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

connection.start().then(function () {
 document.getElementById("sendButton").disabled = false; 
}).catch(function (err) {
 return console.error(err.toString()); 
}); 

The connection.start() method throws that "...websocket is not in the Open state".

There is nothing wrong with the code itself, it's just the wrong spot it is placed on. Usually, developers place it inside the razor page's @section Scripts {} block, where the whole JavaScript section goes to. Razor and MVC Frameworks, especially when dealing with complex applications with multiple scripts and libraries, load numerous libraries or scripts which are potential conflicts for the SignalR.

So placing JavaScript code inside a <script> block within the <head> section or at the end of the <body> section of your HTML page is typically the recommended approach to avoid interference with other scripts or libraries.

When I moved SignalR client side code outside of the @section Scripts {}, my SignalR connection was successfully established!

<script src="~/js/signalr/dist/browser/signalr.js"></script>
<script src="~/js/signalrClient.js"></script>

@section Scripts {
   <script>
     ...........
   </script>
}

where signalrClient.js is the js code for SignalR client. Example:

"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

//Disable the send button until connection is established.
document.getElementById("sendButton").disabled = true;

connection.on("ReceiveMessage", function (user, message) {
    var li = document.createElement("li");
    document.getElementById("messagesList").appendChild(li);
    // We can assign user-supplied strings to an element's textContent because it
    // is not interpreted as markup. If you're assigning in any other way, you 
    // should be aware of possible script injection concerns.
    li.textContent = `${user} says ${message}`;
});

connection.start().then(function () {
    document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
    return console.error(err.toString());
});

document.getElementById("sendButton").addEventListener("click", function (event) {
    var user = document.getElementById("userInput").value;
    var message = document.getElementById("messageInput").value;
    connection.invoke("SendMessage", user, message).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});

Note, you can't access page Model properties via @Model.MyProperty in signalrClient.js file as this code is outside of the framework's Section block.

That's it! Hope it helps you to save some time in dealing with SignalR implementation. Happy coding!

History

  • 19th March, 2024: Initial version