2017-02-14 7 views
3

Я настраиваю систему уведомлений на своем веб-сайте (ASP.NET MVC). Он должен быть апатридом, поэтому я выбрал SignalR. Уведомления поступают только на стороне сервера, и я хочу показать его после обновления новой страницы, а не в режиме реального времени. Обычно это ActionResult, который запускается и отправляет уведомление клиенту, а затем перенаправляет или показывает представление.SignalR отключен с POST-запросом на IE и Firefox

Это способ, которым это происходит:

  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 расслоение плотной

<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 Краю и Firefox.

Microsoft Edge поведение: Соединение выполнено, но клиент не получает сообщение.

-> Примечание: если я отлаживаю приложение и жду достаточно долго после отправки уведомления, я получаю сообщение успешно. кажется, что отправка сообщения занимает слишком много времени, то страница освежает так теряется связь и клиент не может получить сообщение ...

Firefox поведение: Каждый раз, когда я нажимаю кнопку (= отправка POST), соединение потеряно, и, конечно, клиент не может получать сообщения. Я понятия не имею, почему это так!

Если я использую ajax POST, он работает хорошо, но это не то, что я ищу.

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

обновление 16 февраля 2017: к сожалению, мы не можем использовать простой HTTP POST, с этой библиотекой, она должна быть Аякса POST для того, чтобы работать должным образом. Получил ответ на свой git: https://github.com/SignalR/SignalR/issues/3869#issuecomment-280074464

+0

Привет, барбара, у меня была такая же проблема с firefox. Похоже, что после отправки функции submit (POST) signalR создаст новый идентификатор соединения для клиента. способ, который я исправил, использует кнопку AJAX POST, а не кнопку отправки. – Mark

+0

Привет, Марк, спасибо за ваш комментарий. Рад слышать, что я не единственный ... но я не могу использовать пост ajax вместо POST, к сожалению:/ – Barbara

+0

http://stackoverflow.com/questions/39197967/c-sharp-mvc-send-message-with -signalr-from-server-to-caller здесь был мой вопрос. Я много пробовал и ничего не получал. AJAX POST был единственным решением, которое я получил. почему вы не можете использовать пост ajax? – Mark

ответ

0

Нам также пришлось иметь дело с этой проблемой.

Решение: отслеживать новые и старые соединения. Внутри контроллера:

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 от старого и заботиться о потенциальных НЕСКОЛЬКИХ изменений, как это:

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


    return connectionId; 
} 

Конечно, вы должны предоставить новые и старые соединения иды к сервер при запуске концентратора.

 Смежные вопросы

  • Нет связанных вопросов^_^