Showing posts with label SignalR. Show all posts
Showing posts with label SignalR. Show all posts

Monday, 30 December 2013

Self-Hosting ASP.NET SignalR Using Katana

With the recent release of ASP.NET, Microsoft added a new component, Katana. It is an implementation of OWIN (Open Web Interfaces for .NET) that provides a light weight alternative to create a .NET server quickly without needing any of the ASP.NET components or IIS. The server can be composed anywhere, even on a simple Console based application. For more information on Katana, read the excellent introductory article by Howard Dierking.

The project templates of ASP.NET that come with Visual Studio 2013 have some pieces of Katana also installed, as we saw some of them in my post on Identity system. It is used there to make the identity system available for across all flavours of ASP.NET.

Katana made the process of self-hosting ASP.NET Web API and SignalR very easier with its simple interface. Any Katana based application needs a startup class to kick the things off. We can perform any global configuration in this class. It includes hub route mapping in SignalR or API controller routing in Web API.

Let’s build a simple console-hosted SignalR application using Katana. Create a console application using Visual Studio 2013 and install the following NuGet package on this project:


Install-Package Microsoft.AspNet.SignalR.SelfHost


This package installs all the dependencies required to write and publish a SignalR application on a non-web based environment. Add a new class to the project; name it Startup and add the following code to it:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.MapSignalR();
    }
}

The configuration method is used comparable to Application_Start event in Global.asax, it gets called at the beginning of the application. As we see, SignalR routes are mapped in the configuration method. We need to start the server in the Main method of the Program class. Add following code to the Main method:
static void Main(string[] args)
{
    string uri = "http://localhost:8080/";

    using (WebApp.Start<Startup>(uri))
    {
        Console.WriteLine("SignalR server started, start sending requests");
        Console.ReadKey();
        Console.WriteLine("Server stopped!");
    }
}

As there is no web server to host our application, we need to specify a port number where the server has to keep running. The generic static method WebApp.Start is called to start the server; it calls the Configuration method defined above. The server would stop once the console application stops running.

Let’s create a boring hello-world kind of hub. Following is a hub that takes name of a person and returns a greeting message with current time stamp:

public class HelloWorldHub : Hub
{
    public void Greet(string name) 
    {
        Console.WriteLine("Got a request from: {0}", name);
        string message= string.Format("Hello, {0}. Greeted at: {1}",name,DateTime.Now.ToString());
        Clients.All.acceptGreeting(message);
    }
}

Run the console application, you should be able to see the following message:

Let’s quickly create a console client to test if the server is able to push messages to the client. Create another console application and add the following NuGet package to it:


Install-Package Microsoft.AspNet.SignalR.Client


Add following code to the Main method:

static void Main(string[] args)
{
    var hubConnection = new HubConnection("http://localhost:8080/");
    var hubProxy = hubConnection.CreateHubProxy("HelloWorldHub");
    hubProxy.On<string>("acceptGreeting", message => {
        Console.WriteLine("Received from server: " + message);
        Console.WriteLine("\n\nPress any key to exit.");
    });

    Console.WriteLine("Establishing connection...");
    hubConnection.Start().Wait();
    Console.WriteLine("Sending request to hub...");
    hubProxy.Invoke("Greet", "Ravi").Wait();

    Console.ReadLine();
    hubConnection.Stop();
}

Run the client application, you should be able to see the following output:



Happy coding!

Wednesday, 11 September 2013

A Better Way of Using ASP.NET SignalR With Angular JS

A few days back, I blogged on using SignalR and Angular JS together and on Implementing SignalR stock ticker sample using Angular JS(Part 1 and Part 2). In those posts, I have used the traditional call-back model to call the functions defined in controller to modify data whenever an update is received from the server.

One of the readers sent me feedback saying that we have a better way to use SignalR and Angular JS together. The way to go is using event methods defined on $rootscope object. This approach is based on publishing and subscribing events. As events can be published from anywhere and subscribed from anywhere, the source and destination will remain completely unaware of each other. Both of them have to depend on just one object, $rootScope.

Official documentation on scope contains details on each method defined on $rootScope. We will be using the following methods for publishing and subscribing the events:

  • $emit(name, args): Publishes an event with specified name with given arguments
  • $on(name, listener): Subscribes to an event with specified name. Listener is a function containing logic to be executed once the event has occurred

To manage SignalR’s client functionality, it is better to create a service, as services are singletons. There will be only one instance of the service in entire application. This behaviour of services makes it possible to have multiple SignalR client pages in the applications and they can be kept in sync without putting any extra amount of effort.

Let’s modify the example discussed in the post titled Hooking up ASP.NET SignalR with Angular JS to use event model. Server hub, references and structure of the HTML page remains the same as past. The only components to be modified are Controller and Service.

Service carries the responsibility to initialize a connection to the hub and call the SignalR’s server methods. Once a response is received from the server, we will broadcast an event from the service with data received.


app.service('signalRSvc', function ($, $rootScope) {
    var proxy = null;
 
    var initialize = function () {
        //Getting the connection object
        connection = $.hubConnection();
 
        //Creating proxy
        this.proxy = connection.createHubProxy('helloWorldHub');
 
        //Starting connection
        connection.start();
 
        //Publishing an event when server pushes a greeting message
        this.proxy.on('acceptGreet', function (message) {
            $rootScope.$emit("acceptGreet",message);
        });
    };
 
    var sendRequest = function () {
        //Invoking greetAll method defined in hub
        this.proxy.invoke('greetAll');
    };
 
    return {
        initialize: initialize,
        sendRequest: sendRequest
    }; 
});


To keep the things simple, I kept names of the server hub event and event rose using $emit the same. The names can be different. Let’s modify the controller to have a listener to the event raised by the service. Following is the implementation of the controller:

function SignalRAngularCtrl($scope, signalRSvc, $rootScope) {
    $scope.text = "";
 
    $scope.greetAll = function () {
        signalRSvc.sendRequest();
    }
 
    updateGreetingMessage = function (text) {
        $scope.text = text;
    }
 
    signalRSvc.initialize();
 
    //Updating greeting message after receiving a message through the event

    $scope.$parent.$on("acceptGreet", function (e,message) {
        $scope.$apply(function () {
            updateGreetingMessage(message)
        });
    });
}


Now open the modified page on multiple browsers and click the Greeting button randomly from all browsers. Messages printed on all browsers should be updated whenever the button is clicked. This behaviour is same as it was earlier. We just adopted a better approach to make it work.

Happy coding!

Wednesday, 10 July 2013

Book Review - SignalR: Real-time Application Development

Over past few days, I was reading the book SignalR: Real-time Application Development, authored by Einar Ingebrigtsen and published by PaktPub. It is a nice, quick and effective read on SignalR. If you are looking for a simple guide to get you up to speed with the technology, then this book is a right choice.


The author did a nice job by keeping it very simple and yet covering what someone needs to know to start working on a project based on SignalR. All chapters are hands-on based with every step explained in detail. Because of this, it is extremely easy to follow the concepts and keep coding the examples at the same time.

First chapter of the book starts with stories on old terminal systems and discusses till rich clients and how they are better than any of the older client type. Immediately, the author jumps to web development, how it evolved over the years and what is expected out of web today. Here, it discusses what problems are solved by SignalR and why it is necessary to learn this technology.



After introducing the technology, the author dives into technical details of SignalR and discusses the underlying concepts in different chapters. The chapters cover following:

  • Creating server components using Persistent connections and Hubs and consuming them in Web and .NET clients
  • Creating groups on server and maintaining clients in the groups
  • Maintaining state
  • Securing hubs and applying authentication, authorization on Hub’s methods
  • Scaling out across multiple servers using different techniques
  • Monitoring traffic using tools like Fiddler
  • Hosting outside a web application using OWIN
  • Using SignalR in Windows Store applications

I hope you enjoy reading this 124-page quick read on SignalR as much as I did.

Happy coding!

Tuesday, 21 May 2013

Implementing SignalR Stock Ticker using Angular JS - Part2

In last post, we implemented SignalR part of the stock ticker sample using Angular JS and modified the HTML page to use Angular’s directives. As promised earlier, we will finish the implementation in this post by incorporating UI changes using directives and filters.

Angular JS is designed with separation of concerns in mind. One of the best architectural features of Angular JS is, it makes it easier to separate HTML and JavaScript separated from each other while playing together at the same time. Features like directives and filters can be used to easily extend Angular’s expressions and behaviour of HTML elements without wasting a lot of time and energy.

In the original Stock Ticker sample, following changes are made while binding data on the page:

  • Change in stock value is prepended with a up or down symbol based on value
  • Percentage value is multiplied with 100 and % symbol is appended to it

It also has the following UI effects on the page:

  • jQuery Colour flash effect on rows of table and list items
  • List item keeps scrolling when the stock market is open
  • Buttons are enabled and disabled based on current market state


Creating filters to represent data more effectively

Let’s write a couple of filters to manipulate change and percent change while presenting on the screen:

app.filter('percentage', function () {
    return function (changeFraction) {
        return (changeFraction * 100).toFixed(2) + "%";
    }
});
 
app.filter('change', function () {
    return function (changeAmount) {
        if (changeAmount > 0) {
            return "▲ " + changeAmount.toFixed(2);
        }
        else if (changeAmount < 0) {
            return "▼ " + changeAmount.toFixed(2);
        }
        else {
            return changeAmount.toFixed(2);
        }
    }
});

As you see the above code, implementation of the filters is pretty straight forward. Value on which the filter has to act is passed into the filter function. All we need to do is, manipulate the value as needed and return it. Using these filters is very easy as well, following snippet demonstrates the usage:
<td>
    {{stock.Change | change}}
</td>
<td>
    {{stock.PercentChange | percentage}}
</td>

Creating directives to make UI better

The buttons Open market and Reset have to be enabled when market is closed and close market button has to be enabled when market is opened. We can simulate this behaviour using the Boolean property marketIsOpen inside expression ({{ }}).

To evaluate expressions inside a directive, we need $interpolate service. The directive also needs to watch for change of the value to immediately change state of the button. Following is the implementation of the directive:

app.directive('disable', function ($interpolate) {
    return function (scope, elem, attrs) {
        var exp = $interpolate(elem.attr('data-disable'));
        function updateDisabled() {
            var val = scope.$eval(exp);
            if (val == "true") {
                elem[0].disabled = 'disabled';
            }
            else {
                elem[0].disabled = '';
            }
        }
 
        scope.$watch(exp, function (value) {
            updateDisabled();
        });
    }
});

While using the directive, we should assign it with a Boolean expression.
<input type="button" id="open" value="Open Market" data-disable="{{marketIsOpen}}"
            data-ng-click="openMarket()" />
<input type="button" id="close" value="Close Market" data-disable="{{!marketIsOpen}}"
            data-ng-click="closeMarket()" />

To indicate change of a stock value, the corresponding row in the table should flash. Let’s write a directive to do this:
app.directive('flash', function ($) {
    return function (scope, elem, attrs) {
        var flag = elem.attr('data-flash');
        var $elem = $(elem);
 
        function flashRow() {
            var value = scope.stock.LastChange;
            var changeStatus = scope.$eval(flag);
            if (changeStatus) {
                var bg = value === 0
                            ? '255,216,0' // yellow
                            : value > 0
                            ? '154,240,117' // green
                            : '255,148,148'; // red
 
                $elem.flash(bg, 1000);
            }
        }
 
        scope.$watch(flag, function (value) {
            flashRow();
        });
    }
});

The directive can be applied on any element that needs the scroll effect. Following is a sample table row using this directive:
<tr data-ng-repeat="stock in stocks" data-flash="marketIsOpen">
 ...
 ...
</tr>

The final directive that we have to create will be used to make the stock list scrollable. Again, values will keep scrolling when the market is opened. Following is the implementation:
app.directive('scrollTicker', function ($) {
    return function (scope, elem, attrs) {
        var $scrollTickerUI = $(elem);
        var flag = elem.attr('data-scroll-ticker');
        scroll();
 
        function scroll() {
            if (scope.$eval(flag)) {
                var w = $scrollTickerUI.width();
                $scrollTickerUI.css({ marginLeft: w });
                $scrollTickerUI.animate({ marginLeft: -w }, 15000, 'linear', scroll);
            }
            else
                $scrollTickerUI.stop();
        }
 
        scope.$watch(flag, function (value) {
            scroll();
        });
    }
});

It is applied on the list as:
<ul data-scroll-ticker="marketIsOpen">
 ...
 ...
</ul>

Now open the new scroll ticker page on a browser. Open the original jQuery based implementation on another browser window and play with both the screens. Now both of them have same look and behaviour.


This sample demonstrates how to make best use of features of Angular JS with SignalR to create real-time data oriented applications. The beauty of this approach is, we have several independent components playing pretty well together. This approach eases organization of code and makes each component testable in isolation.

 Code covered in this series is available on Github. Feel free to fork the code if you think that any part of it can be improved!!


Note: If you have finished reading this series and want to use your learning in a project, make a note to check this post as well: A Better Way of Using ASP.NET SignalR With Angular JS. GitHub repo for the series contains a controller and a service that fulfill the same purpose in a better way, make sure to check the code

Happy coding!

Sunday, 19 May 2013

Implementing SignalR Stock Ticker using Angular JS - Part1

In my last post, we saw how to use ASP.NET SignalR and Angular JS together using a Hello World type of example. Now that we got some idea on using both the technologies together, we will take a look at a more advanced scenario to make the frameworks work better together.

I assume that you have already seen the SignalR Stock ticker sample. If not, download it from Github or add the NuGet Package to an existing ASP.NET web application. Make sure that you take some time to run the sample at least once on multiple browsers and have a glance at the code before you proceed further.

I hope you had a look at the code on both server and client side of the stock ticker sample. We will not make any modification to the server code and the layout of the page. But we will rewrite the JavaScript part using features of Angular JS. As there is a lot of client side code to convert, let’s do it in a two-part series:

  1. Creating a custom service to communicate with hub on the server and using the service in a controller (This post)
  2. Performing UI changes on the page like enabling/disabling buttons, scrolling stock values in a list, adding animation effect to values in table and list (Next post)

Make a copy of the StockTicker.html file and give it a name of your choice. Add two files JavaScript files, controller.js and factory.js to the project. We will add script to these files in sometime. Modify the script reference section of the page to include the following script files:

<script src="../../bundles/jquery"></script>
<script src="../../bundles/jquerycolor"></script>
<script src="../../Scripts/jquery.signalR-1.0.1.js"></script>
    
<script type="text/javascript" src="../../Scripts/angular.js"></script>
<script type="text/javascript" src="factory.js"></script>
<script type="text/javascript" src="controller.js"></script>
Let’s start implementing SignalR part inside a custom service. To keep the controller free from doing anything other than providing data to the view and handle view events, we are creating a custom service to handle the hub communication logic. The service is responsible for:
  1. Creating objects needed for communication
  2. Configuring client functions to proxy to respond when market is opened, closed, reset or a stock value is updated
  3. Starting a hub connection
  4. Getting current values of stocks and current market status once the connection is started
  5. Opening, closing or resetting market on demand
Following is the module and the factory that handles the functionality mentioned above:
var app = angular.module('app', []);
app.value('$', $);
app.factory('stockTickerData', ['$', '$rootScope', function ($, $rootScope) {
    function stockTickerOperations() {
        //Objects needed for SignalR
        var connection;
        var proxy;
 
        //To set values to fields in the controller
        var setMarketState;
        var setValues;
        var updateStocks;
 
 //This function will be called by controller to set callback functions
        var setCallbacks = function (setMarketStateCallback, setValuesCallback, updateStocksCallback) {
            setMarketState = setMarketStateCallback;
            setValues = setValuesCallback;
            updateStocks = updateStocksCallback;
        };
 
        var initializeClient = function () {
            //Creating connection and proxy objects
            connection = $.hubConnection();
            proxy = connection.createHubProxy('stockTicker');
 
            configureProxyClientFunctions();
 
            start();
        };
 
        var configureProxyClientFunctions = function () {
            proxy.on('marketOpened', function () {
                //set market state as open
                $rootScope.$apply(setMarketState(true));
            });
 
            proxy.on('marketClosed', function () {
                //set market state as closed
                $rootScope.$apply(setMarketState(false));
            });
 
            proxy.on('marketReset', function () {
                //Reset stock values
                initializeStockMarket();
            });
 
            proxy.on('updateStockPrice', function (stock) {
                $rootScope.$apply(updateStocks(stock));
            });
        };
 
        var initializeStockMarket = function () {
            //Getting values of stocks from the hub and setting it to controllers field
            proxy.invoke('getAllStocks').done(function (data) {
                $rootScope.$apply(setValues(data));
            }).pipe(function () {
                //Setting market state to field in controller based on the current state
                proxy.invoke('getMarketState').done(function (state) {
                    if (state == 'Open')
                        $rootScope.$apply(setMarketState(true));
                    else
                        $rootScope.$apply(setMarketState(false));
                });
            });
        };
 
        var start = function () {
            //Starting the connection and initializing market
            connection.start().pipe(function () {
                initializeStockMarket();
            });
        };
 
        var openMarket = function () {
            proxy.invoke('openMarket');
        };
 
        var closeMarket = function () {
            proxy.invoke('closeMarket');
        };
 
        var reset = function () {
            proxy.invoke('reset');
        };
 
        return {
            initializeClient: initializeClient,
            openMarket: openMarket,
            closeMarket: closeMarket,
            reset: reset,
            setCallbacks: setCallbacks
        }
    };
 
    return stockTickerOperations;
} ]);
We need a controller to start the work. The controller will have following components:

  1. An array to store current stock values and a Boolean value to store current market state
  2. Setters to assign values to the fields 
  3. A function to modify the value of an entry in the stocks array
  4. Functions to handle open, close and reset operations when corresponding button is clicked
  5. Set callbacks to the service and ask the service to kick off the communication

Following is the code in the controller:

var StockTickerCtrl = function ($scope, stockTickerData) {
 
    $scope.stocks = [];
    $scope.marketIsOpen = false;
 
    $scope.openMarket = function () {
        ops.openMarket();
    }
 
    $scope.closeMarket = function () {
        ops.closeMarket();
    }
 
    $scope.reset = function () {
        ops.reset();
    }
 
    function assignStocks(stocks) {
        $scope.stocks = stocks;
    }
 
    function replaceStock(stock) {
        for (var count = 0; count < $scope.stocks.length; count++) {
            if ($scope.stocks[count].Symbol == stock.Symbol) {
                $scope.stocks[count] = stock;
            }
        }
    }
 
    function setMarketState(isOpen) {
        $scope.marketIsOpen = isOpen;
    }
 
    var ops = stockTickerData();
    ops.setCallbacks(setMarketState, assignStocks, replaceStock);
    ops.initializeClient();
}

Layout of the HTML page will remain unchanged. But we need to change the way data is rendered on the screen. The stock ticker sample uses poor man’s template technique to render content in the table and in the scrolling list. Since we are using Angular JS, let’s replace it with expressions. Following is the mark-up on the page in Angular’s style:
<div data-ng-app="app" data-ng-controller="StockTickerCtrl">
        <h1>
            ASP.NET SignalR Stock Ticker Sample</h1>
        <input type="button" id="open" value="Open Market" data-ng-click="openMarket()" />
        <input type="button" id="close" value="Close Market" data-ng-click="closeMarket()" />
        <input type="button" id="reset" value="Reset" data-ng-click="reset()" />

        <h2>
            Live Stock Table</h2>
        <div id="stockTable">
            <table border="1">
                <thead>
                    <tr>
                        <th>Symbol</th>
                        <th>Price</th>
                        <th>Open</th>
                        <th>High</th>
                        <th>Low</th>
                        <th>Change</th>
                        <th>%</th>
                    </tr>
                </thead>
                <tbody>
                    <tr class="loading" data-ng-show="stocks.length==0">
                        <td colspan="7">
                            loading...
                        </td>
                    </tr>
                    <tr data-ng-repeat="stock in stocks">
                        <td>
                            {{stock.Symbol}}
                        </td>
                        <td>
                            {{stock.Price | number:2}}
                        </td>
                        <td>
                            {{stock.DayOpen | number:2}}
                        </td>
                        <td>
                            {{stock.DayHigh | number:2}}
                        </td>
                        <td>
                            {{stock.DayLow | number:2}}
                        </td>
                        <td>
                            {{stock.Change}}
                        </td>
                        <td>
                            {{stock.PercentChange}}
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
        <h2>
            Live Stock Ticker</h2>
        <div id="stockTicker">
            <div class="inner">
                <ul>
                    <li class="loading" data-ng-show="stocks.length==0">loading...</li>
                    <li data-ng-repeat="stock in stocks" data-symbol="{{stock.Symbol}}"><span class="symbol">
                        {{stock.Symbol}}</span> <span class="price">{{stock.Price | number:2}}</span><span
                            class="change">{{stock.Change}} ({{stock.PercentChange}})</span>
                    </li>
                </ul>
            </div>
        </div>
    </div>


Open this page on a browser and the original stock ticker page on another browser window and play with the buttons. You will see both the screens with same data at any given point of time. The only difference would be the state of buttons, colour and scrolling list. We will fix them in the next post.




Happy coding! 

Hooking up ASP.NET SignalR with Angular JS

ASP.NET SignalR is a great framework to do real-time communication. I love this framework and I wrote some posts on it in the past. On the other hand, we have Angular JS, the super-heroic JavaScript library to build rich web applications. How about using these frameworks together to build an application with data getting pushed from server continuously and binding it on UI with nicely architected JavaScript code? It definitely sounds great. Let’s see it in action.

In this post, we will create a simple Hello World kind of application using SignalR and Angular JS. We will look at a more advanced scenario in a future post.

Creating Hub
Open Visual Studio (2010 or 2012) and create a new web application. Add SignalR’s NuGet package to this project. Add SignalR route to the Application_Start event of Global.asax as shown below:

protected void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.MapHubs();
}

Add a Hub class to this project and add the following code to it:
public class HelloWorldHub : Hub
{
    public void GreetAll()
    {
        Clients.All.acceptGreet("Good morning! The time is " + DateTime.Now.ToString());
    }
}


On client side
A client can communicate with hub either using a proxy script generated by SignalR or without using proxy. I personally like the no-proxy approach, as it is easier to take control over certain things when we follow this approach. In an Angular JS application, it is always recommended to wrap calls to data sources in a separate service. In such service, we need to take control to add callbacks easily. For this reason, we will follow the no-proxy approach. Following are the scripts required on the page:


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

The page will have a button and a span. When someone clicks on the button, method on the hub will be called to send a greeting message to all clients, which will be displayed on the span. Following is the mark-up on the page:
<div data-ng-app="app" data-ng-controller="SignalRAngularCtrl">
<input type="button" name="GreetAll" value="Greet All" data-ng-click="greetAll()" />
<span>{{text}}</span>
</div>

As stated earlier, the recommended way to call any external data source in Angular JS is using a custom service. We can create a factory or service to solve this purpose. In the following snippet, we create a new module and add a factory performing all SignalR operations to it:

var app = angular.module('app', []);
app.value('$', $);
        
app.factory('signalRSvc', function ($, $rootScope) {
    return {
        proxy: null,
        initialize: function (acceptGreetCallback) {
            //Getting the connection object
            connection = $.hubConnection();
 
            //Creating proxy
            this.proxy = connection.createHubProxy('helloWorldHub');
 
            //Starting connection
            connection.start();
 
            //Attaching a callback to handle acceptGreet client call
            this.proxy.on('acceptGreet', function (message) {
                $rootScope.$apply(function () {
                    acceptGreetCallback(message);
                });
            });
        },
        sendRequest: function (callback) {
            //Invoking greetAll method defined in hub
            this.proxy.invoke('greetAll');
        }
    }
});


Notice the callback passed to initialize method. This callback is a function defined in controller to set data received from server to a scope variable.

Also, notice the way the callback is invoked in proxy.on(). It is wrapped inside $rootScope.$apply(). This is because, the callback of proxy.on() gets executed outside Angular’s realm. Model modification done inside this function will not be processed unless it is called using $apply.

Finally, we need a controller to make everything work together.

function SignalRAngularCtrl($scope, signalRSvc) {
    $scope.text = "";
 
    $scope.greetAll = function () {
        signalRSvc.sendRequest();
    }
 
    updateGreetingMessage = function (text) {
        $scope.text = text;
    }

    signalRSvc.initialize(updateGreetingMessage);
}

As you see, the controller is pretty straight forward. As everything gets kicked off from controller, we need an object of the custom service, which is injected into the controller. The controller invokes the initialize method of the service as soon as it is instantiated. This is to start the connection and configure proxy with required callbacks.

Now open the page created above on two different browsers and click on button in one of the browser. You should be able to see a greeting message with current time.

Note: If you have finished reading this article and want to use your learning in a project, make a note to check this post as well: A Better Way of Using ASP.NET SignalR With Angular JS

Happy coding!

Monday, 17 December 2012

A Real-time chart using SignalR and Flot

I have discussed about SignalR in some of my earlier posts. I lately found Flot, a jQuery plugin that makes it very easy to create charts on HTML pages without doing a lot of work. Since both SignalR and Flot are based on jQuery at the client end, they work well together. In this post, we will see how to create a chart showing price of a stock that changes every second.


On Server Side

As we are using SignalR, we need a hub class. To represent a stock value object, we need a class with a couple of properties in it. Following is the StockValue class that we will use to send data to client:
public class StockValue
{
    public int Time { get; set; }
    public double Price { get; set; }
}

For this solution, I have used Visual Studio 2012 and SignalR 1.0 RC. There are a number of changes made to SignalR in this version. Following are the changes that we will be using in this post:

Calling a client function from Server: Clients.All.functionName(data);
Calling a server function from client: proxy.server.functionName(data);
Defining a JavaScript client function: proxy.client.functionName(data);

We need a StockMarket class that does the following tasks:

  • Initializes stock values
  • Updates the stock values after certain period
  • Sends the updated data to all clients
Code of this class is as follows:
public class StockMarket
    {
        public static readonly Lazy<StockMarket> market = new Lazy<StockMarket>(() => new StockMarket());
        static List<StockValue> stockValues;
        Timer _timer;
 
        public static StockMarket Instance
        {
            get
            {
                return market.Value;
            }
        }
 
        public void InitializeStockvalues()
        {
            stockValues = new List<StockValue>()
                {
                    new StockValue(){Time=10,Price=10.4},
                    new StockValue(){Time=20,Price=10.5},
                    new StockValue(){Time=30,Price=10.2},
                    new StockValue(){Time=40,Price=10.5}
                };
            GetClients().All.drawChart(stockValues);
        }
 
        public void GenerateNextStockValue(object state)
        {
            Random randomGenerator = new Random();
            int changeInCost = randomGenerator.Next(100, 110);
 
            var lastStockValue = stockValues[stockValues.Count - 1];
            var nextStockValue = new StockValue();
            nextStockValue.Time = lastStockValue.Time + 10;
            nextStockValue.Price = changeInCost / 10.0;
 
            stockValues.Add(nextStockValue);
 
            GetClients().All.drawChart(stockValues);
        }
 
        public void PublishPrices()
        {
            if (stockValues == null)
            {
                InitializeStockvalues();
            }
            else
            {
                GenerateNextStockValue(null);
            }
            _timer = new Timer(GenerateNextStockValue, null, 1000, 1000);
        }
 
        public IHubConnectionContext GetClients()
        {
            return GlobalHost.ConnectionManager.GetHubContext<StockValuesHub>().Clients;
        }
    }

Finally, we need a Hub class to kick off the process on the server. The hub class is very simple as we have assigned most of the responsibilities to StockMarket class.
public class StockValuesHub : Hub
    {
        public void GetStockValues()
        {
            StockMarket.Instance.PublishPrices();
        }
    }


On Client Side

On the client HTML page, we need to add references to following JavaScript libraries:
  • jQuery library
  • SignalR jQuery library
  • Flot jQuery library
  • Reference to SignalR’s dynamic proxy library

Flot requires a div element to render chart. So, let’s add the following div element to our page:

<div id="canvasChart" style="height: 300px; width: 300px;"></div>

On page load, we need to invoke the GetStockValues() function to start the process.
var hub = $.connection.stockValuesHub;
var dataToChart = [];
 
$.connection.hub.start()
    .done(function () {
        hub.server.getStockValues();
     });

We need to define the drawChart function on client to consume the data sent by server and render the chart. It involves a bit of logic as Flot doesn’t operate on JSON data. We need to convert our data to a form that Flot understands.

Flot accepts values in the form of an array. In the API documentation of Flot, it is specified that, Flot accepts values in the form of an array of a series. Following is an example of the data to be passed into Flot (copied from API documentation):

[ [1, 3], [2, 14.01], [3.5, 3.14] ]

Since SignalR sends JSON data, we need to convert the data to above format before we render the chart. Each object in the collection has to be converted to an array with two elements. Following function does this job for us:

function convertToArray(data) {
    var dataArray = [];
    dataArray.push(data.Time);
    dataArray.push(data.Price);
    return dataArray;
}

Finally, let’s add the drawChart function to client proxy. Implementation of this function is pretty straight forward.
hub.client.drawChart = function (data) {
    if (dataToChart.length == 0) {
        $.each(data, function () {
            dataToChart.push(convertToArray(this));
        });
    }
    else {
        dataToChart.push(convertToArray(data[data.length - 1]));
    }
    $.plot($("#canvasChart"), [dataToChart]);
};


You can download the complete code here.

Happy Coding!

Tuesday, 2 October 2012

Injecting dependencies into SignalR hub using Unity

In one of my earlier post, I discussed on Dependency Injection with SignalR using Ninject. In this post, we will see how to do it with Unity.

We had a NuGet package available to make our work easier to work with Ninject. We don’t have such a package for Unity. The only difference is that, we need to write one more small class to make the things work.

We need to define a dependency resolver that derives from SignalR.DefaultDependencyProvider and override the methods GetService and GetServices. This implementation is shown below:

public class UnityDependencyResolver : DefaultDependencyResolver
{
        IUnityContainer container;
 
        public UnityDependencyResolver(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container", "Containet cannot be null");
            }
            this.container = container;
        }
 
        public override object GetService(Type serviceType)
        {
            return base.GetService(serviceType) ?? container.Resolve(serviceType);
        }
 
        public override IEnumerable<object> GetServices(Type serviceType)
        {
            return base.GetServices(serviceType) ?? container.ResolveAll(serviceType);
        }
}

We have to register the requested types and target types to the container as shown below:
public static class UnityIoC
{
    public static IUnityContainer Initialize()
    {
        IUnityContainer container = new UnityContainer();
        container.RegisterType<ICustomerRepository, CustomerRepository>();
        container.RegisterType<IJavaScriptMinifier, NullJavaScriptMinifier>();
        return container;
    }
}

In this case, I registered the target type for IJavaScriptMinifier as Unity fails to work without this registration. Ninject and StructureMap don’t need this type to be registered. As last step, we need to set the resolver to RouteTable.Route.MapHubs when the application starts.
public class Global : System.Web.HttpApplication
{ 
    void Application_Start(object sender, EventArgs e)
    {
        GlobalHost.DependencyResolver = new UnityDependencyResolver(UnityIoC.Initialize());
        RouteTable.Routes.MapHubs();            
    }
}

Important note: If you are using SignalR in an ASP.NET MVC project, then configure SignalR first and then ASP.NET MVC. Check SignalR wiki for more details.

Happy Coding!

Sunday, 9 September 2012

Injecting dependencies into SignalR hub using Ninject

Hub is the key component for SignalR on the server. We put the key functional logic in the hub class. So, it is very much possible that we will have to access database or files on the server from the hub class. This dependency may make the hub less testable.

To avoid such difficulties, we will have to implement Dependency Inversion Principle. The hub has to contain an abstract reference of the dependency. An object of the concrete implementation of the abstract type will be injected into the hub using an Inversion of Control (IoC) container. This makes the hub less dependent on the concrete implementation, hence testable in isolation. Inversion of Control is a huge topic to discuss. If you are new to IoC, read this nice post by Joel Abrahamsson. If you have a subscription to Pluralsight, watch the course on Inversion of Control by John Sonmez.

In .NET, we inject the dependencies into a class using a library known as Inversion of Control container or IoC container. There are several implementations of IoC containers. Some of them are: 

  • Ninject
  • Unity
  • Structure Map
  • Castle Windsor
  • MEF

Usage of the IoC containers differs from each other. Before using any of these libraries, we have to learn and understand the syntax using which we configure the types and the way in which we have to resolve them.

SignalR has a dependency resolver class (SignalR.DefaultDependencyResolver). This class is used by the SignalR library to resolve all the dependencies. You may check the source code on GitHub to know what this class does. To inject the dependencies in our application, we have to write a class that derives from the DefaultDependencyResolver class. We have to override the GetService and GetServices methods. The logic in these methods is responsible to accept the abstract type and return an object of the concrete implementation.


For example, say the hub class talks to a database. In enterprise applications, we use the Repository Pattern to perform database operations. Say ICustomerRepository is a repository interface and CustomerRepository is the concrete implementation of this interface.
public interface ICustomerRepository
{
 void AddCustomer(Customer customer);
 void ModifyCustomer(Customer customer);
 IEnumerable<Customer> GetCustomersByDepartment(string departmentId);
}
public class CustomerRepository : ICustomerRepository
{
 //concrete implementations of the methods
} 

Following snippet shows an incomplete implementation of a Hub using the above repository:
public class CustmerHub : Hub
{
 ICustomerRepository repository;
 public CustmerHub(ICustomerRepository repository)
 {
  this.repository = repository;
 }
 …
}

An object of CustomerRepository type has to be injected into the CustomerHub from an external agent. Add the NuGet package for Ninject to the application.


Now we need to create our own dependency resolver by extending DefaultDependencyResolver. Following is the implementation for Ninject:
public class NinjectDependencyResolver:DefaultDependencyResolver
{
    private readonly IKernel _kernel;
 
    public NinjectDependencyResolver(IKernel kernel)
    {
        if (kernel == null)
        {
            throw new ArgumentNullException("kernel");
        }
 
        _kernel = kernel;
    }
 
    public override object GetService(Type serviceType)
    {
        var service = _kernel.TryGet(serviceType) ?? base.GetService(serviceType);
        return service;
    }
 
    public override IEnumerable<object> GetServices(Type serviceType)
    {
        var services = _kernel.GetAll(serviceType).Concat(base.GetServices(serviceType));
        return services;
    }
}

We have to configure requested types and target types so that Ninject will be able to return the right objects when they are requested. Following class does this for us:
public static class NinjectIoC
{
    public static IKernel Initialize()
    {
        IKernel kernel = new StandardKernel();
        kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
        kernel.Bind<RequestedType>().To<TargeTtype>();
        return kernel;
    }
}

Finally, we need to set the resolver to RouteTable.Route.MapHubs when the application starts.
public class Global : System.Web.HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        GlobalHost.DependencyResolver = new NinjectDependencyResolver(NinjectIoC.Initialize());
        RouteTable.Routes.MapHubs();
    }
}

With this step, we have set the dependency resolver to SignalR. Whenever it needs to resolve a dependency, the control will be passed to NinjectDependencyResolver to create the object.

Important note: If you are using SignalR in an ASP.NET MVC project, then configure SignalR first and then ASP.NET MVC. Check SignalR wiki for more details.

Happy coding!

Wednesday, 5 September 2012

SignalR hub communication without using proxy and cross-domain communication

In my previous posts on SignalR, I was using the auto generated proxy script /signalr/hubs to connect and communicate with the server. Doing so, we are asking the client browser to download an additional script. If the hub consists of a number of methods or if there are multiple hubs defined on the server side, the script file will be bulky. Also, it is may not be possible to compress and minify the script file as it is generated dynamically. In this post, we will discuss about communication with hub without using the proxy script file.


The following listing shows connecting, creating proxy, calling a server function and handling callback.

Establishing connection with the server:
var connection = $.hubConnection();

Creating a proxy object of the Hub class on the server:
var proxy = connection.createHubProxy(‘hub-name’)

Starting the hub:
connection.start();

Invoking a server function:
proxy.invoke(‘function-name’);

Handling callback:
proxy.on(‘callback-name’,function(arg1, arg2, …){
 //function body
});

In my previous post, I created a small market application that modifies and displays prices of gold and silver. Let’s add another client page to that application. In this page, we will communicate with server without using the proxy script.

If you haven’t downloaded the code yet, download it now and run it on your PC.

Add a new HTML page to this application. Copy the references of script files (except the reference of /signalr/hubs script) and the mark-up inside the body tag from the GoldSilverPrices.html page into this page.


Handle jQuery’s ready event and initialize the variables and objects as shown:

$(function(){
var up = '▲';
var down = '▼';
var goldPriceSpan = $("#goldPrice");
var silverPriceSpan = $("#silverPrice");
var goldPriceHtml;
var silverPriceHtml;
var gsPrices = new Array();

gsPrices[0] = 0;
gsPrices[1] = 0;
});

Establish connection to the hub:
var connection = $.hubConnection();

Create the proxy object:
var proxy = connection.createHubProxy('priceHub');

Start the connection and invoke the getPrices function once the connection starts:
connection.start().done(function () {
 proxy.invoke('getPrices');
});

Handle the callback function using proxy.on:
proxy.on("populatePrices", function (prices) {
    if (gsPrices[0] != 0 && gsPrices[1] != 0) {
        if (gsPrices[0] < prices[0]) {
            goldPriceHtml = prices[0] + " " + up;
            goldPriceSpan.css("color", "green");
        }
        else if (gsPrices[0] > prices[0]) {
            goldPriceHtml = prices[0] + " " + down;
            goldPriceSpan.css("color", "red");
        }

        if (gsPrices[1] < prices[1]) {
            silverPriceHtml = prices[1] + " " + up;
            silverPriceSpan.css("color", "green");
        }
        else if (gsPrices[1] > prices[1]) {
            silverPriceHtml = prices[1] + " " + down;
            silverPriceSpan.css("color", "red");
        }
    }
    else {
        goldPriceHtml = prices[0];
        silverPriceHtml = prices[1];
    }

    goldPriceSpan.html(goldPriceHtml);
    silverPriceSpan.html(silverPriceHtml);
    gsPrices = prices;
    });
});

Open this page on the browser. This page should behave the same way as the other client page. We followed the same set of steps to create the client page. But, we used a different set of functions defined in the SignalR client script library to make the page functional.


Cross-domain communication

Now, let’s separate the client from the server. Create a new ASP.NET Empty application and add the NuGet package SignalR.Js to it. SignalR.Js consists of SignalR’s JavaScript client libraries alone, it doesn’t include the .NET assembly references.

Copy the client page created above to this project. Also, add the images which are used in the previous application. The only change to be made to this client page to make it work is passing URL while connecting to the hub:
var connection = $.hubConnection("http://localhost:port-no");

That’s it! View this page on the browser. Run the admin page and change the values. All clients should be in sync with the data modified on the admin page.


Happy coding!