Note: A few people have experienced problems running the sample application. Make sure that NServiceBus.Host.exe is set run when debugging (Project Properties > Debug > Start External Program). If all else fails, try removing then re-adding the NServiceBus nuget packages or consult this post.
A challenging aspect of using asynchronous messaging in web applications is how to update the UI. Since HTTP is stateless we normally have to resort to some kind of polling mechanism to check for updates on the server.
SignalR is particularly interesting as it allows us to “push” notifications down to the client by virtue of a persistent connection (that can be automatically recreated if it is broken).
This seems like the perfect solution for notifying the client from within our NServiceBus message handlers, so I thought I’d give it a go.
You can download the full source code for this example at https://bitbucket.org/retroviz/nservicebussignalrdemo.
The application is extremely basic so prepare to be underwhelmed, but it does show how the two technologies can work well together. The concept is fairly simple - add message handlers to your web application that broadcast the results via SignalR.
In the solution we have:
- Commands
- Events
- Terminal (console app that sends commands to the Worker)
- Worker (this is where the commands are processed and events are raised)
- Web - This is where we subscribe to our events and send out notifications via SignalR.
If you’ve used NServiceBus before then this is all pretty standard stuff. Inside the web project we have the following handler:
public class MessagePostedEventHandler : IHandleMessages<MessagePostedEvent>
{
public void Handle(MessagePostedEvent message)
{
var clients = Connection.GetConnection<EventStream>();
clients.Broadcast(message.Message);
}
}
Here we get a reference to the “EventStream” SignalR connection and broadcast the contents of our event message. The EventStream class is a simple handler that inherits from PersistentConnection:
public class EventStream : PersistentConnection
{
}
On the client it’s just as simple. We create a reference to our handler on the server, register a callback for when messages are broadcast, and open up a connection:
$(function () {
var connection = $.connection('EventStream.ashx');
connection.received(function (data) {
$('#messages').append('<li>' + data + '</li>');
});
connection.start();
});
This gives us the following workflow:
- Terminal sends command to Worker
- Worker processes command and publishes event
- Web receives event and pushes to client
I can tell you’re impressed!