Friday 31 August 2012

Calling a SignalR server function on page load



I was working on the demo for next blog post. In the demo, I needed to call a SignalR server method on the page load (i.e., jQuery’s ready event). The only thing I kept in mind was, the connection should be started before I call the method. I added the following piece of code to the ready event and opened the page on a browser:

var proxy = $.connection.myHub;
$.connection.hub.start();
proxy.server.functionCall();

Unfortunately, it didn’t work. I thought that there might be some JavaScript errors with this small piece of code, which I failed to spot by looking at the code. I opened the developer tools of Opera browser and refreshed the page. Execution of JavaScript was halted at the following statement of the dynamically generated /signalr/hubs script:



Error statement


I found the following in the error list:



After reading and analysing a bit on the above error, I inferred that the start() function is not a synchronous function. I invoked hub’s function before SignalR established the connection. Error message in the first screenshot suggests a solution to this issue. It is mentioned there to use .start().done() or .start().fail() to run logic after the connection started. I modified the code to:

var proxy = $.connection.myHub;
$.connection.hub.start().done(  function() {
    proxy.server.functionCall()
});


I opened the page on the browser and as expected, I got the result. I thought of using an approach that I already knew, using pipe() to register the callback logic. I again modified the code to:


var proxy = $.connection.myHub;
$.connection.hub.start().pipe(  function() {
    proxy.server.functionCall()
});

It didn’t disappoint me. I got what I wanted.

I visited the SignalR JS Client documentation page on GitHub to learn more about SignalR client script. I learnt another way of wiring up the callback function on this page. This approach is the simpler than both of the above approaches. We can register the callback to the start function itself as follows:


$.connection.hub.start( function() {
    proxy.server.functionCall()
});


I tried it out and got the result.
If you get to know any other approach, you may share it through comments.

Happy coding!

Sunday 26 August 2012

Getting started with SignalR


What is SignalR?

SignalR is an abstraction over transport that simplifies the connection management to create real-time web applications. SignalR makes it very easy to make asynchronous calls to server using client-side scripting. Data can be either broadcasted to all clients or can be sent to specific clients. Visit Github repository to learn more.

SignalR uses the capabilities of modern browsers and platforms to maintain persistent connection. If the browser or platform doesn’t support the feature SignalR is looking for, it falls back to one of a few alternative approaches. Based on the browser, one among the following is chosen (in a cascading fashion):
  • Web Sockets
  • Server sent events
  • Forever frames
  • Long polling



Good Morning SignalR!

Now that we have some basic understanding on SignalR, let’s build an application to see how SignalR helps us in building rich responsive web applications.

Start Visual Studio 2010 (or 2012) and choose File -> New -> Project. From the dialog, choose the Empty Web Application template. Make sure that the target version of the project is .NET framework 4 or later. Name the application and hit OK




Visual Studio project template


Right click on references and choose the option Manage NuGet Packages (if you have installed NuGet 2.0, otherwise choose Add Library Package Reference)



Search for SignalR in the package manager dialog box and click on the install button to add the library as shown below:




This step adds everything that you need to use SignalR in your application. It includes the following dlls:
  • Microsoft.Web.Infrastructure
  • Newtonsoft.Json
  • Microsoft.AspNet.SignalR.Core
  • Microsoft.AspNet.SignalROwin
  • Microsoft.AspNet.SignalR.SystemWeb
  • Microsoft.Owin.Host.SystemWeb
And the following JavaScript libraries:
  • jQuery core library
  • SignalR jQuery library
Let’s create a page in which a client can greet all other active clients. We need a piece of code on the server which is responsible to send the greeting message to all the clients. To do this, we need to define a class that inherits from Microsoft.AspNet.SignalR.Hub class. The Hub class contains a set of properties using which we can communicate with the clients.

Add a class to the web application and name it SignalRHub. Add a method to this class named GreetAll, which doesn’t take any arguments and sends a Good Morning message to all the clients. In this method, we have to use the Clients property defined in the Hub class. It is a dynamic object, using which we can invoke JavaScript fields and functions defined by the client.
Implementation of the GreetAll method is pretty straight forward. We have to invoke a method which should be defined in the web page to show the message sent from the server.
public class SignalRHub : Hub
    {
        public void GreetAll()
        {
            Clients.acceptGreet("Good Morning");
        }
    }

The acceptGreet function called above should be defined as a JavaScript function in the client web page.


Add an ASP.NET web form to the application. Right click on the application and select Add -> New Item. From the new item dialog, choose Web Form, name it as per your wish and click on Add.

Add references to jQuery core and SignalR jQuery libraries to the page. Also, add reference to a special JavaScript library, which is “/signalr/hubs”. It will be generated dynamically when the application runs. The /signalr/hubs/ library will contain JavaScript proxies of the methods defined in the hub and the logic of calling the server methods. In case of this application, the library will have a proxy of the GreetAll method. So, now you should be having the following script tags added to the page:


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

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

<script src="/signalr/hubs" type="text/javascript"></script>


Add an HTML button to the page, on click of which, we will invoke the GreetAll method.
<input type="button" id="greetingButton" value="Greet Everyone!" />

To make the client functional, we need to add some JavaScript code on the page. Handle the jQuery’s document ready event and create a proxy object as shown:
$(document).ready(function () {
     var proxy = $.connection.signalRHub;         
)};

The connection field used above is defined by SignalR. It is a JavaScript object that contains the details like transport used to establish the connection, current state of the connection, proxy objects of the hubs defined on the server side, status of the current request. You may say that connection is the heart of the SignalR on the client side.

Here signalRHub is a JavaScript proxy object that corresponds to the SignalRHub class defined in C#. You can find it in the /signalr/hubs script that gets generated dynamically. I suggest everyone to have a look at the contents of the signalRHub object using browser tools after running the application.

You won’t get signalRHub in intellisense as it will be resolved at the runtime. On click of greetingButton, call the GreetAll function using the proxy object created above.
$("#greetingButton").click(function () {
     proxy.server.greetAll();
});

Define the acceptGreet function, which is called by the server using the Clients property of the Hub class as follows:
proxy.client.acceptGreet = function (greetingMessage) {
     alert(greetingMessage);
};

Finally, start the hub from the client side. After this step, the client will have a persistent connection with the server.
$.connection.hub.start();

Build the application and run it. On click of the greetingButton, you should see an alert box with the message Good Morning. This is not too great, is it? Open another browser and copy the URL from already running browser and paste it in the address bar of the new browser and hit enter. Click the button on one of the browsers. You should be able to get the alert on both browsers as shown below:





Here is the magic!!! The message from the server is broadcasted to all of its clients. SignalR is extremely useful in the applications where many clients have to be notified about some change in the server at the same time. To build pages showing stock values, weather details of major cities, live score of a game or any similar requirement where data changes very rapidly, SignalR is very useful.



References and further learning:

Damien Edwards’ talk on SignalR at NDC
Damien Edwards and David Fowler's talk on SignalR at Build 2012
Scott Hanselman's talk on SignalR at Devcon 2012



Happy coding!