SignalR brought developers an easier way to build real-time, very responsive web applications. But, how does it play with other available technologies? I took a couple of days to implement a very common scenario needed in every Enterprise Application: A DataTable to do CRUD operations persisting changes on a database.
My initial thought was this is going to be a trivial task, I have done DataTables a few times in the past. Then, I realized the real-time model with many concurrent users introduces a few challenges.
Before going through details, here is a screenshot of what I accomplished: A DataTable where multiple users are collaborating on the add/edit/delete of its contents! When user 1 edits David Fowler, the Delete and Edit buttons disappear for David in the browsers of users 2, 3, and 4. When user 2 edits Gustavo Armenta, the Delete and Edit buttons disappear for Gustavo in the browsers of users 1, 3, and 4. When user 1 finishes editing David Fowler, Delete and Edit buttons reappear on all browsers.
HTML Content needs to update every time I receive a SignalR message
My SignalR client receives a JSON message indicating there is a new friend. Now I need to update my html table with the new content. AngularJS plays beautiful in this scenario as I only have to add a row in my existing array (array.push(item)) and refresh content (scope.apply()).
// SignalR Events hubProxy.client.add = function (friend) { console.log("client.add(" + JSON.stringify(friend) + ")"); $scope.friends.push(friend); $scope.$apply(); } |
Broadcast SignalR messages when user modifies data
The previous code works well when the server pushes data to client. Now, let’s handle the case when the user is pushing changes.
// AngularJS Events $scope.add = function () { hubProxy.server.add({ Name: $scope.add_friend.Name }); $scope.add_friend.Name = ""; } |
Concurrent users competing to edit the same row
What to do when two or more users want to edit the same row? You could allow them to edit simultaneously and the last one to save changes win. You could track versions and let the first user save changes and fail for other users as they need to refresh to the latest version before submitting changes. You could lock the row and allow only a single user to make changes, once he finishes other users can take the lock.
In this sample, I have followed the lock approach with a few more considerations.
- User can only lock one row at a time
- Release lock in row when user completes the update or user disconnects temporarily or permanently
- Handle race condition when multiple users try to edit same row
Most of the magic happen on the SignalR Hub. OnConnected() returns both a list of items and a list of locks. OnReconnected() simply refreshes the state as if connecting for the first time. OnDisconnected releases the lock I had taken so other active users can edit the row.
private static ConcurrentDictionary<string, int> _locks = |
Then, AngularJS provides a very clear mapping between HTML content and conditional logic using ”ng-repeat” and “ng-show”. Look how easy is to make UI decisions based on the current state of JSON objects bound to $scope.
<tr ng-repeat="friend in friends | orderBy:predicate"> <td><button name="deleteButton" ng-click="delete(friend)" |
Things to improve in this sample
- Improve UI Look & Feel
- Play well with other datatypes like number, currency, date
- Display validation and error messages
- Support SignalR scaleout
Source Code
https://github.com/gustavo-armenta/SignalR-JS-HTML
Feedback
Have you seen other HTML/JS/SignalR controls out there? Please share the links!
I have only seen this one:
http://mvc.syncfusion.com/demos/ui/grid/productshowcase/signalr#
0 comments