gpt4 book ai didi

javascript - SignalR 在 IE 和 Firefox 上与 POST 请求断开连接

转载 作者:太空宇宙 更新时间:2023-11-03 15:08:31 25 4
gpt4 key购买 nike

我正在我的网站上设置一个通知系统 (ASP.NET MVC)。它需要是无状态的,所以我选择了 SignalR。通知仅来自服务器端,我想在刷新新页面后显示它,而不是实时显示。通常它是一个将被触发并向客户端发送通知,然后重定向或显示 View 的 ActionResult。

这是它进行的方式:

  1. 服务器向客户端发送消息。
  2. 客户端将其存储到浏览器本地存储。
  3. 重定向后,它会显示来自本地存储的通知。

我将 SignalR 2.2.1 与 JQuery 1.9.1 结合使用

NotificationHub.cs

[HubName("notificationHub")]
public class NotificiationHub : Hub
{
public static void Send(string connectionId, string name, string message)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificiationHub>();
hubContext.Clients.Client(connectionId).sendNotification(name, message);
}
}

_Layout.cshtml js

<script>
getNotificationStack = function () {
if (localStorage.getItem("notifications") != null) {
return JSON.parse(localStorage.getItem("notifications"));
}
return [];
}

checkNotification = function () {
var notificationStack = getNotificationStack();

var count = notificationStack.length;
for (var i = 0; i < count; i++) {
window.alert(notificationStack.pop());
}
localStorage.removeItem("notifications");

}

initHubConnection = function () {
// Reference the auto-generated proxy for the hub.
$.connection.hub.logging = true;

var notification = $.connection.notificationHub;
notification.client.sendNotification = function (name, message) {
var notificationStack = getNotificationStack();
notificationStack.push(name + ": " + message);
localStorage.setItem("notifications", JSON.stringify(notificationStack));
};

// Start the connection.
$.connection.hub.start().done(function () {
// allows to send notification to one tab through connectionId
document.cookie = "connectionId=" + $.connection.hub.id;
});
}

$(function () {
checkNotification();
initHubConnection();
});
</script>

MyView.cshtml

@using (Html.BeginForm("TestSendNotification", "Home", FormMethod.Post))
{
<input type="submit" value="Press that button"/>
}

HomeController.cs

public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}

public ActionResult TestSendNotification()
{
NotificiationHub.Send(Request.Cookies["connectionId"].Value, "Info", "Oh you pressed that!");

return RedirectToAction("Index", "Home");
}
}

它在 Chrome 中的效果很好,但在 Microsoft Edge 和 Firefox 中却不行。

Microsoft Edge 行为:已建立连接,但客户端未收到消息。

-> 注意:如果我调试我的应用程序并在发送通知后等待足够长的时间,我就会成功收到消息。好像发送消息时间过长,然后页面正在刷新导致连接丢失,客户端无法接收到消息...

Firefox 行为:每次单击按钮(= 发送 POST)时,连接都会丢失,客户端当然无法接收消息。我不知道为什么会这样!

如果我使用的是 ajax POST,它运行良好,但这不是我想要的。

############################################# ###############

2017 年 2 月 16 日更新:不幸的是,我们不能对这个库使用简单的 http POST,它必须是 ajax POST 才能正常工作。在他们的 git 上得到了答案:https://github.com/SignalR/SignalR/issues/3869#issuecomment-280074464

最佳答案

我们也必须处理这个问题。

解决方案是:跟踪新的和旧的 connectionIds。在 Controller 内部:

public ActionResult RegisterConnectionId(string newConnectionId, string oldConnectionId)
{
Session["SignalRConnectionId"] = newConnectionId;

if(!string.IsNullOrEmpty(oldConnectionId))
RemapConnectionId(newConnectionId, oldConnectionId);
}

我们引入了一个过期的 MemoryCache 作为旧 ConnectionId 的受害者缓存。

public void RemapConnectionId(string newConnectionId, string oldConnectionId)
{
if(newConnectionId != null && newConnectionId != oldConnectionId)
MemoryCache.Default.Set(oldConnectionId, newConnectionId, ...);
}

您可以从旧的 ConnectionId 获取当前的 ConnectionId 并像这样处理潜在的 MULTIPLE 更改:

public string ResolveConnectionId(string connectionId)
{
while (!IsEligibleConnectionId(connectionId) && !string.IsNullOrEmpty(connectionId))
connectionId = MemoryCache.Default.Get(connectionId) as string;


return connectionId;
}

当然,你需要在 hub 启动时向服务器提供新的和旧的连接 ID。

关于javascript - SignalR 在 IE 和 Firefox 上与 POST 请求断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42231774/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com