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