Friday, May 18, 2012

ASP.NET MVC 3 Actual Time Shared Applications through SignalR


In this article, we’ll create a simple blog app using ASP.NET MVC 3 and SignalR, that will allow multiple collaborators to review the same article in real-time.




What is SignalR?

By the book – It is an asynchronous signaling framework that helps maintain persistent connections between client and server.

Not by the book – A real cool framework built on top of ASP.NET (server side) and a JavaScript library (on the client side) that helps build collaborative web apps in a jiffy. David Fowler and Damien Edwards maintain the SignalR project on GitHub

SignalR abstracts the raw technique of keeping connections open between a web client and a web server. Behind the scenes it uses an existing technique called long polling. However as the WebSockets protocol crystallizes, it could very well use WebSockets transparently, behind the scenes.

SignalR uses the task parallel library on the server side. It scales well as of now. However, work is in progress to make it better.

Why do I need SignalR?

Most common examples where long polling is used are stock tickers or chat clients. However as we will see today SignalR throws open a whole new set of possibilities, enabling rich collaborative applications on ASP.NET.

Solving a business problem with SignalR

Enough theory, let’s get down to the real world. I am sure most of us have at some point used Google docs and recently if you have noticed, you can share it with multiple people and now you can even have two people edit it at the same time. Each person gets a different colored caret to track who is doing what.

Wouldn’t it be cool if you could embed such ’Review’ functionality to your app? Imagine filling out a form and then sending it out for review only to find out someone down the chain rejected it after a week because of a typo? Now imagine what if you could do instant reviews and everyone could give their inputs and sign off on the document at the
same time?

In this article we’ll create a simple blog app that will allow multiple collaborators to review an article at real-time.

Step 1: Create new ASP.NET project.

In Visual Studio From File > New Project, select the MVC 3 Web Application template

asp-mvc-project

Select ‘Intranet Application’. This results in creation of a project that works by default with Windows Authentication mode.

We use the Razor View engine and keep the Use HTML5 semantic markup checked.

razor-view

If you already have Nuget Package Manager installed, skip to Step 2. Else go to Tools > Extension Manager, and from the ‘Online Gallery’ install ‘NuGet Package Manager’.
nuget-manager

It will require a Visual Studio restart. Restart once installed.

Step 2: Setup SignalR dependencies using Nuget

Bring up the Package Manager Console from the View->Other Windows->Package Manager Console menu item. 
In the console type Install-package SignalR

Wait for the packages to be downloaded and setup. The jQuery dependencies will be refreshed too.

package-mgr-console

Step 3: Setup Data Model

We will use EF Code First to setup our model. The entity is called BlogPost and it has three properties for simplicity, Id, Title and BlogBody.
data-model

Note: Since the focus of the article is SignalR I am cutting some ‘pattern corners’ by putting Display attributes in my Entity Model and skipping the View model abstraction.

Create a BlogPostContext class that derives from DbContext. Build the Solution.

Step 4: Scaffold the Controllers and Views

We will use the built in scaffold tooling to generate the controller and views.

add-controller

Select the Template, Model class and Data context class in the ‘Add Controller’ dialog

controller-dialog

Step 5: Add the ‘Review’ Controller and View

By default, the scaffolding generates Index, Create Edit and Delete views each mapping to their respective actions. We will leave these as is and add a new Action called ‘Review’. To do this we’ll simply copy the Edit Action and rename it.

In the BlogPostController, add the Review action methods as follows:

review-action-method

Under Views\BlogPost add the Review.cshtml

review-cshtml

In the Index.cshtml, add a new link to the ‘Review’ view.

review-view-link

Step 6: Getting SignalR into action

On the Server Side
In your web project create a folder called SignalR (You can call it anything you want, in a real life project this as server side component and could very well reside in a dll of it’s own). In the SignalR folder add a class BlogHub.cs. Update the class to look as follows:

blog-hub-class

The class is decorated with the ‘HubName’ attribute that takes a string parameter. The string parameter is the ‘client side’ name of the ‘Hub’. The Hub as the name suggests keeps track of the ‘subscribers’ and ‘publishes’ or broadcasts the messages that are passed to it by the subscribers.

In the above snippet, the Send method is called from the web page via JavaScript. SignalR framework takes care of the appropriate hookups.

Each ‘client’ that is web page, interested in receiving events from the hub subscribes to it and then implements the addMessage function. So when the Hub fires back, all clients handle the event.

On the Client Side

Open Review.cshtml and add the following references

review-references

The jQuery and signalR dependencies will be available for you from the SignalR nuget package installation, however json2.min.js is not. You have to download it separately fromhttps://github.com/douglascrockford/JSON-js. This library is written by Douglas Crockford and is a public domain license. The minified version is available athttp://code.google.com/p/webscan/source/browse/trunk/ui/js/third-party/json2.min.js?r=80 (or in the code package of this article).

The ‘/signalr/hubs’ reference is showing the green squiggly for a reason. It doesn’t exist as design time. It will be generated at run-time.

Bringing Diff-Match-Patch into the party

We will use Neil Fraiser’s excellent implementation from http://code.google.com/p/google-diff-match-patch/ There are multiple implementations available and you could use it on the server side (C# library) or client side (javascript library). I decided to let the client do all the hard work, so I used the javascript library. Add the script reference to Review.cshtml

mvc-review-reference

Add a placeholder to Review.cshtml that will hold the session id. This session Id is used to identify which client initiated the request.

session-id

Hooking up the hub and the publish handlers

Add the following script block to the Review.cshtml
publish-handlers

The code comments are pretty self-explanatory and the sequence of events is as follows:
  1. Two clients come to review the same BlogPost
  2. One makes changes to the BlogPost’s Article (aka BlogBody) that is ‘Send’ to the hub with an identifier as to who initiated the change (Session Id).
  3. The hub simply lobs it back to all the clients by calling the ‘addMessage’ method.
  4. Now both the clients receive the addMessage ‘signal’. Only the one that has a session Id that doesn’t match goes ahead and does a diff-match-patch.

Other Miscellaneous changes
Update _Layout.cshtml ‘s jquery script reference to the version you have. 
Make things pretty by changing the default title of the app from ‘My MVC Application’ in the _Layout.cshtml to something nicer. 
Change the Index.cshtml and update the header from ‘BlogBody’ to ‘Article’ 
Change the Global.asax ‘s RegisterRoutes method to navigate to the BlogPost’s Index directly

register-routes

Step 7: Let it Roll

Run the application and create a new Post. Save it. Your Index page should look something like the following

mvc-signalr-demo

Click on Review to go the review page. Press Ctrl+N to fire up a new browser instance with same page. Hit F5 to update session Id in the new Browser instance.

Line up the browsers side by side. Type in one and watch the other one change.

mvc-signalr-sync

Conclusion

SignalR is a powerful and easy to use framework that enables permanent connections and Asynchronous signaling in ASP.NET. Its potential uses include but not limited to
  • Collaborative editing tools like the one we saw here.
  • Highly dynamic apps where certain changes can be pushed in near real time for example, a Cart can signal a purchase completion enabling dynamic updates of ‘stock numbers’ for end users
  • News tickers with real-time feeds and many many more.
Long-polling is not a new thing, however now we have a fantastic abstraction to use in ASP.NET.


SPONSORS:

No comments:

Post a Comment