65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET Core Razor Pages (MVC) SignalR 客户端错误消息“连接断开,错误为‘websocket 状态不是 Open’”的处理

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2024年3月19日

CPOL

1分钟阅读

viewsIcon

4919

SignalR JavaScript 客户端错误:“websocket 状态不是 Open”已解决

引言

遇到 SignalR JavaScript 客户端抛出“websocket 状态不是 Open”错误的情况非常常见。虽然这可能是由于各种原因造成的,但其中一种原因在此处描述。

背景

我在网上搜索了几个小时,并与 ChatGPT 聊天,但都没有找到针对我的场景的解决方案。最终,我通过大量的分析、调试、创建原型项目等方式解决了这个问题。所以,以下是“websocket 状态不是 Open”错误消息的一种原因。

Using the Code

通常,您会在 Razor Pages 的 JavaScript 端使用以下代码来实现 SignalR 客户端

<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()); 
}); 

connection.start() 方法抛出“…websocket 状态不是 Open”错误。

代码本身没有问题,只是放置的位置不正确。通常,开发者会将它放在 Razor Page 的 @section Scripts {} 块中,也就是整个 JavaScript 部分所在的位置。Razor 和 MVC 框架,尤其是在处理包含多个脚本和库的复杂应用程序时,会加载大量的库或脚本,这些可能会与 SignalR 产生冲突。

因此,将 JavaScript 代码放在 HTML 页面的 <head> 部分或 <body> 部分的末尾,通常是推荐的方法,以避免与其他脚本或库的干扰。

当我将 SignalR 客户端代码移出 @section Scripts {} 后,我的 SignalR 连接成功建立!

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

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

其中 signalrClient.js 是 SignalR 客户端的 js 代码。例如

"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();
});

请注意,由于此代码位于框架的 Section 块之外,您无法在 signalrClient.js 文件中通过 @Model.MyProperty 访问页面 Model 的属性。

就这样!希望这能帮助您节省处理 SignalR 实现的时间。祝您编码愉快!

历史

  • 2024年3月19日:初始版本
© . All rights reserved.