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





5.00/5 (2投票s)
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日:初始版本