Tuesday, April 10, 2012

SignalR push notifications to all browser instances of single authenticated user

I'm working on an application that needs to notify the user when they receive a new notification. The application will be hosted on Azure and will be .NET MVC 3 (probably not important, but FYI). I also


Notifications are saved in an MSSQL db (2008) and have an IsRead field. Notifications are generated from various user and server actions. Based on user preferences, some notifications will be created with IsRead == false.


I have 2 different scenarios that I feel that SignalR will be perfect in handling, I just need a little guidance:



  1. User has several windows open browsing the site and a new notification row is added, assigned to that user, with IsRead == true

    • I would like all the specific user's browser instances to have a specific js function called to reveal a notification pop up


  2. User has several windows open and clicks on the notification pop up.

    • I would like all the specific user's browser instances to have a specific js function called to remove the notification pop up. (Only the specific browser instance that handled the click will also execute a js function to show the notification details)




What I've tried






For the first scenario, I think that the same action that causes the notification to be written to the database will have the responsibility of notifying all the user's browser instances.


The second scenario would be similar in that by clicking on the pop up, a server endpoint would be called via Ajax and that endpoint would update the db to mark the notification as read, and then notify all the other user's browser instances.


If there is a way to keep track of SignalR Clients based on ASP.NET Forms Authentication Username, then I think that will work in solving the problems in both scenarios.


TL;DR






My main problem is that I don't know how to signal all of one specific user's browser instances using SignalR. I was thinking about making a group based on the ASP.NET Forms Authentication Username. Would this work? Is there an easier way that is built into SignalR that handles this?


 
 

Answer:


Your call to make a Group with the User Name as a key is good one and I think it's the most fast to implement. You can call a function every time a page loads(and ConnectionId is changed) by subscribing to the:
$.connection.hub.start(function () {
    yourHub.register();
});
And in the hub in Code behind:
public void Register()
{
    AddToGroup(username);
}
And when you want to refresh the client's screens you do:
Clients[username].refreshClientScreen();
Where refreshClientScreen() is your javascript function which does the job of hiding the notification in the browser.
Another way to do it is to check the ConnectionId on every request and have a place where you register and persist the user's connections on the server. When you need to update them you can use this code on each one of them:
Clients[ConnectionId].refreshClientScreen();
You can find the ConnectionId in the Context object of a Hub.
I think the second approach is harder to implement because you have to manage where you'd save theConnectionId-s and subscribe to the Disconnect event by implementing IDisconnect so you can keep your ConnectionId-s list up to date, so I'd choose the first approach - the one with the groups.

No comments:

Post a Comment