SignalR with Ext.NET

SignalR promises a great evolution of real-time interactivity in web applications. It is also something that can be used with Ext.NET.

In this post we briefly look at what SignalR is and how it works. We then look at how Ext.NET can be used with SignalR by modifying a stock ticker example provided by the SignalR project. Lastly we look at some remaining things to be aware of if looking into using SignalR right now.

What is SignalR?

SignalR is an ASP.NET library making it easier to create real time web applications.

The Web experience is traditionally a pull based approach — browsers pull requests from the server. And AJAX builds on top of that.

HTML5 has long discussed server side push, without the need for plugins and applets. Server Sent Push and more recently Web Sockets are the powerful features modern browsers are incorporating.

If a server can simply notify the connecting browser when it is ready then it opens the doors to many possibilities. For example,

  • Chat applications
  • Collaborative working
  • Notification of system changes
  • And so on

As an example, imagine a backoffice application, such as one to manage products for an ecommerce web site. Suppose you are updating product information. In the meanwhile a colleague logs into the same application and starts looking at it. There is of course the risk that one could override the other’s changes.

Using SignalR you could both be notified that others are looking at the same data. Maybe you are given an option to chat about it (“hey, lets coordinate what we are going to edit here.”) Or, maybe the app could lock it for others until you are done with it, and so on.

Perhaps the ecommerce app is getting an incoming feed of updated data from third parties or other systems (e.g. updated order or stock data). The server could notify any browsers connected, offering to update relevant information straight away.

How does SignalR work?

SignalR has libraries for the server side (.NET) and client side (both .NET clients and JavaScript clients). As different browsers have different capabilities, SignalR takes advantage of graceful degradation to determine which transport to use when communicating from a browser to a server:

SignalR uses a fallback mechanism to connect the browser to the server. After an initial negotiation request the following transports are tried in order until a successful connection can be made:

  • WebSockets (if the both the server and browser indicate they can support WebSockets)
  • Server Sent Events, aka EventSource (if the browser supports Server Sent Events, which is basically all browsers except Internet Explorer)
  • Forever Frame (for Internet Explorer only)
  • AJAX long polling

WebSockets is the only true full-duplex connection transport. All other transports listed here use the technique/technology named for the incoming data from the server, and standard AJAX POSTs for sends from the client to the server.

SignalR FAQ (as of March 16, 2013)

Unlike general HTTP, a SignalR client will make a persistent connection to the server (in the case of WebSockets, they are truly persistent; for others various techniques are used to make it appear like that). It is on GitHub so you can have a look at how they are progressing it.

On the server side, you have Hubs that provide a high level abstraction for all the message pushing you will do. With your hubs you can push messages to all clients or specific groups of clients or individual clients. These hubs use dynamic methods and other such properties and result in dynamically generated proxies for the client to talk to the server (so on both client and server, you do not worry about low level transport/socket coding, but instead just do regular method calls). It ends up looking like RPC.

For a really quick and simple overview of how it works, I highly recommend you check out Scott Hanselman’s video on SignalR. It is just a few minutes, but really clearly explains everything you need to know to get started!

 

Why not just stick with AJAX?

AJAX based applications are immensely powerful, no doubt.

The above ecommerce backoffice scenarios could all be implemented with AJAX. However, to do that you would need to continuously poll the server. This can be wasteful. Instead with the client just waiting for notification events from the server, bandwidth and resources on both client and server are reduced.

SignalR, in effect, gets closer to more traditional client/server programming paradigms.

What does this have to do with Ext.NET?

There are a number of useful sample applications that Microsoft have provided to demonstrate SignalR, including a chat application, a stock ticker, and more.

Their examples are based on jQuery + HTML.

But this blog post demonstrates very briefly that the same techniques can just as easily be used with Ext.NET, so that your Ext.NET applications can potentially benefit from SignalR.

Note, we won’t look at how the StockTicker hub was created in the original GitHub project that I forked. For an overview of hubs and other aspects of implementing SignalR do look at that short video mentioned above!

Converting the SignalR StockTicker Demo into an Ext.NET friendly one

There’s a project at GitHub demonstrating a simple fake stock ticker application using SignalR.

When you run the sample page, you get this:

Original SignalR stock ticker example
Original SignalR stock ticker example

The above screenshot shows a simple table on a page. When run, as updated stock values (fake ones!) are available from the server, they automatically update and various rows highlight momentarily in green or red depending on whether the price went up or down. The buttons above the table also show the market is already open (hence it is now disabled).

If you now open the same page on another browser it will start to show the same data automatically. If you close the market, all browsers will get the close event simultaneously. It is a nice way to see SignalR in action.

So I thought this would be a nice example to convert into an Ext.NET GridPanel instead. I forked the sample project on GitHub so you can get the full source code here:
https://github.com/anupshah/ExtNET-SignalR-StockTicker.

The end result is the same data but showing up on an Ext.NET Grid Panel:

Ext.NET GridPanel Stock Ticker example using SignalR
Ext.NET GridPanel Stock Ticker example using SignalR

In my fork I simply included Ext.NET 2 from NuGet. Here is the overall approach to the code changes I then made:

  1. Created a custom Ext.NET component that inherits the GridPanel (both .NET side and JavaScript side)
  2. Initiated the SignalR connection from the custom GridPanel’s JavaScript class
  3. Updated the GridPanel’s Store as and when data from the SignalR connection comes in
  4. Highlighted updated rows using a fade technique for a similar effect as the original example

Note, I didn’t re-implement the ticker below the table that scrolls across, but the same ideas can be applied there if you wish to try it. In addition, I did not need to make any changes to their StockTicker hub class; I just reused it (and therefore the client proxy that it generates without any need for alterations for it to work with Ext.NET).

Custom Ext.NET GridComponent (C#)

using Ext.Net;

namespace Microsoft.AspNet.SignalR.StockTicker.Ext.NETSignalR.StockTicker
{
    public class SignalRGridPanel : GridPanel
    {
        public override string XType
        {
            get { return "signalrgridpanel"; }
        }

        public override string InstanceOf
        {
            get { return "ExtNetSignalRDemo.SignalRGridPanel"; }
        }

        protected override void OnInit(EventArgs e)
        {
            BuildTopBar();
            BuildStore();
            BuildColumns();
            BuildView();

            base.OnInit(e);
        }

        // All the private Build* methods omitted for brevity
        // Download the code from GitHub to see the details
    }
} 

This subclass of GridPanel sets the XType and InstanceOf so that we can put our custom JavaScript inside a subclass of GridPanel on the client side. It then builds the grid here inside the component to demonstrate this being a fully self-contained and therefore much more reusable component. See the full source at GitHub to see how it is all set.

For the JavaScript definition of the custom GridPanel, here is an outline:

Ext.define(‘ExtNetSignalRDemo.SignalRGridPanel’, {
    extend : ‘Ext.grid.Panel’,
    alias  : ‘widget.signalrgridpanel’,

    // the SignalR generated client-side hub proxy
    ticker : $.connection.stockTicker,

    // more configuration options here

    initComponent: function (config) {
        this.callParent(config);

        this.on(‘afterrender’, this.onAfterRender, null, { single: true });
    },

    // …

    onAfterRender: function () {
        // initialize the SignalR connection
    }
}); 

So, simply put, after the GridPanel is rendered, we will initialize the SignalR connection to the server and deal with the various operations that are possible. Notice there is a property called ticker which holds a reference to the client-side hub proxy for the stockTicker created by the SignalR components. Here is onAfterRender:

onAfterRender: function () {
    var gridInstance = this,
        store = gridInstance.getStore(),
        ticker = gridInstance.ticker;

    function init() {
        return ticker.server.getAllStocks().done(function (stocks) {
            $.each(stocks, function () {
                store.load(stocks);
            });
        });
    }

    // Client-side hub methods that the server will call
    $.extend(ticker.client, {
        updateStockPrice: function (stock) {
            var rowIndexOfStockItem = store.indexOfId(stock.Symbol),
                highlightRow = rowIndexOfStockItem,
                row, el, bgColor;

            if (rowIndexOfStockItem === -1) {
                store.loadData([stock], true);
                highlightRow = store.getCount();
            } else {
                store.getAt(rowIndexOfStockItem).set(stock);
            }

            row = gridInstance.getView().getNode(highlightRow);
            el = Ext.get(row);
            bgColor = stock.Change >= 0 ? gridInstance.upBgColor : gridInstance.downBgColor;

            if (el != null) {
                el.highlight(bgColor, { attr: ‘backgroundColor’, duration: 750 });
            }
        },

        marketOpened: function () {
            gridInstance.down("#btnOpen").setDisabled(true);
            gridInstance.down("#btnClose").setDisabled(false);
            gridInstance.down("#btnReset").setDisabled(true);
        },

        marketClosed: function () {
            gridInstance.down("#btnOpen").setDisabled(false);
            gridInstance.down("#btnClose").setDisabled(true);
            gridInstance.down("#btnReset").setDisabled(false);
        },

        marketReset: function () {
            return init();
        }
    });

    // Start the connection
    $.connection.hub.start()
        .pipe(init)
        .pipe(function () {
            return ticker.server.getMarketState();
        })
        .done(function (state) {
            if (state === ‘Open’) {
                ticker.client.marketOpened();
            } else {
                ticker.client.marketClosed();
            }
        });
} 

The above code is very similar to the JavaScript code for their original example, just refactored to be part of the Ext.NET custom GridPanel component.

In the above we see the ticker client extended with functions that will handle the messages sent by the server, such as updateStockPrice, marketOpened, marketClosed and marketReset.

Once those are set up, we simply start the hub connection.

In updateStockPrice we simply load the new stock data into the Store – we either add a new row if the symbol doesn’t exist in the grid already, or we update the row that contains the symbol with the new data. We then get the row element and using the Ext JS highlight method we flash the green or red indicator depending on the stock price.

To put it all together, we simply use the custom GridPanel on a page, which can be as simple as follows:

<ext:SignalRGridPanel ID="GridPanel1" runat="server" /> 

Remaining issues

It is worth being aware of some of the limitations or implications of using SignalR right now, as it is still early days for it. For example, consider the following:

Scaling out

Perhaps one of the main limiting factors about SignalR at the moment is that there is a single point of failure. Redundancy or scaling your servers with hardware is currently not supported. On the plus side, they are working on it (just in pre-alpha stage as of writing). See for example, https://github.com/SignalR/SignalR/wiki/Azure-service-bus.

Still, that should not stop you trying it out and getting familiar with it.

Depends on jQuery

A point to note, perhaps more minor, is that the client side implementation of SignalR has been done with jQuery. While jQuery is an awesome library itself and pairs nicely with Ext.NET (Ext JS), perhaps Microsoft could have provided its SignalR implementation independent of any other JavaScript framework at its core, but then provide mechanisms such as plugins to work with popular frameworks such as jQuery and others.

That being said, the need to include an additional library such as jQuery within an Ext.NET application could perhaps be worth it given the benefits that come along with it.

To take full advantage of WebSockets, you need IIS 8

In terms of pre-requisites be aware that while many modern browsers support HTML5 Web Sockets, only IIS8 on the server does (i.e. Windows 8/Windows Server 2012).

That being said, Windows Server 2008 (IIS 7.5) still works, but WebSockets will not be used; instead Server Sent Events will be used instead as the fallback. (I dev’d the Ext.NET stock ticker demo on Windows Server 2008 R2, for example.)

Links for further information

The following links were used in the above article, but are summarized here as useful starting points

6 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *