Have you ever tried to solve concurrency, or at least notification of concurrency threats? Have you worked out a way to keep data flowing between the client and the server? How about multiple client-side subscribers and the server? Server-to-client notification? And, if you have, were you able to make it easily available in other projects? Easily extensible?
If you’re a .NET developer, there’s no more guessing. SignalR is your new BFF.
It’s a new web, people. We all know this. We don’t make “web pages” or even “web sites” any more. We make living, breathing applications. More and more, this also means a social aspect, and increasingly this means collaboration.
It’s my thing. I spend most of my time in Asp.Net working with the MVC Framework, so my first question is, “Does it work with MVC?”. Of course!
And it’s super simple:
- You’re going to create a project & install SignalR via NuGet
- Build your backend by creating one class that inherits from one of the SignalR base classes
- Finally, you need to wire up your view by writing a tiny bit of script on the client
How does it work? Crazy ninja magic. Covered with chocolate and ice cream. Two scoops. Let’s walk through a simple, but meaningful example (you can checkout the hello world on Github) and then revisit the interesting bits.
Let’s start by creating a new MVC4 project (all the kids are doing it) in Visual Studio 2010. I’ve called mine Mvc.SignalR.
Next, we’re going to pick the empty template because we’re not too concerned about the whole flashy starter pages and default styling.
And we’re off to the races! Let’s drop into the package manager console and install SignalR. Type the following:Install-Package SignalR
…and NuGet will do it’s magic for us, adding the required dependencies and updating our project accordingly. What else is cool there? Glad you asked! NuGet also went ahead and updated any other libraries that SignalR takes a dependency on at a higher version. Sweet! Check out your console for all the details, that’s some great stuff there.
Next, we’re going to need a controller and a view so that we have something to see. Right-click on your Controllers folder (in Solution Explorer) and click “Add –> Controller…” and create a new “HomeController”. You’ll be taken to the class, at which point you can right click on the Index method and then select “Add View…”. Again, just create an empty view called Index. Press F5 to run the app and you should see this:
Not too much going on, but we’re just getting to the great stuff. One more quick thing, we’re going to need it later, let’s stuff the client’s IP address into the ViewBag in our Index method of the HomeController.
SignalR makes things super-easy for us to create the backend bits required for the continuous communication: we only need to inherit from a single class. What we’ll do in this sample is make a page visit counting mechanism that provides live updates to viewers of the page. Original idea, and totally worth a patent. I’ll call it, “Analytics”. On we go.
The first bit is in creating a model class to record the visit. We’ll keep it simple and track only a few properties, but we’re going to take advantage of EF Code First to use as a data store. Create two classes in your Models folder, SiteVisit and SiteVisitContext. Their implementations look like this:
Note that inheriting from DbContext requires importing the System.Data.Entity namespace in the code below.
Poof! We have a database. Next, I’ve got a simple class called UserLink where we provide the function that will be accessible from the client, through SignalR. We inherit from Hub here to give us a whole bunch of “free” client-side goodness and make sure the SignalR bits know about us. Reflection is a beautiful thing.
All I’m doing here is accepting an IP address, saving it to the SiteVisits table (that we created above through EF) and then getting a record count. The interesting bit happens after we make that result message.
Now, every page in our application (that uses this layout) will have access to SignalR.
“Wait a minute!”, says the observant, kung-fu yielding developer, “Script source is /signalr/hubs? But there’s no file that corresponds to that!”
Right you are, Darryl.
Good, simple stuff. Now the script.
I’m using jQuery (‘cause it’s awesome) to wire up an onload page handler and capturing the IP address from our hidden input (that we injected into our ViewBag in the controller). So far, so good.
Next we fetch our proxy to our hub dynamically through SignalR’s connection object, then use this proxy to wire up a callback. This is the method that will be executed from our Hub. My handler simply takes a string and pushes it into a <p> tag. Finally, we start the connection and pass in an anonymous function to be executed once SignalR is up and running. This is where we make the call to our method in the hub. So, to recap:
- We create a proxy
- We setup an event handler
- We startup the connection, and when complete, call our recordView method on the hub (I’ll get back to the timing of startup in a minute)
Sweet. Hit F5, and see all your hard work come together…in fact, open a few browsers and watch as ALL the clients are updated when another loads.
Hit refresh on any one of those to witness the awesomeness. Nice work, fearless web developer!
If you start poking through the samples and venturing off to create new, more complex scenarios you may run into a couple things that aren’t at first apparent. I did, and hope that these points can help others who are looking.
- Case Matters
Don’t stop here, you’ve got some ‘sperimenting to do!
- Make sure Visual Studio 2010 is up to date. If you don’t have a copy, get it here.
- Get to know your open source community projects. Things like SignalR are helpful extensions to your projects and make development fun. There are a ton of worthwhile projects that you should get to know., but reviewing the source can lead you in new directions as well.
- Get involved! Sure, you can use SignalR, but you can contribute as well. Check out the project on GitHub, or if you have questions, pop into JabbR and connect with some of the helpful folks there.
I want to sent a quick thanks out to Michael Carter who helped through some timing and casing errors on JabbR while I put this sample together, David Fowler for sharing his excellent work on this project (the guy is absolutely brilliant) as well as Steve Lydford for the docs/samples he contributed to the project.