How to use SignalR cross domain

Hackered
Tuesday, September 9, 2014
by Sean McAlinden

I recently had requirement for a relatively low latency real time UI where the data was accessible via endpoints on another domain. Luckily I had the option for the endpoints to allow cross origin resource sharing (CORS) with the client domain and could  also add a little code here and there. Whilst I could use Ajax to poll the endpoints, there is an awesome technology that would achieve this in a much more efficient and elegant way... I am of course talking about SignalR.

Cross domain SignalR: Surely this can't be done!

Ok, clearly it can or this post would be pretty useless. Whilst this is definitely not a general introduction to SignalR, I will have to put a little code on the page to show how to perform CORS requests. So lets deal with the 2 halves of this mission:

1. The server with the data

Create the project

Create a standard MVC project and don't change the authentication settings, this is important only because it creates a StartUp.Auth class which we're going to use later on. Install SignalR via nuget.

Enable CORS

We must enable CORS on the server so we can call it cross domain. Install Microsoft.Owin.Cors via nugetAs this isn't a tutorial on CORS we're going to do a quick and dirty implementation... alter the ConfigureAuth method in the Startup.Auth.cs file in the AppData folder to look like the following:

public void ConfigureAuth(IAppBuilder app)
{
    app.UseCors(CorsOptions.AllowAll);
    app.MapSignalR(new HubConfiguration { EnableJSONP = true });
}

The main thing to notice is that JSONP has been enabled for the SignalR Hubs.

Create a Hub

First lets create a SignalR hub that does something useful such as returning the current time:

using System;
using System.Threading;
using Microsoft.AspNet.SignalR;

namespace SignalRCrossDomain.Hubs
{
    public class CrossDomainHub : Hub
    {
        public void StartTimer()
        {
            while (true)
            {
                Clients.All.showTime(DateTime.UtcNow.ToLongTimeString());
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
        }
    }
}

The only interesting thing here really is the fact we derive from Hub, however this is just standard SignalR.

Kick it off

That's all we need for the server so feel free to launch the site (you'll need the url and port for the next bit). Note: for a great test, you could also load it into Azure as an azure website.

2. The client website

Create the project

Create a standard MVC project. Install SignalR via nuget.

Create a container for displaying our clock

Anywhere on the home index page, create the following div:

Create the cross domain script

Add the following at the bottom of the home index page. Replace the http://localhost:1234 with the url of your server app.

@section scripts
{
    <script type="text/javascript">
        $.getScript('http://localhost:1234/Scripts/jquery.signalR-2.1.1.min.js', function () {
            $.getScript('http://localhost:1234/signalr/hubs', function () {
                $.connection.hub.url = 'http://localhost:1234/signalr';
                var myHub = $.connection.crossDomainHub;
 
                myHub.client.showTime = function(dateTimeFromServer) {
                    $('#dateTime').html(dateTimeFromServer);
                }
 
                $.connection.hub.start().done(function () {
                    myHub.server.startTimer();
                });
            });
        });
    </script>
}

What's going on?

  1. We load the jquery signalR script from the remote website
  2. We then load the signalr hubs script from the remote website
  3. We set the hub url to the remote website

After that is it just some standard signalR.

  1. Once the start function is called (i.e signalR connection has been established) call the startTimer method on the remote server hub
  2. Remote server pushes the current time every second to the showTime function which updates the DOM on the client website

That's your lot

So, if you need it, it is relatively simple to perform cross domain signalR