Running SignalR on Mono

Posted by Filip Ekberg on 10 Dec 2012

If you are one of those people, just like I am, that still use Linux for hosting despite that you love and only do .NET development; this is something extremely awesome. Ever since I started using SignalR I've wanted to host it on my own servers but all of them run on Linux with Mono and Apache. When David Fowler tweeted a couple of days ago that he was working on getting SignalR working on Mono; I had fireworks in my belly!

When I later told him that I actually run "real" web stuff on Linux with Mono and Apache, I was asked if I wanted to try get SignalR working on Mono! I love working on Windows so ideally I want to build and test stuff on my Windows development machine and then deploy to one of the Linux servers that uses Mono and Apache. The server that I got this running on is running Apache 2.2.14 and Mono 2.11.

tl;dr: You just need to compile the SignalR dev branch and use those libraries. Upload to a host that already runs Mono and Apache!

Preparing SignalR

The first thing that David instructed me to do was to clone the git repository and grab the latest dev-branch. In the future I expect that this work flow will change a bit, but for now this is how you do it.

Fire up you Git Bash and write the following in order:

  1. clone https://github.com/SignalR/SignalR.git
  2. cd SignalR
  3. git checkout dev
  4. git submodule init
  5. git submodule update
  6. build.cmd

After a while when the project has finished building, you should see something like this:

Since this is the dev branch some things have changed from what you might have seen before. For instance Microsoft.AspNet.SignalR.Hosting.Common.dll isn't there anymore check inside src\Microsoft.AspNet.SignalR.SystemWeb\bin\Debug for the libraries that you will need to use. The Hosting library gave you the RoutingExtensions which is now moved to SystemWeb

Getting Persistent Connection to work

Now that SignalR is compiled and ready to be tested, we can create a new empty web project for .NET 4.0. Since I tried this on Mono 2.11 I am using .NET 4.0!

Let's get the most basic thing working; the persistent connection. The idea here is that we want to get the broadcast demo that is available on the SignalR Wiki page working. I also showed this in my latest screencast about SignalR.

First we need to add the references to the SignalR libraries that we just compiled and set them to be copied locally.

As you can see the references are from src\Microsoft.AspNet.SignalR.SystemWeb\bin\Debug.

Before we start coding, we can add the JavaScript which you can find in src\Microsoft.AspNet.SignalR.Client.JS\bin. Now we can do just as the Wiki page instructs us to do.

Add a class called MyConnection with the following content:

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

public class MyConnection : PersistentConnection 
{
    protected override Task OnReceivedAsync(IRequest request, string connectionId, string data) 
    {
        // Broadcast data to all clients
        return Connection.Broadcast(data);
    }
}

You will also need to add a Global.asax file with a route added:

using System;
using System.Web.Routing;
using Microsoft.AspNet.SignalR;

namespace MonoTesting
{
    public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            RouteTable.Routes.MapConnection<MyConnection>("echo", "echo/{*operation}");
        }
    }
}

Finally we can add a HTML file with the following content:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <script src="http://code.jquery.com/jquery-1.7.min.js" type="text/javascript"></script>
    <script src="jquery.signalR.js"></script>
    <script type="text/javascript">
        $(function () {
            var connection = $.connection('/echo');

            connection.received(function (data) {
                $('#messages').append('<li>' + data + '</li>');
            });

            connection.start().done(function () {
                $("#broadcast").click(function () {
                    connection.send($('#msg').val());
                });
            });

        });
    </script>

    <input type="text" id="msg" />
    <input type="button" id="broadcast" value="broadcast" />

    <ul id="messages">
    </ul>
</body>
</html>

Now we're ready to compile and run it!

Running it on Apache with Mono

I'm not going to cover how to set up Apache with Mono, there are plenty of tutorials for that out there already. However, all I did was create a new virtual host that is Mono enabled and I copied the content over to that folder and it just works!

Converting a SignalR application to run on Mono and Apache

As you might have seen in my screencast on SignalR I've created a Tic-Tac-Toe game, which is also available on github. I downloaded the master and opened up the solution to make the changes needed to get it running on Mono and Apache.

First thing that needs to be done here is to change the Target framework to .NET Framework 4 instead of 4.5. This will cause some issues with the SignalR version that was grabbed from NuGet. So you will also need to remove those before proceeding.

Just as we did with the persistent connection, we need to add the libraries that we compiled and also add the new javascript:

Now we need to replace the SignalR script that we are using in the client HTML to the new script file that we just added to the solution. In the case of Tic-Tac-Toe we replace:

<script src="/Scripts/jquery.signalR-1.0.0-alpha2.min.js" type="text/javascript"></script>

with

<script src="Scripts/jquery.signalR.js"></script>

Finally if you haven't already, force long polling for the time being:

$.connection.hub.start({ transport: 'longPolling' });

Compile and run it locally to test that it still works then upload to your favorite Mono hosting! There's a live demo available at signal.fekberg.com that looks like this (and as you can see it runs on Mono + Apache!):

Need an introduction to SignalR?

comments powered by Disqus