Places I have been working they have banded the use of WebSockets to pushing data to the end-user, or devices. I want to delve into the concept of WebSocket introduced in HTML 5, security issues around the WebSocket model, and the best practices that should be adopted to address security issues around WebSocket.
Continue reading WebSocket Security IssuesCategory Archives: SignalR
Push Notifications
What are Push Notifications?
A notification is a message that pops up on the user’s device. Notifications can be triggered locally by an open application, or they can be “pushed” from the server to the user even when the app is not running. They allow your users to opt-in to timely updates and allow you to effectively re-engage users with customised content.
Continue reading Push NotificationsSignalR – the right way
It has been quite sometime that SignalR has been around, 2014, so why are not more people using it? First what is SignalR?
ASP.NET SignalR is a library for ASP.NET developers that makes developing real-time web functionality easy. SignalR allows bi-directional communication between server and client. Servers can now push content to connected clients instantly as it becomes available. SignalR supports Web Sockets and falls back to other compatible techniques for older browsers. SignalR includes APIs for connection management (for instance, connect and disconnect events), grouping connections, and authorisation.
For further information check https://www.asp.net/signalr
Could it because people just don’t get it or really understand what it can do, or perhaps they hit issues without realising they don’t understand the structure? Whatever the reason people are not using SignalR, I’m going to provide a useful sample application to get you off on the right footing.
There are a lot of different samples and information on how to use SignalR, but I’m always a firm believer of KISS (Keep It Simple Stupid).
There are two primary sides to SignalR, the client side and the server hubs, here I have created an MVC application with Individual User Accounts for Authentication.
First, add the SignalR NuGet package
Install-Package Microsoft.AspNet.SignalR
Then we need to map the Hubs connection to the application.
To enable SignalR in your application, create a class called Startup with the following:
using Microsoft.Owin; using Owin; using MyWebApplication; namespace MyWebApplication { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); } } }
What is important here is that app.MapSignalR() is the last to be called, and this is because any changes to the app need to be done before you call the mapping. The incorrect order got me once when we had some custom Authentication, and it was not being passed to SignalR hubs.
I won’t be going into how you go about setting up the step by step process, as this is documented in many places, and also comes in the readme.txt file as part of the NuGet package.
What I will be adding is the Authorization to the project, which is covered by Microsoft in Authentication and Authorization for SignalR Hubs.
What is important to note how the connection is handled, we are using a class called SignalRConnectionManager, and this controls the connections based on the username coming from the context and the connection id which also comes from the context.
public class SignalRConnectionManager<T> : IDisposable { private readonly ConcurrentDictionary<T, HashSet<string>> _connections = new ConcurrentDictionary<T, HashSet<string>>(); public int Count { get { return _connections.Count; } } /// <summary> /// Attempts to add the specified userid and connectionid /// </summary> public void Add(T userid, string connectionid) { HashSet<string> connections = _connections.GetOrAdd(userid, new HashSet<string>()); lock (connections) { connections.Add(connectionid); } } public IEnumerable<string> Connections(T userid) { HashSet<string> connections; if (_connections.TryGetValue(userid, out connections)) { return connections; } return Enumerable.Empty<string>(); } public IEnumerable<T> UserIds() { return _connections.Keys; } /// <summary> /// Attempts to remove a connectionid that has the specified userid /// </summary> public void Remove(T userid, string connectionid) { HashSet<string> connections; if (!_connections.TryGetValue(userid, out connections)) { return; } lock (connections) { connections.Remove(connectionid); if (connections.Count == 0) { HashSet<string> emptyConnections; _connections.TryRemove(userid, out emptyConnections); } } } #region IDisposable Support private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { _connections.Clear(); } // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. // TODO: set large fields to null. disposedValue = true; } } // This code added to correctly implement the disposable pattern. public void Dispose() { // Do not change this code. Put cleanup code in Dispose(bool disposing) above. Dispose(true); // TODO: uncomment the following line if the finalizer is overridden above. // GC.SuppressFinalize(this); } #endregion IDisposable Support }
Client Code
In my case I’m going to be looking at JavaScript within a C# MVC application, which looks like this:
<p>SignalR</p> <!--The jQuery library is required. --> <script src="~/Scripts/jquery-1.10.2.js"></script> <!--Reference the SignalR library. --> <script src="~/Scripts/jquery.signalR-2.2.3.min.js"></script> <!--Reference the auto generated SignalR hub script. --> <script src="~/signalr/hubs"></script> <!--Add script to update the page and send messages - SignalR - HeartBeat.--> <script type="text/javascript"> $(function () { // Declare a proxy to reference the hub. var heartBeat = $.connection.heartBeatHub; heartBeat.client.broadcastMessage = function (html) { $('#message').html(html).fadeIn(); }; if ($.connection.hub && $.connection.hub.state === $.signalR.connectionState.disconnected) { $.connection.hub.start() .done(function () { console.log('SignalR now connected, connection ID=' + $.connection.hub.id); heartBeat.server.send('Heart beat listening'); console.log("Heart beat started") }) .fail(function () { console.log('Could not Connect!'); }); } }); </script> <div id="message"> </div>
two important lines in this code are:
Reference the auto generated SignalR hub script
<script src="~/signalr/hubs"></script>
Declaring the proxy to reference the hub, you’ll notice the case of the letter ‘h’ is different the the C# code, this is important otherwise you will get a JavaScript error in your browser.
var heartBeat = $.connection.heartBeatHub;
Another important thing to note is that you should only start the hub once, no matter how many SignalR endpoints you have, and you place the listening code within the done section of hub, I’ve commented out another listening hub in this sample code:
if ($.connection.hub && $.connection.hub.state === $.signalR.connectionState.disconnected) { $.connection.hub.start() .done(function () { console.log('SignalR now connected, connection ID=' + $.connection.hub.id); heartBeat.server.send('Heart beat listening'); console.log("Heart beat started") //anotherHub.server.send('Another hub listening'); }) .fail(function () { console.log('Could not Connect!'); }); }
That is it for now, a good clean SignalR project, and here it is: SignalR