2017-02-14 32 views
3

私のWebサイト(ASP.NET MVC)に通知システムを設定しています。ステートレスでなければならないので、私はSignalRを選んだ。 通知はサーバー側からのみ発生し、リアルタイムではなく新しいページを更新した後に表示したいとします。通常はトリガされ、クライアントに通知を送信し、リダイレクトまたはビューを表示するActionResultです。IEとFirefoxでPOSTリクエストでSignalRが切断されました

  1. をサーバがクライアントにメッセージを送信します。

    これは、進行する方法です。

  2. クライアントは、ブラウザのローカルストレージに保存します。
  3. リダイレクト後、ローカルストレージからの通知が表示されます。私は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

    でSignalR 2.2.1を使用してい

@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"); 
    } 
} 

それはクロームと魔法のようにではなく、マイクロソフトのエッジとFirefoxで動作します。

マイクロソフトエッジ動作: 接続が行われますが、クライアントがメッセージを取得していません。

- >注意:私のアプリをデバッグし、通知を送信してから十分に待っていると、メッセージが正常に取得されます。 それは...メッセージを送信することは、接続が失われ、クライアントがメッセージを取得することはできませんので、ページがリフレッシュされ、時間がかかりすぎるように思わ

Firefoxの動作:(POSTを送信する=) 私はボタンをクリックするたびに、接続が失われ、もちろんクライアントはメッセージを受け取ることができません。なぜそれがそれを行うのか分かりません!

私がajax POSTを使用している場合、正常に動作しますが、それは私が探しているものではありません。

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

アップデート2017年2月16日: 残念ながら私たちは、このライブラリを持つ単純なHTTP POSTを使用することはできません、それが機能するために、AJAX POSTである必要があります正しく。 彼らのgitで答えを得ました:https://github.com/SignalR/SignalR/issues/3869#issuecomment-280074464

+0

こんにちは、私もfirefoxと同じ問題がありました。送信(POST)機能を送信した後、signalRはクライアントの新しいconnectionIDを作成します。私が修正したのはボタンを送信するのではなく、AJAX POSTを使う方法です。 – Mark

+0

こんにちは、ご意見ありがとうございます。私が唯一の人ではないことを聞いてうれしいですが、残念ながらPOSTの代わりにajax投稿を使用することはできません:/ – Barbara

+0

http://stackoverflow.com/questions/39197967/c-sharp-mvc-send-message-withここからサーバーから発信者へのシグナルが私の質問でした。私は多くのことを試してきて、何も来なかった。 AJAX POSTは私が得た唯一の解決策でした。なぜあなたはajax投稿を使用できないのですか? – Mark

答えて

0

私たちはこの問題にも対処しなければなりませんでした。

解決策は次のとおりです。新旧のconnectionIdを把握する。 は、コントローラ内部:

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

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

我々は古いConnectionId年代のための犠牲キャッシュとして期限切れMemoryCacheを導入しました。

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; 
} 

、あなたは新しいと古い接続IDを提供する必要がありますハブの起動時に

関連する問題