Simple Talk is now part of the Redgate Community hub - find out why

Using SignalR to Create Mobile Applications

SignalR isn't just for web applications. It can also provide the basic real-time communications for a connected Windows Universal Application or even iOS and Android applications. Christos Matskas demonstrates how to get started with creating applications across a range of platforms that require real-time communication using SignalR

SignalR is a powerful, open source library that allows developers to quickly and easily implement real-time communications across different platforms. Although SignalR is predominantly used in web applications, the library is versatile enough to be used in mobile apps as well. This means that you can implement native real-time connected applications without requiring the use of a web view. SignalR provides client libraries for .NET, JavaScript, Windows Phone, Windows Universal applications, iOS and Android.:p>

There are two ways to add SignalR to cross-platform mobile applications. For .NET developers, there is the option to “write-once deploy-everywhere, leveraging the power of C# and Xamarin. Xamarin is a 3rd party library that takes advantage of the .NET framework and provides a unified SDK that binds directly to the native libraries in order develop mobile applications. Because Xamarin works on top of the .NET framework, it means that all that’s needed in order to use SignalR is to add the necessary .dll to the solution, usually through NuGet.

If you don’t want to go down the route of Xamarin, there are also native ports of the SignalR library both in Objective-C and Java. For iOS development you can use this port (SignalR-ObjC), and for Android development there’s this port (SignalR/java-client). There is, however, a small caveat when using these ports: because these two libraries are not officially supported by the SignalR community, there is a chance that they may be out of date or have features missing.

In this article, we are going to develop a sample Windows Universal Application (store and mobile) and implement basic real-time communications between the application and a back-end service using SignalR.

The Server setup

To demonstrate the real-time communication framework, we are going to implement a sample stock price service.  Clients that are connected through SignalR will receive real-time stock prices when these are updated on the server. The server will use just a mock service to generate dummy prices for the purpose of this demo. In a production environment, this data would be coming from a real API.

The SignalR hub will be installed on a WebAPI 2.0 running on top of ASP.NET 4.5. The hub will only have one public method which will be used to broadcast the data to all connected clients. 

On a new, empty WebAPI solution in Visual Studio, open the NuGet console manager and run the following command:

This will install SignalR along with the necessary dependencies such as Owin (ASP.NET’s middleware framework). Owin is used to bootstrap SignalR and route all incoming SignalR requests to the hub.

By default, SignalR hubs are configured to reject incoming request from external domains. This means that if your SignalR hub (WebAPI) is running under the https://contoso.com and clients are trying to connect from https://mydomain.com, then the requests will fail with an HTTP 500 error.  To fix this problem, we can configure Owin to accept cross-domain requests (CORS).  Go back to the NuGet console manager and run the following command:

With the dependencies installed, we can now start configuring the hub. Right-click on the WebAPI project and add a new class. Name the class Startup.cs and paste the following code:

This code bootstraps SignalR and configures CORS in order to allow cross-domain clients to connect. At the moment all external clients can hit the hub because we defined CorsOption.AllowAll. Unless you wish to create a truly open API, it is advisable that you restrict access to the service.

Before we create the hub, we need a mock service to feed stock data to the clients. Add a new class to the project and name it StockService. Paste the following code in it:

The service is pretty basic. It creates a timer which is used to push stock data at a 5 second interval. There are a couple of extension methods that are used to generate random decimals. Add a new class to your project and name it Extensions. Paste the following code:

With the service in place, the last step in creating the service process is adding the SignalR hub to relay data to and from the clients. Right-click on the WebAPI project and add a new class. Name it StocksHub and paste the following code: 

I understand your surprise. The hub is, in fact, empty. We only use it to instantiate the StockService. This is the beauty of SignalR. The hub can act as the conduit -passing information back and forth between the client and some arbitrary back-end service. This is all we need to do to get a functional hub. Next, we’ll look into what’s required to allow a Windows Universal application to receive data from the SignalR hub.

The Client Setup

The steps used to enable SignalR on the Windows Universal apps are the exact same steps you would follow if you were working on a Xamarin application. Open up Visual Studio and create a new Windows Universal app. In the end, the solution should consist of 3 projects:

  •  Windows Phone Application
  • Windows Desktop Application
  • Shared project

We will use the shared project to add the common logic, such as the SignalR client and configuration settings. The individual projects will have only the UI specific logic necessary to display the data retrieved through SignalR.

We’ll start by adding the SignalR packages. Open the NuGet console manager and run the following command:

Next, open up App.xaml.cs and add the following public property and private method in the class:

Change the OnLaunched() method to be async by changing the method declaration like this:

and add the following line anywhere in the body of the method:

The above code will start up the client and connect to the remote hub in order to start receiving data. Next, since we’re working with XAML, we can take advantage of data binding so that we can update the UI asynchronously and automatically when new data is received. In the shared project, create a new class and name it PageData. Add the following code:

In a proper application, we would opt in for proper MVVM framework that can eliminate most of the above boiler plate code. Nonetheless, this is a demo app with limited requirements so there’s no reason to complicate the design and add unnecessary dependencies. Finally, we need to create the SignalR client. Add a new class to the shared project and name it SignalRClient. Paste the code below:

In the code above, we create a proxy and then we define an event handler that listens for a “sendStockData()” method. Notice how this event name matches exactly the StockService method we defined in our hub on the server. This instructs the client to raise an event every time the server calls that method. 

At the point of writing this, ‘Windows Universal apps’ seems to also suffer from a small bug when connecting to a hub. The connection process is particularly slow due to protocol failures. To resolve this problem, we need to define the transport protocol during our attempt to instantiate the connection. This is achieved here by requesting that the connection uses the Web Sockets protocol:

Finally, it’s worth noting that when creating a new HubConnection() we need to pass the hub URL, which is the same as the WebAPI URL. Make sure you use the right URL otherwise your connection will fail.

The last step is to update the UI in the phone and desktop apps to use the SignalR data. On the Windows phone project, open the MainWindow.xaml and replace the <Grid></Grid> root element with the code below:

<Grid.RowDefinitions>

            <RowDefinition Height=”150″></RowDefinition>

            <RowDefinition Height=”*”></RowDefinition>

        </Grid.RowDefinitions>

        <TextBlock Grid.Row=”0″ Style=”{StaticResource HeaderTextBlockStyle}” Margin=”25,0,0,0″>STOCK PRICES</TextBlock>

        <StackPanel Grid.Row=”1″ Margin=”25,0,0,0″>

            <StackPanel Orientation=”Horizontal”>

                <TextBlock Style=”{StaticResource BodyTextBlockStyle}” Width=”70″>GOOG:</TextBlock>

                <TextBlock Style=”{StaticResource BodyTextBlockStyle}” Text=”{Binding GOOG }”></TextBlock>

            </StackPanel>

            <StackPanel Orientation=”Horizontal”>

                <TextBlock Style=”{StaticResource BodyTextBlockStyle}” Width=”70″>MSFT:</TextBlock>

                <TextBlock  Style=”{StaticResource BodyTextBlockStyle}” Text=”{Binding MSFT}”></TextBlock>

            </StackPanel>

            <StackPanel Orientation=”Horizontal”>

                <TextBlock Style=”{StaticResource BodyTextBlockStyle}” Width=”70″>APPL:</TextBlock>

                <TextBlock Style=”{StaticResource BodyTextBlockStyle}” Text=”{Binding APPL}”></TextBlock>

            </StackPanel>

        </StackPanel>

We also need to add the necessary code to retrieve and bind the data to the UI View, so open MainView.xaml.cs and paste the code below:

Since this is a universal application, we need to apply similar code changes to the Windows Store project. Go to the MainView.xaml and paste the following code, which should replace the root <Grid></Grid> element:

<Grid Background=”{ThemeResource ApplicationPageBackgroundThemeBrush}”>

        <Grid.RowDefinitions>

            <RowDefinition Height=”150″></RowDefinition>

            <RowDefinition Height=”*”></RowDefinition>

        </Grid.RowDefinitions>

        <TextBlock Grid.Row=”0″ Style=”{StaticResource HeaderTextBlockStyle}” Margin=”25,20,0,0″>STOCK PRICES</TextBlock>

        <StackPanel Grid.Row=”1″ Margin=”25,0,0,0″>

            <StackPanel Orientation=”Horizontal”>

                <TextBlock Style=”{StaticResource SubheaderTextBlockStyle}” Width=”120″>GOOG:</TextBlock>

                <TextBlock Style=”{StaticResource SubheaderTextBlockStyle}” Text=”{Binding GOOG }”></TextBlock>

            </StackPanel>

            <StackPanel Orientation=”Horizontal”>

                <TextBlock Style=”{StaticResource SubheaderTextBlockStyle}” Width=”120″>MSFT:</TextBlock>

                <TextBlock  Style=”{StaticResource SubheaderTextBlockStyle}” Text=”{Binding MSFT}”></TextBlock>

            </StackPanel>

            <StackPanel Orientation=”Horizontal”>

                <TextBlock Style=”{StaticResource SubheaderTextBlockStyle}” Width=”120″>APPL:</TextBlock>

                <TextBlock Style=”{StaticResource SubheaderTextBlockStyle}” Text=”{Binding APPL}”></TextBlock>

            </StackPanel>

        </StackPanel>

    </Grid>

And the equivalent code-behind to provide the data for the view:

To test the whole system, run the WebAPI first and then run the Windows Phone and Store apps in the order you like. The end result should look like this:

2301-imgE4.jpg

2301-clip_image004.jpg

Conclusion

In this article, we saw how easy it is to get started with real-time communication across platforms using SignalR. It doesn’t matter if you’re targeting web, mobile or desktop platforms. In the end, we’ve proved that SignalR requires minimal code to provide something that in the past was clunky, unreliable and very hard to implement. I would like to close with Arthur C. Clarke’s quote – “Any sufficiently advanced technology is indistinguishable from magic“. SignalR is advanced enough to make real-time communications seem like magic.

How you log in to Simple Talk has changed

We now use Redgate ID (RGID). If you already have an RGID, we’ll try to match it to your account. If not, we’ll create one for you and connect it.

This won’t sign you up to anything or add you to any mailing lists. You can see our full privacy policy here.

Continue

Simple Talk now uses Redgate ID

If you already have a Redgate ID (RGID), sign in using your existing RGID credentials. If not, you can create one on the next screen.

This won’t sign you up to anything or add you to any mailing lists. You can see our full privacy policy here.

Continue