我在我的网站上设置了一个通知系统(ASP.NET MVC)。它需要无国籍,所以我选择了SignalR。 通知仅来自服务器端,我想在刷新新页面后显示,而不是实时显示。通常它是一个ActionResult,它将被触发并向客户发送通知,然后重定向或显示视图。
这是它的进展方式:
我使用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行为: 已建立连接,但客户端未收到消息。
- &GT;注意:如果我调试我的应用并在发送通知后等待足够长时间,我会成功收到消息。 似乎发送消息需要太长时间,然后页面刷新,因此连接丢失,客户端无法获取消息...
Firefox行为 每次我点击按钮(=发送POST),连接都会丢失,当然客户端无法获取消息。我不知道为什么会这样做!
如果我使用ajax POST,它运行良好,但这不是我正在寻找的。 p>
############################################### ###############
2017年2月16日更新: 不幸的是我们不能在这个库中使用简单的http POST,它必须是ajax POST才能正常工作。 得到了他们的git答案:https://github.com/SignalR/SignalR/issues/3869#issuecomment-280074464
答案 0 :(得分:0)
我们也必须处理这个问题。
解决方案是:跟踪新旧connectionIds。 在控制器内:
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;
}
当然,您需要在集线器启动时向服务器提供新的和旧的连接ID。