1 Comments

These days if you can write code with C# you can write code for Windows, Linux and OSX, your code can run on Desktop, Server, Mobile or Embedded Devices. So C# runs pretty much everywhere which if you are a C# developer is a great thing! Smile Only little hiccup, even though C# is a standardised language, there are multiple runtimes existing today on which C# runs. This may lead to the assumption of having to rewrite code for every runtime. As the standard .Net C# library can not be reused on a Silverlight runtime, or the new Windows RT runtime, or I think you get the message. But fear not – thanks to the Portable Class Library (PCL) one is able to write code that can be reused over multiple platforms.

Portable Class Libraries

When adding a Portable Class Library (PCL) you will have to choose which platforms you want to use the platform on. The supported platforms have an impact in the functionality the PCL provides without adding any additional libraries (usually via NuGet). You can find a list  of libraries supported by each platform on MSDN.

For this post we will want to reuse our code on the following platforms:

  • Universal Windows App (Windows 10)
  • Classic desktop WPF app
  • iOS (with Xamarin)
  • Android (with Xamarin)

To keep things simple the logic in the app will be creating a list of people. We will even be able to share our view models from the PCL so the only overhead we will be having when creating the app is the actual UI code and wiring up the view models to the actual views. Now in this setup the timesaving's might seem marginal but think about your standard business app and the savings will start to up add up quickly in a major way.

Creating a PCL

Adding the platform specific projects is pretty straight forward. Simply add the corresponding project template to the solution when adding a new project, so I’ll leave it at that and go over to adding a PCL. When adding the PCL a dialog will be opened offering to choose the platforms that shall be supported i.e. can consume the PCL.

Showing Add Portable Class Library Visual Studio dialog with .Net Framework 4.6, Windows Universal 10.0, Xamarin.Android and Xamarin.iOS selected

The iOS and Android option will show up after installing the Xamarin tool chain.

With the platforms chosen we can now start implementing the “business logic” which in our case is a simple generator that we invoke, called PersonService.cs:

public class PersonService
{
    public async Task<IEnumerable<Person>> GetPeople(int count = 42)
    {
        var people = new List<Person>(count);
        // In case of large counts lets be safe and not run this on the UI thread
        await Task.Run(() =>
        {
            for (int i = 0; i < count; ++i)
            {
                people.Add(new Person{FirstName = NameGenerator.GenRandomFirstName(), LastName = NameGenerator.GenRandomLastName()});
            }
        });

        return people;
    }
}

To present our data to the UI we will use the MVVM pattern.

Adding MVVM Light

When using MVVM in a project (which is like always for me Winking smile) I prefer using MVVM Light. MVVM Light can be added by simply installing a NuGet package:

PM> Install-Package MvvmLightLibs

As we will access the view models from the platforms make sure to add the MVVM Light libraries also to the platform specific code bases.

Now we can add the view model MainViewModel.cs that will hold the list of people we will display.

public class MainViewModel:ViewModelBase
{
    private readonly IPersonService _personService;

    public MainViewModel(IPersonService personService)
    {
        if (personService == null) throw new ArgumentNullException(nameof(personService));
        _personService = personService;
        if (IsInDesignMode)
        {
            People = new ObservableCollection<Person> {new Person{FirstName = "Doctor Who"}, new Person {FirstName = "Rose", LastName = "Tyler"}, new Person {FirstName = "River", LastName = "Song"} };
        }
        else
        {
            People = new ObservableCollection<Person>();
        }
    }

    public ObservableCollection<Person> People { get; set; }

    public async Task InitAsync()
    {
        var people = await _personService.GetPeople();
        People.Clear();
        foreach (var person in people)
        {
            People.Add(person);
        }
    }
}

Next we still need to configure the ViewModelLocator.cs, which allows us to easily manage dependencies.

public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<IPersonService, PersonService>();
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel MainViewModel => SimpleIoc.Default.GetInstance<MainViewModel>();
}

So now we have all of our cross platform code setup. Let’s get it running on our desired targets.

The platforms

On the platforms we can simple reference the PCL like any other library we might use and access the features. On our platforms we will have to do the following steps:

  1. Create the UI
  2. Hook up theViewModelLocator.cs
  3. Wire up the view model to the view

Let’s do these steps for the Universal Windows App.

Universal Windows App (UWA)

For the view we will simply add a ListView to the MainPage.xaml:

<Page
    x:Class="PclSample.UWA.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PclSample.UWA"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="..."
    mc:Ignorable="d">

    <ListView ItemsSource="{Binding People}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding FirstName}"/>
                <TextBlock Text="{Binding LastName}"/>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Page>

Under Windows (this is also true for WPF) MVVM Light really integrates really nicely. The Locator we can simply add to the App.xaml:

<Application
    x:Class="PclSample.UWA.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PclSample.UWA"
    RequestedTheme="Light">
    <Application.Resources>
        <vm:ViewModelLocator x:Key="Locator" xmlns:vm="using:PclSample.Core" />
        <ResourceDictionary />
    </Application.Resources>
</Application>

This allows us to access properties from the ViewModelLocator.cs class within our view(s) i.e. MainPage.xaml. So the next step would be wiring up the view model to the views DataContext, which will populate the view:

<Page
    x:Class="PclSample.UWA.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PclSample.UWA"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding Source={StaticResource Locator}, Path=MainViewModel}"
    mc:Ignorable="d">

    ...
</Page>

Now all is set and we can enjoy the view of our light weight UWA.

Screenshot of the UWA running in the Windows 10 Mobile Emulator

Windows Presentation Foundation (WPF)

Following the same steps as in the UWA in a WPF app will lead to the same result.

Shows sample app running in as a WPF desktop application

So we can reuse all of our business logic from one Microsoft client development model to an other one. Isn’t that just great? Smile But wait there is more. We can take the C# code outside of the Microsoft Ecosystem. With for example Xamarin we can reuse our C# code on iOS and Android.

iOS

Under iOS the UI is usually created in a designer (similar to Windows Forms) so there is not much code to show. We add the ListView equivalent from iOS a UITableView to a page and give it a name, in this sample PeopleTableView.

Showing iOS Designer and where the name of the UITableView is set.

Setting up the ViewModelLocator.cs is not quite as elegant when we leave the Microsoft platforms but then again it is done just as easily. In the AppDelegate.cs which is the start up point of every iOS app we simply create an Instance of the ViewModelLocator.cs and store it in a property. The property then can be accessed throughout the iOS app. The Wiring up of the view model is done in the ViewController.cs which is linked to the view that we setup earlier:

public partial class ViewController : UIViewController
{
    ObservableTableViewController<Person> _tableViewController;

    public ViewController (IntPtr handle) : base (handle)
    {
    }

    private MainViewModel Vm => Application.Locator.MainViewModel;

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        // Perform any additional setup after loading the view, typically from a nib.

        _tableViewController = Vm.People.GetController(CreatePersonCell, BindPersonCell);
        _tableViewController.TableView = PeopleTableView;
    }

    public override async void ViewWillAppear (bool animated)
    {
        base.ViewWillAppear (animated);
        await Vm.InitAsync();
    }

    public override void DidReceiveMemoryWarning ()
    {
        base.DidReceiveMemoryWarning ();
        // Release any cached data, images, etc that aren't in use.
    }

    UITableViewCell CreatePersonCell (Foundation.NSString reuseId)
    {
        var cell = new UITableViewCell(UITableViewCellStyle.Default, null);
        return cell;
    }

    void BindPersonCell (UITableViewCell cell, Person person, Foundation.NSIndexPath path)
    {
        cell.TextLabel.Text = person.FullName;
    }
}

Now all that is left to do for us is again fire up the iOS Simulator to verify all is correct and there we have it, the same C# code we used for our WPF and UWA apps is now running under iOS:

iphone

Android

What we did under iOS we can also replicate under Android. Though not part of the Microsoft eco system the model should be more familiar if you have written WPF, Modern Apps (and all the other fancy names they had i.e. Universal Apps). Under Resources/Layouts there is the main.axml which is a (Application) XML file we can edit to tell the Android OS how to render the UI. Sounds a bit like XAML right? And the concepts do overlap in some parts too. Adding a ListView to the XML and set the id of the element which will allow us to access it later on:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ListView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/PeopleListView" />
</LinearLayout>

Again we will have to setup the locator. Under Android there is no fixed setup point, so we will use a static class Locator.cs and property which we will access from the Android app:

internal static class Locator
{
    private static readonly Lazy<ViewModelLocator> _locator = new Lazy<ViewModelLocator>(() => new ViewModelLocator());
    public static ViewModelLocator Instance => _locator.Value;
}

Wiring up the view model is done in the MainActivity.cs, which you can think of as the code behind/ViewController equivalent. I wrote about this binding in more detail in a former blog post which you can find here.

[Activity(Label = "PclSample.Droid", MainLauncher = true, Icon = "@drawable/icon")]
internal class MainActivity : Activity
{
    protected override async void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.Main);

        await Vm.InitAsync();

        // Get our button from the layout resource,
        // and attach an event to it
        PeopleListView.Adapter = Vm.People.GetAdapter(GetPersonView);
    }

    public ListView PeopleListView => FindViewById<ListView>(Resource.Id.PeopleListView);

    private MainViewModel Vm => Locator.Instance.MainViewModel;

    private View GetPersonView(int position, Person person, View convertView)
    {
        View view = convertView ?? LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);

        view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = person.FullName;

        return view;
    }
}

Note that the id we previously set allows us to retrieve the UI control.

At this point we can start up the Android Emulator and just to have mentioned it Visual Studio 2015 provides a great Android Emulator – way better then the stock emulator! And once again we can see the app is running reusing the C# code we tucked away in our PCL.

Shows app running in the Android Emulator

Conclusions

In this blog post we saw how one can share C# code with a Portable Class Library (PCL). The PCL can be included in all major C# stacks .Net, UWP, Silverlight, Xamarin etc. and though the capabilities in the PCL are more limited then a standard .Net library it does allow to share code from a legacy WPF/Win Forms app to a mobile application.

PCLs can be extended by installing further NuGet packages such as storage, network access and many more. The PCL has been around for a couple of years now and has proven itself to be a valuable component when writing cross platform applications.

The entire sample can be found on GitHub.

8 Comments

showing the running sample app

This post will focus specifically on how to bind collection of data to a view. In another post I already focused on how to use bindings for data entry, be sure to read that one to get more insight into data binding under iOS with MVVM Light. In this post we will display a list of people using the standard UITableView iOS UI control. Via two buttons we will be able to add or remove a person. The people will be randomly generated by a service but first things first. Let’s start by creating the view.

Model

The people are generate with the help of the NameGenerator.cs, which is a class that generates random first- and last names.

// As found on https://digitaltoolfactory.net/blog/2012/04/how-to-make-a-random-name-generator-in-c/
public static class NameGenerator
{
    public static Random rnd = new Random();

    public static string GenRandomLastName()
    {
        List<string> lst = new List<string>();
        string str = string.Empty;
        lst.Add("Smith");
        // ...

        str = lst.OrderBy(xx => rnd.Next()).First();
        return str;
    }
    public static string GenRandomFirstName()
    {
        List<string> lst = new List<string>();
        string str = string.Empty;
        // male
        lst.Add("Aiden");
        // ...

        //female

        lst.Add("Sophia");
        // ...

        str = lst.OrderBy(xx => rnd.Next()).First();
        return str;
    }
}

This class will be accessed form the view models, but let’s first setup the view.

View

The view consists of a UITableView and two UIButtons which we add in the Storyboard and name them PeopleTableView, AddPersonButtonand  RemovePersonButton.

showing designer when creating the iOS view

After setting up the view next thing on the list is creating the view model.

View Model

In the view model we implement an ObservableCollection to hold the list of people and two RelayCommands which when invoked add and remove a person from the list:

public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        AddPersonCommand = new RelayCommand(AddPerson);
        RemovePersonCommand = new RelayCommand(RemovePerson);
    }

    public RelayCommand AddPersonCommand { get; set; }
    public RelayCommand RemovePersonCommand { get; set; }
    public ObservableCollection<Person> People { get; private set; }

    public async Task InitAsync()
    {
        if (People != null) return;

        People = new ObservableCollection<Person>();
        var people = await InitPeopleList();
        foreach (var person in people)
        {
            People.Add(person);
        }
    }
}

The list data is initialized asynchronously in an initialisation method. Now what is left to do is connect the view model with the view via bindings.

Configuring Bindings

The bindings are setup in the RootViewController.cs, which is attached to the View which we are about to populate and interact with. The command bindings are implemented in the ViewDidLoad method:

public override async void ViewDidLoad()
{
    base.ViewDidLoad();

    await Vm.InitAsync();

    // Setup bindings
    AddPersonButton.SetCommand("TouchUpInside", Vm.AddPersonCommand);
    RemovePersonButton.SetCommand("TouchUpInside", Vm.RemovePersonCommand);
}

The UITableView’s source is set in the ViewWillAppear method - if done in the ViewDidLoad method you will be initially showed nothing until you start scrolling the blank list.

public override void ViewWillAppear(bool animated)
{
    base.ViewWillAppear(animated);

    _tableViewController = Vm.People.GetController(CreatePersonCell, BindCellDelegate);
    _tableViewController.TableView = PeopleTableView;
}

In the CreatePersonCell method the cell we will display gets created.:

private UITableViewCell CreatePersonCell(NSString cellIdentifier)
{
    return new UITableViewCell(UITableViewCellStyle.Default, "Gnabber");
}

In case you are wondering: “But what about cell recycling?”. Well there is some good news, MVVM Light takes care of that for you. That being said currently (version 5.1.1) does not support multiple cell templates for one collection.

The BindCellDelegate sets the content of the cell:

private void BindCellDelegate(UITableViewCell cell, Person person, NSIndexPath path)
{
    cell.TextLabel.Text = person.FullName;
}

When all is setup we can start up the app you will be able to add and remove people to the list without having to react any further to the events or updating the table source any further.

Conclusion

In this post you saw how you can bind a list of data to an iOS UITableView. Further demonstration showed how easy it is to change the content of the list and updating the UI with the new data. MVVM Light not only allows to integrate your view models nicely in under iOS but only provides some nice little helpers when it comes down to creating an iOS TableSource.

Thanks again to Laurent Bugnion providing us with this great library.

You can find the whole sample on GitHub.

0 Comments

TitleImage

Writing Unit, Component and Integration tests allows to test functionality of software modules. In other words letting developers sleep tightly without worries at night. These tests run against certain parts of the code verifying the logic and interaction between modules of the app. All this is usually performed on the developers machine powered by a beefy processor and often unheard amount of RAM when it comes to mobile devices. Wouldn’t it be great if we could get a bit closer to the real thing? Well we can…

In this blog post we will look at how we can run xUnit.net tests on a device. The app will be a Xamarin(.Forms) app, which consists of three platform projects and a shared Portable Class Library which can be used to write logic that can be consumed on every platform.

Setting up xUnit.net

The typical xUnit.net tests are created in a standard .Net library. All that is required is the xUnit.net NuGet package:

PM> Install-Package xunit -Version 2.0.0

Now we can create start writing unit tests, for this blog post let’s stick to the basic calculator example in the BasicMathServiceTest.cs:

public class BasicMathServiceTest
{
    private BasicMathService _basicMathService;

    public BasicMathServiceTest()
    {
        _basicMathService = new BasicMathService();
    }

    [Fact]
    public void Add_GivenTwoNumbers_TheSumIsReturned()
    {
        var x = 35;
        var y = 7;
        var expectedResult = 42;

        var result = _basicMathService.Add(x, y);

        Assert.Equal(expectedResult, result);
    }

    [Fact]
    public void Subtract_GivenTwoNumbers_TheSubtractedResultIsReturned()
    {
        var x = 456;
        var y = 123;
        var expectedResult = 333;

        var result = _basicMathService.Subtract(x, y);

        Assert.Equal(expectedResult, result);
    }

    [Fact]
    public void Mulitply_GivenTwoNumbers_TheResultIsReturned()
    {
        var x = 2;
        var y = 2;
        var expectedResult = 4;

        var result = _basicMathService.Multiply(x, y);

        Assert.Equal(expectedResult, result);
    }

    [Fact]
    public void Divide_GivenTwoNumbers_TheSumIsReturned()
    {
        var x = 848;
        var y = 8;
        var expectedResult = 106;

        var result = _basicMathService.Divide(x, y);

        Assert.Equal(expectedResult, result);
    }

    [Fact]
    public void TheFailingTest()
    {
        var x = 4;
        var y = 2;
        var expectedResult = 8;

        var result = _basicMathService.Add(x, y);

        Assert.Equal(expectedResult, result);
    }
}

The code that we test against lives in a PCL and performs the calculations. Now let’s take these existing tests and execute them on the simulator or even a real device.

Running Tests on devices

For this first add the platforms on which the project will run. Now add the following xUnit.net NuGet package:

PM> Install-Package xunit.runner.devices -Version 1.0.0

Written by Oren Novotny whom we have to thank for enabling xUnit.net on Android, iOS and Windows Phone! This package will automatically add the xUnit.net and other dependencies required for running tests on your devices according to the platform to which it’s being added. Depending on the platform the xUnit.net for Devices package adds different template files as text files:

  • Android
    • MainActivity.cs.txt
  • iOS
    • AppDelegate.cs.txt
  • Windows Phone
    • MainPage.xaml.txt
    • MainPage.xaml.cs.txt

Simply replace the content of their default counterparts e.g. for iOS replace the AppDelegate.cs with the content of the App.Delegate.cs.txt (and thanks to some extra effort by Oren Novotny even the namespaces will just simply match Smile). Now you could simply start adding new class files and write out tests. The runner will automatically find them via reflection (even if you place them in subfolders).

Using existing tests

What is probably a more useful approach is to simply reuse existing tests. This is why in a next step lets see how we can add the unit test file BasicMathServiceTest.cs without creating a duplicate dopy. Simply right click on the Project then Add/Existing Item… browse to the unit test file and add it as link.

Shows the dropdown on the Add button that can be used to add a file as a link.

As a link to the file is simply a pointer to the original we only have to maintain one unit test file and all the links will automatically “update” as they simply reference the original.

Now the Project can be set as startup project and executed on the device. Bellow you see some sample screenshots from an iOS Emulator.

TestOverview

You can even dig into the error messages and see what went wrong during a test.

TestDetails

Conclusion

In this post we saw how to create and reuse xUnit.net tests on devices for iOS, Android and Windows. This can be very powerful when we have to test certain features on a device for example does this work with AOT on iOS? Or simply running integration tests on a real device, giving valuable insights and further allowing to tests performance, latency and so on.

This post focuses on xUnit.net and also shows one of it’s many strengths on the capabilities that can be easily added. The same can be done with NUnit which may be your testing framework of choice and which Xamarin provides project templates to run the tests on a device.

You can find the sample code on GitHub.

2 Comments

In this weeks blog post lets look at how we can enable bindings with MVVM Light under iOS using a Storyboard with Xamarin. So lets create a simple application that has a label, button and text entry field.

MvvmLightiOSBinding

The label will display the previous message which was entered in the text entry field and submitted with the button. The entire UI is designed in the Storyboard designer and then hooked up to the ViewModel in the code behind.

Wiring up the View to the ViewModel

Under iOS the bindings have to be defined within the code, so for the label that gets updated from the ViewModel the binding looks as follows:

_textLabelBinding = this.SetBinding (
() => Vm.TheResponse,
() => TextLabel.Text);

The button is wired via a command binding:

SubmitTextButton.SetCommand("TouchUpInside", Vm.SubmitTextCommand);

When it comes to the text field we have to register ourselfs to an event of the UI control on which we are invoked. Then we pass the value of the text field to our MainViewModel i.e. the property.

_textFieldBinding = this.SetBinding (
() => EntryTextField.Text)
.ObserveSourceEvent ("EditingDidEnd")
.WhenSourceChanges (() => Vm.TheInput = EntryTextField.Text);

So as you can see there is a bit more work to do for using ViewModels under iOS than under Xamarin.Forms, Android or Windows – but it can be done Smile

Taking a peek at the ViewModel

The MainViewModel is pretty straight forward and does not differ from ViewModels you may use for Windows applications e.g. Universal Windows Apps.

public class MainViewModel : ViewModelBase
{
private string _theInput;
private string _theResponse;
private RelayCommand _submitTextCommand;

public MainViewModel ()
{
Names = new ObservableCollection<string>();
SubmitTextCommand = new RelayCommand (HandleSubmitTextCommand, () => CanExecuteSubmitText);
CanExecuteSubmitText = true;

TheResponse = "Awaiting your input";
}

public string TheInput {
get {
return _theInput;
}
set {
_theInput = value;
RaisePropertyChanged (() => TheInput);
}
}

public string TheResponse {
get {
return _theResponse;
}
set {
if (value == _theResponse) return;
_theResponse = value;
RaisePropertyChanged (() => TheResponse);
}
}

public RelayCommand SubmitTextCommand {
get {
return _submitTextCommand;
}
private set {
_submitTextCommand = value;
}
}

public bool CanExecuteSubmitText {
get;
set;
}

public ObservableCollection<string> Names { get; set; }

private void HandleSubmitTextCommand ()
{
CanExecuteSubmitText = false;

TheResponse = "You just entered: " + TheInput;

CanExecuteSubmitText = true;
}
}

When the command is invoked we simply register a handler for which in the case of the sample code is the HandleSubmitTextCommand method. You can also use set the CanExecute property of an ICommand and it will prevent the Command from re-executing while the handler is still working on a call from the user.

Conclusion

So as you could see the MVVM Light framework from Laurent Bugnion can be used to implement a MVVM client architecture under iOS using Storybaords. The biggest difference from the standard approach is that the developer has to handle wiring up the bindings and ensure that the bindings are attached to corresponding events in case of reacting to new values from the UI. Other then that the code is the same as you would expect it to be from Windows implementations.

You can find the sample code on GitHub.

References

Laurent Bugnions Xamarin Evolve talk.

Getting started with MVVM Light and Xamarin.Forms Post.

1 Comments

JSON Logo i.e. blog post logo

Though frowned upon often due to overuse inheritance remains a powerful and (when used correctly) great feature of an object oriented programming language such as C#. But when it comes down to serializing inheritance object structures i.e. deserializing them on the other side things tend to get hairy. The post will show you how serialization and deserialization of inheritance related objects can be performed with JSON.Net.

So lets have a look at the project setup. The server will be your standard ASP.Net Web API restful web service that comes with JSON.Net out of the box. On the client side we will be using consuming the service from a Portable Class Library PCL that will be able to run with most C# stacks e.g. Windows Store, .Net, Xamarin.iOS, Xamarin.Android etc.. I’ll be using a Xamarin.Forms app but the code will run just fine in your ever day WPF app. The basic system setup is the client calls the server for data, the server returns the data serialized as JSON which will then be deserialized on the client and then used to display the information to the user.

System overview showing communication flow from the client to the server and back via JSON serialized data.

So lets have a look how it works in more detail.

Setting up the project

Lets start with looking at the server which mainly exists of a controller:

public class InheritanceController : ApiController
{
// GET: api/Inheritance
public IEnumerable<ParentClass> Get()
{
return new ParentClass[] {new ParentClass(), new ChildClass()};
}
}

The controller creates a list of ParentClasses and ChildClasses before serializing them back to the caller.

public class ParentClass
{
public virtual string Title
{
get { return "Parent"; }
}

public virtual string Descirption
{
get { return "Hello from the parent."; }
}
}

public class ChildClass:ParentClass
{
public override string Title
{
get { return "Child"; }
}

public override string Descirption
{
get { return "The child says hi..."; }
}

public string ChildSecret
{
get { return "42"; }
}
}

So not a lot of magic going as you can see on the server side. So lets have a look at the client. In the PCL we will use the HTTP Client NuGet package to call the server and the JSON.Net package to deserialize the data from the server.

Nuget Package overview on the client showing JSON.NET, Microsoft BCL Build Components, MVVMLIght libraries only, Microsoft HTTP Client Libraries and Xamarin.Forms packages

On the client we will display the data in a list, you can see the UI code in the MainPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="InheritanceJsonSerialization.Client.Views.MainPage">
<Grid>
<ListView ItemsSource="{Binding DataItems}" ItemSelected="ListView_OnItemSelected" />
<ActivityIndicator IsRunning="{Binding IsLoading}" IsEnabled="{Binding IsLoading}" IsVisible="{Binding IsLoading}"/>
</Grid>
</ContentPage>

In the HttpHandler class in the GetData method the data is requested from the server and then deserialized.

using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using InheritanceJsonSerialization.Client.Models;
using Newtonsoft.Json;

namespace InheritanceJsonSerialization.Client.Services.Http.Impl
{
public class HttpHandler:IHttpHandler
{
private readonly HttpClient _httpClient;

public HttpHandler()
{
_httpClient = new HttpClient();
}

public async Task<IEnumerable<ParentClass>> GetData()
{
// Ensure that uri matches the service backend you are calling
//const string uri = "http://localhost:52890/api/inheritance";
const string uri = "https://inheritancejsonserializationweb.azurewebsites.net/api/inheritance";

var httpResult = await _httpClient.GetAsync(uri);
var jsonContent = await httpResult.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<IEnumerable<ParentClass>>(jsonContent);

return result;
}
}
}

Now when we deserialize the information on the client we run into the problem that the type information is not passed on to the client and therefore all objects deserialized are of type ParentClass.

Serializing with type information

Luckely JSON.Net allows us to easily include the type information when we serialize the type. On the server in the Register method within the WebApiConfig class we can setup how JSON.Net serializes objects:

public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.All;

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}

Now the information will be serialized in the JSON string:

{
"$type": "InheritanceJsonSerialization.Models.ParentClass[], InheritanceJsonSerialization",
"$values": [
{
"$type": "InheritanceJsonSerialization.Models.ParentClass, InheritanceJsonSerialization",
"Title": "Parent",
"Descirption": "Hello from the parent."
},
{
"$type": "InheritanceJsonSerialization.Models.ChildClass, InheritanceJsonSerialization",
"Title": "Child",
"Descirption": "The child says hi...",
"ChildSecret": "42"
}
]
}

On the client side we will have to do a bit more work to get deserialization working.

Deserializing with Type information

For deserializing with type information you might have already found the following line of code that will trigger JSON.Net to check for the type information and try to deserialize it according to the information present in the JSON string.

            JsonConvert.DeserializeObject<IEnumerable<ParentClass>>(jsonContent, new JsonSerializerSettings{TypeNameHandling = TypeNameHandling.All});

The problem here is that all will go well when you serialize and deserialize from the same binary/namespace but in this setup (which I regard as the common setup) you will get an exception as the namespace will not exist i.e. be different on the client than on the server. To solve this issue we have to write a SerializationBinder that inherits from the DefaultSerializationBinder as follows:

public class InheritanceSerializationBinder : DefaultSerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
switch (typeName)
{
case "InheritanceJsonSerialization.Models.ParentClass[]": return typeof(ParentClass[]);
case "InheritanceJsonSerialization.Models.ParentClass": return typeof(ParentClass);
case "InheritanceJsonSerialization.Models.ChildClass[]": return typeof(ChildClass[]);
case "InheritanceJsonSerialization.Models.ChildClass": return typeof(ChildClass);
default: return base.BindToType(assemblyName, typeName);
}
}
}

This will simply map the server namespace to local types. Finally we can update the GetData method in the HttpHandler class:

public async Task<IEnumerable<ParentClass>> GetData()
{
// ...
var result = JsonConvert.DeserializeObject<IEnumerable<ParentClass>>(jsonContent, new JsonSerializerSettings{TypeNameHandling = TypeNameHandling.All, Binder = new InheritanceSerializationBinder()});

return result;
}

And now when we deserialize the list the ChildClass will be correctly identified i.e. the list will be preserved through deserialization.

Conclusion

In this post you saw how inheritance hirarchies can be correctly serialized and deserialized on the client using JSON.Net. By doing so we had to configure our ASP.Net Web API and add handling mechanisms on the client side. I hope this post is of any help and please let me know if I may have mist anything Smile

You can find the code on GitHub.