Introduction to WebSockets with SignalR in .NET Part 5: dependency injection in Hub

Introduction

We’ve now gone through the basics of SignalR. We’ve looked at a messaging project and a primitive, but working stock ticker. Actually most of the work is put on the client in form of JavaScript code. The WebSockets specific server side code is not too complex and follows standard C# coding syntax.

However, the relative server side simplicity doesn’t mean that our code shouldn’t follow good software engineering principles. I mean principles such as SOLID, with special subjective weight given to my favourite, the letter ‘D‘.

You’ll recall from the previous post that the stock prices were retrieved from a concrete StockService class, an instance of which was created within the body of StartStockMonitoring(). The goal now is to clean up that code so that the stock prices are retrieved from an interface instead of a concrete class. The interface should then be a parameter of the ResultsHub constructor.

We’ll use StructureMap to inject the dependency into ResultsHub.cs.

Demo

I’ll use two sources from StackOverflow to solve the problem:

Let’s start by creating the abstraction. Add the following interface to the Stocks folder:

public interface IStockService
{
	dynamic GetStockPrices();
}

Then modify the StockService declaration so that it implements the abstraction:

public class StockService : IStockService

Change the ResultsHub constructor to accept the interface dependency:

private readonly IStockService _stockService;

public ResultsHub(IStockService stockService)
{
	if (stockService == null) throw new ArgumentNullException("StockService");
	_stockService = stockService;
	StartStockMonitoring();
}

Make sure you refer to the private field in the Task body of StartStockMonitoring:

Task stockMonitoringTask = Task.Factory.StartNew(async () =>
				{					
					while(true)
					{
						dynamic stockPriceCollection = _stockService.GetStockPrices();
						Clients.All.newStockPrices(stockPriceCollection);
						await Task.Delay(5000);
					}
				}, TaskCreationOptions.LongRunning);

Next, create an interface for ResultsHub in the Stocks folder:

public interface IResultsHub
{
	void Hello();
	void SendMessage(String message);
}

…and have ResultsHub implement it:

public class ResultsHub : Hub, IResultsHub

Next import the StructureMap NuGet package:

StructureMap NuGet package

We’ll need a custom HubActivator to find the implementation of IResultsHub through StructureMap. Add the following class to the solution:

public class HubActivator : IHubActivator
{
	private readonly IContainer container;

	public HubActivator(IContainer container)
	{
		this.container = container;
	}

	public IHub Create(HubDescriptor descriptor)
	{
		return (IHub)container.GetInstance(descriptor.HubType);
	}
}

IContainer is located in the StructureMap namespace.

Next insert the following class that will initialise the StructureMap container:

public static class IoC
{
	public static IContainer Initialise()
	{
		ObjectFactory.Initialize(x =>
			{
				x.Scan(scan =>
					{
						scan.AssemblyContainingType<IResultsHub>();
						scan.WithDefaultConventions();
					});
			});
		return ObjectFactory.Container;
	}
}

The last step is to register our hub activator when the application starts. Add the following code to Application_Start() in Global.asax.cs:

IContainer container = IoC.Initialise();
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new HubActivator(container));

That’s it actually. Set a breakpoint within the ResultsHub constructor and start the application. If all goes well then code execution should stop at the breakpoint. Inspect the incoming stockService parameter. If it’s null then something’s gone wrong but it shouldn’t be. Let the code execution continue and you’ll see that it works as before except that we’ve come a good step closer to loosely coupled code.

Read the finishing post in this series here.

View the list of posts on Messaging here.

Advertisements

Introduction to WebSockets with SignalR in .NET Part 4: stock price ticker

Introduction

In the last post we saw the first basic, yet complete example of SignalR in action. We demonstrated the core functionality of a messaging application where messages are shown on screen in real time.

We’re now ready to implement the demo that I promised before: update a stock price in real time and propagate the changes to all listening browsers.

We’ll build on the sample project we’ve been working on so far in this series, so have it open and let’s get into it!

Demo: server side

Add a folder to the solution called Stocks. Add a new class called Stock:

public class Stock
{
	public Stock(String name)
	{
		Name = name;
	}

	public string Name { get; set; }
	public double CurrentPrice 
	{
		get
		{
			Random random = new Random();
			return random.NextDouble() * 10.0;
		}
	}
}

We need a stock name in the constructor. We’ll simply randomize the stock price using Random.NextDouble(). In reality it will be some proper repository that does this but again, we’ll keep the example simple.

Next add a new class called StockService which will wrap stock-related methods.

Note that such service classes should be hidden behind an interface and injected into the consuming class to avoid tight coupling. However, for this sample we’ll ignore all such “noise” and concentrate on the subject matter. If you’re not sure what I’m on about then read about dependency inversion here. The next post on SignalR will explore dependency injection.

StockService takes the following form:

public class StockService
{
	private List<Stock> _stocks;

	public StockService()
	{
		_stocks = new List<Stock>();
		_stocks.Add(new Stock("GreatCompany"));
		_stocks.Add(new Stock("NiceCompany"));
		_stocks.Add(new Stock("EvilCompany"));
	}

	public dynamic GetStockPrices()
	{
		return _stocks.Select(s => new { name = s.Name, price = s.CurrentPrice });
	}
}

We maintain a list of companies whose stocks are monitored. We return an anonymous class for each Stock in the list, hence the dynamic keyword.

We’ll read these values from our ResultsHub hub. We’ll need to constantly monitor the stock prices in a loop on a separate thread so that it doesn’t block all other code. This calls for a Task from the Task Parallel Library. If you don’t know what Tasks are then check out the first couple of posts on TPL here, a basic knowledge will suffice. We’ll need to start monitoring the prices as soon as someone opens the page in a browser. We can start the process directly from the hub constructor:

public ResultsHub()
{
	StartStockMonitoring();
}

private void StartStockMonitoring()
{
	
}

Here’s the complete StartStockMonitoring method:

private void StartStockMonitoring()
{
	Task stockMonitoringTask = Task.Factory.StartNew(async () =>
		{
			StockService stockService = new StockService();
			while(true)
			{
				dynamic stockPriceCollection = stockService.GetStockPrices();
				Clients.All.newStockPrices(stockPriceCollection);
				await Task.Delay(5000);
			}
		}, TaskCreationOptions.LongRunning);
}

We start a task that instantiates a stock service and starts an infinite loop. We retrieve the stock prices and inform all clients through a newStockPrices JavaScript method and pass in the stock prices dynamic object. Then we pause the loop for 5 seconds using Task.Delay. Task.Delay returns an awaitable task so we need the await keyword. In order for that to take effect through we’ll need to decorate the lambda expression with async. You’ve never heard of await and async? Start here. Finally, we notify the task scheduler in the task constructor that this will be a long running process.

Demo: client side

Let’s extend our GUI and results.js to show the stock prices in real time. We’ll use a similar approach as we had in case of the messaging demo: knockout.js with a view-model. Add the following code to results.js:

resultsHub.client.newStockPrices = function (stockPrices) {
     viewModel.addStockPrices(stockPrices);
}

…which will be the JS function that’s called from ResultsHub.StartStockMonitoring. We’ll complete the addStockPrices later, we need some building blocks first. We’ll need a new custom JS object to store a single stock. Add the following constructor function to results.js:

var stock = function (stockName, price) {
        this.stockName = stockName;
        this.price = price;
};

Also, we need a new property in the messageModel constructor function to store the stock prices in an array:

var messageModel = function () {
        this.registeredMessage = ko.observable(""),
        this.registeredMessageList = ko.observableArray(),
        this.stockPrices = ko.observableArray()
    };

Add the following function property to messageModel.prototype:

addStockPrices: function (updatedStockPrices) {
            var self = this;     

            $.each(updatedStockPrices, function (index, updatedStockPrice) {
                var stockEntry = new stock(updatedStockPrice.name, updatedStockPrice.price);
                self.stockPrices.push(stockEntry);                
            });
}

We simply add each update to the observable stockPrices array. updatedStockPrice.name and updatedStockPrice.price come from our dynamic function in StockService:

public dynamic GetStockPrices()
{
	return _stocks.Select(s => new { name = s.Name, price = s.CurrentPrice });
}

We just need some extra HTML in Index.cshtml:

<div data-bind="foreach:stockPrices">
    <p><span data-bind="text:stockName"></span>: <span data-bind="text:price"></span></p>
</div>

The stockName and price properties in the text bindings come from the stock object in results.js.

This should be it. Start the application and you’ll see the list of stocks and their most recent prices coming in from the server in a textual form.

View the next part of this series here.

View the list of posts on Messaging here.

Introduction to WebSockets with SignalR in .NET Part 1: the basics

Introduction

The normal communication flow between a browser and a web app on a server is quite limited: the client sends a HTTP request to the server and receives a HTTP response back. If the client needs some new information then it will need to send another request to the server. Normally a web server will not just send out HTTP responses to a client without a HTTP request first to act upon.

This is true even for pages where you view the same type of data which is updated periodically. A typical example is a sports site where you can view the current standing of a game. You as the viewer would probably like to have real time updates so that you can be happy when your team scores – or smash your smart phone against the wall if it’s losing.

There are various ways to solve this problem on a web site:

  • Put a big “Refresh” button on the page which requests and updated set of objects from the server – very straightforward, but not too convenient for the client
  • Put some kind of JavaScript timer function on the web page which periodically requests an update from the server and refreshes the page
  • Same as above but use an Ajax call to only refresh the page partially

…and possibly others.

The underlying method with all three solutions is that the browser will need to keep sending the same request to the server over and over again. Imagine that this site is very popular so their server receives tens of thousands of essentially the same request. The company will need to invest in extra infrastructure, such as a web farm, a load balancer, CDN etc. Wouldn’t it be easier if the browser could tell the server: “hey, server, I need updates from you on the same set of data periodically, thanks.” And then the communication channel is magically kept open between the client and the server. The server will be able to send updates over that channel automatically without waiting for new requests. This can potentially result in an alleviated server load, a very responsive web UI and significant savings for the company in terms of reduced infrastructure.

Web Sockets

These communication channels through Web Sockets have been available for some years now, so it’s not some kind of a dream. A web socket is a TCP socket connection between the client and the server. This socket is maintained between two parties. It is a two-way full duplex communication channel: the client can send data to the server and the server can send data back to the client over the same channel at any time.

The protocol for a web socket is “ws”, such as “ws://mysite.com”. Similarly a secure web socket follows the “wss” scheme. Note that not all browsers support web sockets. Check out the table on this web site to see which browsers support it.

SignalR is a technology that alleviates the burden of setting up a web app which uses web sockets. There are many things you need to take care of with web sockets communication: serialising data, deserialising data, maintaining the connection, processing messages that arrive in no particular order. SignalR simplifies the construction of sockets-aware web apps by hiding a lot of the underlying complexity. You as a developer can then concentrate on the fun parts instead of worrying too much about low level details. SignalR can even help older browsers “understand” web sockets by emulating its behaviour.

So what’s SignalR?

As hinted on above SignalR is a Microsoft framework that makes working with web sockets easier for the programmer. You can make it available in your web project by downloading the Microsoft.AspNet.SignalR NuGet package. The most recent version at the time of writing this post is 2.0.3:

SignalR Nuget package

By the time you read this post there might be an updated package. If you see that some functionality described in this blog series is not compatible with a newer version then please comment about it and then I’ll update the posts.

As we said before Web Sockets can be quite challenging to work with if you try to do so using some low-level JavaScript package. WebSockets is not the only type of connection that enables real-time two-way communication between the client and the server. Here come some more:

SignalR will test all 4 of these until it finds one that’s available. It always tries WebSockets first as it is the the most efficient one of the 4 as far as overhead is concerned. Normally if the browser supports WebSockets then it can be used for communication. However, this is not always the case. In that case it will test the other three one after the other.

For WebSockets to succeed then even the web server will need to support this technology. You are presumably a .NET web developer so chances are high that you’ll deploy your web app on IIS. Only IIS8 and above will support WebSockets. I have Window8.1 on the PC I’m building the demo on but IIS8 should be available on Windows8 as well. The built-in IIS Express server of Visual Studio 2013 supports WebSockets. If you’d like to deploy and test your web app locally on your PC then search for IIS on your PC. If you don’t find it then you’ll need to enable it first:

Turn windows features on and off

Enable IIS

Also enable the WebSocket feature:

Enable WebSockets

Start IIS and check its version:

Check IIS version

If you’re deploying your app an Windows Server then you’ll need Windows Server 2012 and you’ll need to enable the WebSocket feature as shown above.

The SignalR NuGet package will enable us to work with both the client side and server side part of the communication. On the server side the most important component we’ll work with is called a Hub which is a class that hides the implementation details of the communication on the server side. On the client side we’ll need some JavaScript code that can be called by SignalR to connect to this Hub.

In the next post we’ll start our demo.

View the list of posts on Messaging here.

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: