Resolving FileNotFoundException when using Simple.OData.Client in iOS applications

Several users of Simple.OData.Client 4.0 pre-release reported about an error when using the library on iOS platform. An attempt to send an OData request resulted in FileNotFoundException with the error message about the V3 or V4 adapter, e.g.:

System.IO.FileNotFoundException: Could not load file or assembly 'Simple.OData.Client.V3.Adapter' or one of its dependencies.

This error occurs only on iOS platform, and it is caused by application size optimization performed by the iOS linker. The linker scans applications dependencies and strips out all unused assemblies. Or should I say – assemblies it suspects to be unused. To reduce memory footprint, Simple.OData.Client 4.0 loads only assemblies that are required by the selected version of OData protocol, and the root adapter assembly is loaded by reflection making the iOS linker believe that it’s unused.

This is in fact well-documented behavior, and there are several workarounds. Some of them requires marking code to be preserved with special attributes, but Simple.OData.Client is a packaged as a portable class library, so it can’t have dependencies on platform-specific definitions. An alternative is to include in the main application assembly a single line of code referencing the OData adapter assembly. Here’s how you do it if your application uses OData services over V3 protocol:

Simple.OData.Client.V3Adapter().Reference();

And of the code for V4 protocol is similar:

Simple.OData.Client.V3Adapter().Reference();

Note that this code does nothing. Absolutely nothing. So you can place it anywhere within the iOS application assembly. And it’s only iOS apps that need it. Android, Windows Phone and desktop applications will run fine without an explicit adapter reference.

Second look at Xamarin.Forms: building OData client

A few weeks ago I wrote a blog post about getting started with Xamarin.Forms. While I went through the full cycle of creating Xamarin.Forms applications on all three supported mobile platforms, the actual application (“Hello, Forms” greeting) was too dull to give an impression about the product UI capabilities.

After that I continued working on my pet project – a cross-platform OData client library Simple.OData.Client. In addition to a NuGet PCL package I also wanted to publish the library in Xamarin Component Store, and Xamarin Store submissions require samples for all supported platforms. Earlier I planned to write three separate samples, but with the release of Xamarin.Forms there is a much easier way to write small prototype-alike apps for such purposes. I asked folks at Xamarin whether it would be acceptable to submit component samples written using Xamarin.Forms, and it turned out that it would be the first such submission but it would be OK and in fact worth gathering some experience.

Prototyping NuGetFinder

The sample that I planned to write had to demonstrate capabilities of an OData library, and NuGet is definitely the most popular OData feed among developers. I decided to write a simple NuGet package finder with three pages: a page to specify package search criteria, a result page with a list of matching packages and a page with package details. I quickly made a UI prototype using Balsamiq Mockups.

Mockups

Choosing between Portable and Shared projects

As I wrote in my “First look” post, Xamarin Visual Studio add-on and Xamarin Studio install mobile apps templates that give developers a choice between applications based on Shared (Universal) projects and Portable projects. The first option is about sharing only projects assets, not resulting binaries. The second option is based on portable class libraries (PCL).

I am a big fan of portable class libraries, and Simple.OData.Client itself is a PCL, but after some considerations I decided to build Xamarin Store samples based on Shared projects. The main reason for this is that even though I wanted samples to reuse common code, I also wanted them to be autonomous, so a sample project assembly would contain its user interface rather that referencing another PCL.

C# or XAML?

Xamarin.Forms support describing user interface either using markup language (its own XAML dialect) or directly in C#. Both methods give same results, but for the time being none of them has comprehensive documentation, and with C# you are guarded by a compiler and guided by Intellisense. Writing XAML you must know markup and watch typos. I concluded that at this point it will be easier to describe UI elements in C#, but I plan to use XAML in the future when it’s better documented.

Where are those radio buttons?

I created a solution with shared UI assets and applications for iOS, Android and Windows Phone and started implementing its UI based on my mockups. I am a backend developer during daytime, so I have good excuses for not knowing much about available UI mobile controls. And it took me some time to realize that there is not such a thing as cross-platform radio button control. Xamarin doesn’t want to repeat a mistake made by designers of Java applets and offer cross-platform user interface elements that would look equally bad on each platform. Instead they offer UI abstractions that can translate into native controls. And since Xamarin.Forms is a multiplatform product, its UI elements are limited with those that can be found on all three platforms. Thus no radio or check buttons. I ended up with Picker control that provides the same functionality (although with a very different look).

Search page

Search page is the page that sets up and performs communication with the NuGet OData feed. The user enters search details and clicks “Search” button triggering the following code:

searchButton.Clicked += async (sender, e) =>
{
    var packages = await FindPackagesAsync();
    var resultsPage = new ResultsPage(packages);
    await this.Navigation.PushAsync(resultsPage);
};

And here’s the definition of FindPackagesAsync:

private async Task<IEnumerable<Package>> FindPackagesAsync()
{
    int count = 0;
    switch (_resultSizePicker.SelectedIndex)
    {
        case 0: count = 10; break;
        case 1: count = 25; break;
        case 2: count = 100; break;
    }

    var odataClient = new ODataClient("https://nuget.org/api/v1");
    var command = odataClient
        .For<Package>("Packages")
        .OrderByDescending(x => x.DownloadCount)
        .Top(count);

    switch (_sortPicker.SelectedIndex)
    {
        case 0:
            command.OrderByDescending(x => x.DownloadCount);
            break;
        case 1:
            command.OrderBy(x => x.Id);
            break;
        case 2:
            command.OrderByDescending(x => x.LastUpdated);
            break;
    }

    if (!string.IsNullOrEmpty(_searchText.Text))
    {
        command.Filter(x => x.Title.Contains(_searchText.Text) && x.IsLatestVersion);
    }
    else
    {
        command.Filter(x => x.IsLatestVersion);
    }

    command.Select(x => new {
        x.Id, x.Title, x.Version, x.LastUpdated, x.DownloadCount, 
        x.VersionDownloadCount, x.PackageSize, x.Authors, x.Dependencies });

    return await command.FindEntriesAsync();
}

Here how the Search page looks on iPhone simulator:

SearchPage

Nothing fancy, but enough to prototype page UI on all major mobile platforms.

Results page

Results page is essentially a list of packages satisfying search criteria with an event handler for a selected item:

resultList.ItemSelected += (sender, e) =>
{
    var package = (PackageViewModel)e.SelectedItem;
    var detailsPage = new DetailsPage();
    detailsPage.BindingContext = package;
    Navigation.PushAsync(detailsPage);
};

Here’s how the results pages look on an Android simulator:

ResultsPage

Details page

Selected package details are shown on a new page that consists of label and text box controls. The programming logic is very simple, here’s a code extract that assigns package title and package id:

var titleLabel = new Label() { Font = Font.SystemFontOfSize(NamedSize.Large) };
titleLabel.SetBinding(Label.TextProperty, "Title");
stackLayout.Children.Add(titleLabel);
var idLayout = new StackLayout() { Orientation = StackOrientation.Horizontal };
idLayout.Children.Add(new Label() { Text = "Package Id: " });
var idLabel = new Label();
idLabel.SetBinding(Label.TextProperty, "Id");
idLayout.Children.Add(idLabel);
stackLayout.Children.Add(idLayout);

Here’s how Details page look on Windows Phone emulator:

DetailsPage

And now there is a new Xamarin component!

These samples have been packaged and submitted together with Simple.OData.Client library. They are now available in Xamarin Component Store. And the sample source code is also available from the GitHub repository.

Component

First look at Xamarin.Forms

Today (May 29) was the Norwegian national holiday, so it was a good timing for me that Xamarin just announced availability of Xamarin 3 with the main new addition called Xamarin.Forms. So I downloaded both Windows and Mac versions and spent some time checking out how they work. This post is about setting up Xamain.Forms projects, it doesn’t contain a thorough look at its functional capabilities.

Since I have a Mac machine, I decided to try both Windows and Mac versions. To use Xamarin.Forms with Visual Studio I had to install Visual Studio 2013 Update 2 (RTM) – this is a prerequisite, earlier versions won’t work. Xamarin Visual Studio add-on installs 3 new templates in the “Mobile Apps” folder, so you have choice between applications based on Shared (Universal) projects, Portable projects or just building a portable class library (PCL).

VsProjectTypes

I selected Xamarin.Forms portable and Visual Studio created a common portable class library project (with shared form definition) and applications for all three supported platforms (Android, iOS and Windows Phone 8).

PortableAppProjects

The common PCL uses profile that supports five different platorms – in addition to mobile platforms it can also be used in desktop and Silverlight applications.

VsPortableApp1

Then I switched to MacOS, started Xamarin Studio and chose an alternative template for Xamarin.Forms solution – this time it was Shared project template.

XsProjectTypes

Xamarin Studio created a shared forms project and applications for two platforms supported for development on MacOS (Android and iOS).

SharedAppProjects

Now I could start building mobile applications. I switched back to Visual Studio and started with Windows Phone app. For the first time Windows Phone is a target of Xamarin tools platform (Xamarin Studio still supports only iOS and Android). The actual UI content (placed in a PCL and shared by all platforms) consisted of an obligatory first-app-greeting:

VsPortableApp2

I built a Windows Phone app and deployed it to a phone simulator. Note “PortableApp1.WinPhone” that appears in the application list. Executing it results in a “Hello, Forms!” message.

VsWinPhone1VsWinPhone2

Next was Android simulator. It took me some time to figure out how to select Android API version required by the app. The trick was to locate a small toolbar button that opens Android options. I chose “MonoForAndroid_API_15”.

VsAndroid1

Having selected correct version of Android Simulator, I was able to deploy PortableApp1.

VsAndroid2

 

VsAndroid3

The last platform was iOS, it required establishing a connection with Mac host. I also had to choose the Simulator device type.

VsIOS1

After the iOS deployment configuration was correctly set, Visual Studio deployed the iOS app to the iPhone simulator running on Mac.

VsIOS2

Having completed all three applications from within Visual Studio, I switched back to Xamarin Studio on Mac. There is no Windows Phone support in Xamarin Studio, so I built Android and iOS apps. The content of App.cs file in a Shared project is almost identical to its Portable project counterpart. And the Android simulator on Mac OS looks similar.

XsAndroid1

Next was iOS app and choice of its simulator.

XsIOS1

After the deployment of iOS app I had both PortableApp1 and SharedApp1 installed on the iPhone simulator – the first one was earlier installed by Visual Studio.

XsIOS2

After completion of apps with Xamarin Studio I tried swapping solutions between development environments. Here not everything went smooth. Xamarin Studio opened and built the solution created with Visual Studio (of course with exception of Windows Phone project that was ignored), but Visual Studio refused to load shared app project with a cryptic error message:

VsOpenXs

The log file contained a stack trace of the AggregatedException with not much more useful details. I described an error in Xamarin forum, and one of the suggestion was to install a Shared Project Reference Manager extension. I followed the advice, and while I no longer received the error above, Visual Studio still refused to deal with the shared project, this time hanging on project load.

VsOpenXsCrash

I also tried to create a solution based on Shared project template in Xamarin Studio for Windows, but the result was still the same: Visual Studio couldn’t handle the solutions created by Xamarin Studio. It looks like the problem is only with Shared project template – when I created with Xamarin Studio a project from Portable project template, Visual Studio had no problems with it.

So for the time being if you want to be able to swap solutions between different environments, you need to create Shared apps with Xamarin add-in to Visual Studio which can be a problem because this option requires the expensive Xamarin Business license. Hopefully this issue will be addressed soon.

I also tried to get a feeling of what it takes to author UI content in Xamarin.Forms, so I used code from a login page example.

XsSharedApp1

I only needed to edit this code once – in a Portable or Shared app, and all apps reflected the change.

VsWinPhone3XsIOS3

XsAndroid2

This a very trivial example, and I am looking forward to check more advanced scenarios. During beta testing period Xamarin.Forms had a codename QuickUI, and it’s a really way to simultaneously develop applications on all three major mobile platforms. There is no restriction in mixing native UI elements with content created with Xamarin.Forms, so the resulting apps don’t need to suffer from least common denominator design syndrome.

 

 

Simple.OData.Client roadmap: versions 2, 3 and 4

It’s been a few month since I wrote a blog post comparing features of Simple.OData.Client and WCF Data Services client. Judging from NuGet download statistics, questions and GitHub issues I can see that the library has been used in various scenarios and on various platforms, including Xamarin iOS and Android. This is indeed very encouraging but at the same time raises the bar for the platform tests, conformance to OData protocol and API expressiveness. Some of the forthcoming changes to Simple.OData.Client API are breaking, and with respect to semantic versioning I have to release them with a different major version number. So I’d like to give in this blog post a quick overview of each version.

Version 1

Initial release of Simple.OData.Client came as a library extracted from Simple.Data OData adapter to improve its granularity and portability. The library implemented HTTP communication based on HttpWebRequest and favored synchronous calls. This didn’t work well with platforms like Silverlight and Windows Phone that required asynchronous communication all the way.

Version 2

This is the most recent (in May 2014) version of Simple.OData.Client with two major changes comparing to version 1:

  • The library is now using Microsoft HttpClient PCL (Microsoft.Net.Http);
  • The library API has been redesigned to be asynchronous but it still exposes obsolete synchronous methods in addition to asynchronous ones;

I have to admit now that keeping synchronous methods was a mistake – I did it for backward compatibility, but it misleads developers in belief that they can use synchronous API on platforms where it can easily cause deadlocks. In fact, I wouldn’t recommend to use sync API on any platform except .NET 4.x. For the sake of existing .NET 4 clients I will keep adding minor changes to version 2 even after release of newer major versions of the library.

Version 3

This is already available as release candidate and contains the following significant changes:

PCL profile numbers may not say much, but this is in fact the major change although not reflected in API method signatures. PCL profile 147 corresponds to so called legacy surface area intended to fit most platforms. This requires use of internal wrappers and adapters and as it turned out results in problems – ironically on the legacy platforms. For example, I never managed to succeed using HttpClient PCL from another PCL called from a Silverlight application. So I changed the PCL targeting strategy and now Simple.OData.Client targets .NET 4.0 and Silverlight platforms via native platform-specific libraries with the its PCL targeting other platforms.

Version 4

Currently Simple.OData.Client uses its own parser and formatter that only support XML payload in the format of RSS feeds. That was the original OData message format, but the protocol has been extended with support for JSON, and being more compact, more readable and more network bandwidth friendly, JSON is becoming a preferred OData payload representation and is selected as a default format by OData feeds built using HTTP Web API. Now that Microsoft has converted its ODataLib (Microsoft.Data.OData) to support all target Simple.OData.Client platforms, I plan to retire internal Simple.OData.Client OData parser and formatter and instead use the one from ODataLib so I can ensure the same message serialization and keep the library up-to-date with most recent OData protocol updates reflected in ODataLib.

Summary: which version to use?

 

  • If you’re using Simple.Data OData adapter, you don’t need to care: just use the most recent version available at NuGet or keep using the one you’re using now if it works fine. Simple.Data OData adapter will be maintained and its dependencies will be updated so you don’t have to take any actions in regards to Simple.OData.Client.
  • If you’re using Simple.OData.Client synchronous API with .NET 4.0 applications and everything works fine, you can continue using it. For mobile applications use only asynchronous API calls.
  • The release of the version 3 is around the corner, pre-release is already available. Works much better with Silverlight clients, support for cancellation tokens, modern PCL profile widely used on Xamarin platforms.
  • Version 4 will add support for JSON payload and will be based on ODataLib. But I haven’t even started working on it.