0
我似乎有一个问题,从使用SignalR的控制器动作发送警报(Toast)消息。除非在发送呼叫后添加Thread.Sleep()
,否则我从不会看到该消息。不可避免地,发送呼叫发生在return View()
之前,因此我想像一下,在前一个视图中,警报在毫秒内可见,直到新的视图被服务。从控制器动作发送SignalR警报消息
我的第一个粗略的解决方案是使用计时器继续发送消息,直到得到确认。
该解决方案很臭。我还可以做些什么?我可以让'接收'页面轮询服务器,看看它们是否有任何警报,但是这打破了SignalR的目的。
但是,然后,也许SignalR不适合我的情况,我应该只发送警报作为模型上的JSON字符串。
从Login
行动:
....
//ModelState.AddModelError("", "Invalid login attempt.");
AlertsHub.ShowClientAlert(new Alert(AlertLevel.Error, "Invalid login attempt."));
return View(model);
集线器:
public class AlertsHub : Hub
{
private static Alert pendingAlert;
static Timer pollTimer;
internal static void ShowClientAlert(Alert alert)
{
if (pendingAlert != null)
{
return;
}
pendingAlert = alert;
pollTimer = new Timer(_ => SendAlert(pendingAlert), null, 0, 500);
}
static private void SendAlert(Alert alert)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<AlertsHub>();
context.Clients.All.ShowAlert(alert.Level.ToString(), alert.Message, alert.Title);
}
[HubMethodName("AlertReceived")]
public void AlertReceived(Guid alertId)
{
pollTimer.Dispose();
pendingAlert = null;
}
}
从JS:
var toast;
$(function() {
if (typeof toast != 'undefined' && toast != null) {
showToast(toast);
toast = null;
}
var alertsProxy = $.connection.alertsHub;
alertsProxy.client.showAlert = function(alertId, level, message, title) {
toast.alertId = alertId;
toast.level = level;
toast.message = message;
toast.title = title;
};
$.connection.hub.start()
.done(function() {
console.log('Now connected, connection ID=' + $.connection.hub.id);
})
.fail(function() {
console.log('Could not Connect!');
});
});
function showToast(toast) {
switch (toast.level.toLowerCase()) {
case "success":
toastr.success(toast.message, toast.title);
break;
...
}
alertsProxy.server.AlertReceived(alertId)
.done(function() {
console.log("Alert '" + alertId + "' acknowledged.");
})
.fail(function() {
console.log("Acknowledgement of alert '" + alertId + "' failed.");
});
}
你能分享一下相关的代码吗? (Controller + JS,如果两者兼有) –
@ PedroG.Dias目前代码处于一种不稳定的状态,但我只会展示我正在进行的实验性工作。它仍然需要很多工作。 – ProfK