Continuous Communication: Bridging the Client and Server with SignalR

 

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.

SignalR and the MVC Framework

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:

  1. You’re going to create a project & install SignalR via NuGet
  2. Build your backend by creating one class that inherits from one of the SignalR base classes
  3. 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.

Creating the Project

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.

image

Next, we’re going to pick the empty template because we’re not too concerned about the whole flashy starter pages and default styling.

image

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:

image

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.

image

 

Building the Backend

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:

image

Note that inheriting from DbContext requires importing the System.Data.Entity namespace in the code below.

image

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.

image

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.

Clients is of type Dynamic.  There is no method on it called updateViewCount.  It doesn’t really know what I want to do, other than at runtime it’s going to have to go figure out where updateViewCount is and pass it my string.  Where does the method actually exist?  On the client, mes amis.  We’re writing that bad boy in JavaScript.

Wiring up the View

At this point, we need to make the client aware of the backend hub we’ve created. Open up _Layout.cshtml from Solution Explorer (it’ll be in your Views/Shared folder) and add a script reference to page. You’ll also need to update the reference to jQuery (remember how NuGet got us up-to-date?):

<script src=”@Url.Content(“~/Scripts/jquery-1.6.4.min.js”)” type=”text/javascript”></script>
<script src=”@Url.Content(“~/Scripts/jquery.signalR.js”)” type=”text/javascript”></script>
<script src=”/signalr/hubs” type=”text/javascript”></script>

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.

SignalR does this brilliant thing: it exposes your Hub classes through a route that it creates and initializes on your behalf. Your client is then able to access the methods of your class from JavaScript. It builds the library dynamically on the first call, caches it (until your application is recycled), and then takes care of resolving the calls for you.

Great, so our _Layout is updated to include the JavaScript bits we need, and SignalR is all up in our browser like a tree fort in a…tree.  So what do we need to do in our view?  Well, we want to have the IP address available from script, and we need a placeholder for our messages to come back to:

<input type=”hidden” id=”client-ip” value=”@ViewBag.ClientIpAddress” />
<div id=”view-updates”></div>

Good, simple stuff.  Now the script. 

image

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:

  1. We create a proxy
  2. We setup an event handler
  3. 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.

image

Hit refresh on any one of those to witness the awesomeness.  Nice work, fearless web developer!

Things I Learned Along the Way

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
    *   Class names and function names in c# are converted to camel case on the client side. This is important to know because, for example, if you try to get a reference to the proxy/hub for your ClassName, it would have to be $.connection.className. Conversely, client-side event handlers aren’t converted to TitleCase, so if your function is functionName, you’re going to call functionName against the dynamic Clients object in your hub.  <li>If you don’t follow casing conventions, you’ll run into errors with SignalR:
        *   “Unable to set value of the property 'someCallBack': object is null or undefined” is likely a class case issue, happens when registering a callback in a SignalR hub.  <li>“Object doesn't support property or method 'YourMethod'” is likely an issue with case on a method in your hub, happens when you try to call the method after you’ve started the hub, and the JavaScript runtime is ouching because it can’t find the method in the proxy SignalR has generated. <li>**Wait for Startup to Finish**
    *   While this seems obvious, many of the samples I found used a button click handler to make a call into the hub, which allows for extra time for the script to finish starting up. I tried at first to invoke a method right after my call to $.connection.hub.start(). I got the following error:
        *   SignalR: Connection must be started before data can be sent. Call .start() before .send() <li>If you run into this scenario just use the method I coded above.&nbsp; $.connection.hub.start() has an overload that accepts a callback as parameter, to be executed when the startup cycle is completed.&nbsp; There is also an overload that accepts settings; you can view the client API [here](https://github.com/SignalR/SignalR/wiki/SignalR-JS-Client). 
    

 

Next Steps

Don’t stop here, you’ve got some ‘sperimenting to do!

  1. Make sure Visual Studio 2010 is up to date. If you don’t have a copy, get it here.
  2. 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.
  3. 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.

 

A Quick Thanks

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.

Calling All Albertan Developers...PrDC is Approaching!

imageI am excited to see the stars aligning for another round of Prairie Dev Con.  This will be my third time speaking at PrDC and my first time in Calgary, where I worked for the better part of six years.  I’m looking forward to getting back there…I can hear the mountains calling!

There’s a great mix of sessions covering a variety of topics.  Some heavyweights from Microsoft are going to be there, delivering over 30 sessions on MS technologies.  There’s also a ton of great speakers covering agile, data, patterns and newer trends such as NoSQL.  Calgary local Simon Timms will even run you through what it takes to hack leverage phone systems in interesting ways.  Interested in Windows Phone development?  The one-and-only Bil Simser will be on hand to walk you through from project start to phone deployment.

Myself, I’ll be covering application development on the ASP.NET MVC framework.  I’m doing an intro session that is a 65 minute wild ride through a project, as well as a Dojo-style 2 hour marathon for which you’ll need to prove yourself as a developer by writing code.  Bring your laptop!

Registration is still open…head over to http://www.prairiedevcon.com for more information!

Them're Big Shoes To Fill

MvpBadge

I woke up this morning – the first day of 2012 – and knew it was going to be a great year. The kids were playing together, actually getting along!, my beautiful wife had made me a fresh cup of joe, and after getting a good couple weeks of visiting in with friends and family over Christmas, I officially start my holidays tomorrow.

And then I checked my email.

I am very pleased to be recognized as an MVP by Microsoft in the area of ASP.NET. 

After completing my registration on the MVP site, I had a look around the list of community leaders already in the program for ASP.NET and realized I have a long way to go to consider myself peers with those folks.  I read a lot of their blogs and many of the folks on the list have – through their articles, conference sessions, blog posts and emails – helped me out of more than one pickle.

Thanks to my nominator as well as the MVP lead here in Canada, and to Microsoft for this award.  I look forward to another great year of working in the ASP.NET space!

So, You Want to Speak JSON, eh?

I am actively developing on ASP.NET MVC 3 and that has proven very useful to me as I make the switch to developing for Windows Phone 7.

What?  you say That doesn’t make any sense!

To which I reply: embrace the cloud, homeboy. 

Okay, Wait a Minute

I know, I know, I just went from JSON to MVC 3 to Windows Phone 7 to the cloud. But, here’s the thing: they’re all complimentary.

If you’re looking for the code that makes returning JSON pretty much a freebie, skip ahead. Else { BuckleUp(); }

ASP.NET MVC is great for working with JSON – it supports binding JSON to your model classes natively, even when you’re dealing with complex mappings like collections of entities nested in other entities.  It’s also trivial to return JSON encoded data from your model classes and the result types are native to the framework.  It gets even better with LINQ to JSON and the Json.Net serialization library available on NuGet.

JSON is lightweight, so it makes it a great candidate for pushing data around in mobile scenarios.  If you want to work with anything other than Windows Phone 7 (what? why would you do that?!), then the freebies in the .NET world don’t play so nicely and you’ll want to jump on the JSON bandwagon.  Json.Net works on WP7 as well, so now you’re covered for your soon-to-be-awesome Windows Phone app.  (By the way…go join the movement and get a free Xbox, WP7, $500 and more here, if you’re Canadian…publish some apps!).

Where does the cloud come into this? Thought you’d never ask.  A refresh on the Azure toolkit earlier this year gave us MVC3 deployment templates, so pushing your app out on the web is simple. Find out more http://blogs.msdn.com/b/cdndevs/p/canadadoesazure.aspx.

Speaking JSON

So, you’re doing some MVC 3 dev, you (maybe) are hosting out in the cloud, and you want to knock off some low-hanging fruit to turn your controllers and actions into full-fledged JSON participants?  I was at a conference recently and saw how easy this was in Ruby on Rails, and figured there had to be a way to do this in MVC.  I didn’t want to have to write new versions of all my actions just to respond with the same data as JSON.

Turns out this is too easy, but first we need to understand a little bit about how controllers and actions work.

Incoming requests are handled by the routing framework for us.  A request coming in for Home/Index results in an instance of the HomeController getting created and then our Index action (method) being invoked.  But did you know that you have the chance to use ActionFilters?  If we create our own ActionFilter, we get the chance to modify the parameters coming into the action, we get access to the controller, the HttpContext and more. 

And that’s just on the front end of execution. We get a chance to look at everything again – including the view data – on the back end of execution as well, meaning we can swap out our own result object.  Huzzah! We have a vector!

Using the Vector

Here’s the plan:

  • Let the action execute
  • Check to see if the requesting party was looking for a JSON response, and, if they were,
  • Create a new JsonResult and push the model data from the action into it

 

Seems simple enough, right? Here’s what the implementation looks like (and honestly, there’s as much commenting in there as code):

namespace Json.ActionFilter
{     public class SupportsJson : ActionFilterAttribute     {         // we will use the framework default but allow users to override in the constructor         private JsonRequestBehavior _jsonRequestBehavior = JsonRequestBehavior.DenyGet;         public SupportsJson() {}         // if you want to allow GET (lame!) then be my guest...         public SupportsJson(JsonRequestBehavior behavior)         {             _jsonRequestBehavior = behavior;         }         // this happens AFTER the action is executed and BEFORE the result is returned         // so it's the perfect place to swap out the result object for our JSON one         public override void OnActionExecuted(ActionExecutedContext filterContext)         {             // capture the application types             var applicationTypes = (filterContext.HttpContext.Request.AcceptTypes ?? new string[] {""});             // check to see if json is in there             if (applicationTypes.Contains("application/json"))             {                 // swap out the result if they requested Json                 var model = filterContext.Controller.ViewData.Model;                 filterContext.Result = new JsonResult { Data = model, JsonRequestBehavior = _jsonRequestBehavior };             }         }     }
}

Bam! And just like that we have us some JSON capabilities!

Using the ActionFilter

Here’s an existing ActionResult I have:

        public ActionResult FooCookies(string term)         {             PeopleRepository repository = new PeopleRepository();             var people = repository.GetPeople(term);             return View(people);         }

How much work is it to have it return JSON instead?

        [SupportsJson]         public ActionResult FooCookies(string term)         {             PeopleRepository repository = new PeopleRepository();             var people = repository.GetPeople(term);             return View(people);         }

Tada! That’s right, just add the attribute SupportsJson and instantly you can repurpose any action to return JSON from the controller.

Next Steps

Hey look, you don’t need to be building Windows Phone 7 apps on Azure to take advantage of this.  If you’re building any site using jQuery or jQuery UI, if you work with other mobile platforms or even building for Windows 8, now is a good time to make sure that your data (and complex entity collections) are JSONable. So, you can start by:

Good luck!

Ninjas Unleashed to the Wild

I want to extend a huge thank you for all who attended my inaugural Asp.Net MVC3 Dojo event.  Over a dozen folks came out and slogged away at code as we worked through building a movie review site end-to-end using the MVC Framework, NuGet and one mighty fine IDE, Visual Studio 2010.

Some of the things we covered in today’s two and a half hour code work-out:

  • Models, views and controllers (of course!)
  • Scaffolding and the MvcScaffolding package
  • jQuery and AJAX in MVC
  • Partial views
  • Action filters
  • Authentication and Authorization
  • The MVC tool chain
  • NuGet and little “gems” like jQuery.RateIt and MvcMembership.Mvc
  • Customizing the output of the scaffolders
  • EF Code First, data contexts and dbsets
  • Data annotations
  • Model binding
  • JSON and other alternate action return types
  • …and more

 

We covered a lot of ground, for sure.  If you want to have at the reference app with the rest of the code that we weren’t quite able to get to, please pop on over to github and grab a copy of the solution.

Looking forward to hearing the feedback and please, feel free to get in touch.

Next Steps

Now that you’ve gone through File –> New Project, don’t stop there.

  • Make sure you get your IDE up to date
  • Keep exploring MVC, including MVC 4
  • Ask questions…
    *   On the [Canadian Developer Connection](http://www.linkedin.com/groups/Canadian-Developer-Connection-3398140) (Linked In)...I keep watch here for web dev questions and am always happy to help out  <li>Here, on my blog ![Winking smile](http://oldblog.jameschambers.com/Media/Default/Windows-Live-Writer/Ninjas-Unleashed-to-the-Wild_1378A/wlEmoticon-winkingsmile_2.png)  <li>Ask on [Twitter](http://www.twitter.com/canadianjames) with the #aspnetmvc hash tag  <li>Or on a community site you're already comfortable with <li>Have a good browse over at [nuget.org](http://nuget.org/) and find packages that will simplify your development 
    

 

Thanks again!

ASP.NET MVC 101/WPG

It’s great to be speaking in my stomping grounds and to be able to share a little about the ASP.NET MVC Framework while I’m here at Prairie Dev Con 2011 Winnipeg. 

Surviving the Boom!

Yikes. Talk about a presenter’s nightmare! In the perfect storm of technology fail, my particular combination of laptop make and model, the Apple mini-displayport adapter and a wonky projector worked together to try to stop the presentation from happening at all.

Thanks especially to D’Arcy Lussier for making a last minute schedule change and squeezing me back in.  There were about 50 people on board for the session with great questions and lots of interest.  Please keep the feedback coming and stay tuned for lots more info on MVC 4 here in my scratching grounds.

As for diving deeper, join me tomorrow for a two-hour Dojo-style dive into MVC3 and we’ll get your feet wet.  Bring your laptops!

Here’s a couple of links for you to help transition from what we talked about today in session to your own projects in your IDE:

 

Thanks again everyone for joining me and I look forward to seeing you at the Dojo session tomorrow.