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

Finding a suitable PCL profile for a cross-platform library

I recently posted on StackOverflow a question about finding a right profile for a .NET portable class library. For a long time I have packaged Simple.OData.Client, an open source OData client library that I wrote and maintain, as a PCL using one of the broadest possible profiles (Profile147):

Image

Since Profile147 supports .NET framework starting from the version 4.0.3, I had to include in the NuGet package a platform-specific version for .NET 4.0. Later I also added a platform-specific version for Silverlight 5, because I experienced problems with using HttpClient from a PCL targeting Silverlight. So in practice I could change the profile for my library to a more narrow one (Profile78):

Image

But I kept the original profile, mainly to ensure my PCL can be referenced by a largest possible set of other PCLs. When a portable class library references another PCL, it can not target a wider set of platforms than the refenced PCL. So I wanted to cover a case when somebody would write a PCL that targets Silverlight 5 and references Simple.OData.Client.

But targeting legacy platforms comes at some costs. Legacy platforms may lack or have different API signatures (e.g. reflection API), and use of async/await keywords requires installing Microsoft.Bcl.Async NuGet package. More packages, more dependencies, different API revisions. And there’s more. Microsoft’s David Kean, answering a question about .NET portable subsets, uncovered some of the internals: “For legacy platforms (Phone 7.x, SL4/5, .NET 4, Xbox), when we come up with the intersections between multiple platforms, we need to physically generate actual assemblies that represent the common APIs. For example, when you combine Windows Phone 7 and .NET Framework, we generate (these are generated on our side in Microsoft) an actual mscorlib, system, system.core, etc that contain the APIs that these share. This is not only very time consuming, it’s also extremely problematic in that it can generate not very useful subsets.”

David also answered my original question and among other things wrote the following: “Looking at the data internally, I can see that “Profile78” (.NET Framework 4.5, Windows 8, Phone 8, Xamarin.Android, Xamarin.iOS) is overwhelming the most popular target (~45% of portable projects target this). This is not surprising. It targets large breadth of modern platforms with a reasonable large feature support. These platforms that this profile targets, also support what we consider our “modern surface area”, hence have way more shared API surface vs profiles that target platforms that support our legacy surface area (Silverlight, .NET Framework 4).”

It all convinced me that it’s time to revise my profile selection strategy and target the modern surface area. The fact that 45% of portable libraries choose Profile78 also indicates that my original intention to support wider set of platforms for the sake of transitive PCL support wasn’t practically justified: developer move on and target newer platforms.

And to illustrate some other consequences of choosing the legacy surface area, I made a few tests using Xamarin HttpClient sample. The sample contains a core PCL that demonstrates HttpClient capabilities and two mobile applications (for iOS and Android) using that PCL. The original sample uses Profile7 (.NET 4.5 + Windows Store). I built it and successfully ran on both iOS and Android simulators. Then I changed the profile to Profile78 (added Windows Phone 8). Tried to build again, but compilation failed:

xamarin-samples\HttpClientPortable\HttpPortable\NetHttp.cs(18,46,18,56): error CS0234: The type or namespace name 'HttpClient' does not exist in the namespace 'System.Net.Http' (are you missing an assembly reference?)
xamarin-samples\HttpClientPortable\HttpPortable\NetHttp.cs(19,13,19,62): error CS1502: The best overloaded method match for 'HttpPortable.IRenderer.RenderStream(System.IO.Stream)' has some invalid arguments
xamarin-samples\HttpClientPortable\HttpPortable\NetHttp.cs(19,29,19,61): error CS1503: Argument 1: cannot convert from 'void' to 'System.IO.Stream'

So adding Windows Phone 8 requires installing HttpClient NuGet package (Microsoft.Net.Http). I did it from a Package Manager window:

PM> install-package Microsoft.Net.Http
Attempting to resolve dependency 'Microsoft.Bcl (≥ 1.1.3)'.
Attempting to resolve dependency 'Microsoft.Bcl.Build (≥ 1.0.10)'.
Installing 'Microsoft.Bcl.Build 1.0.14'.
Successfully installed 'Microsoft.Bcl.Build 1.0.14'.
Installing 'Microsoft.Bcl 1.1.7'.
Successfully installed 'Microsoft.Bcl 1.1.7'.
Installing 'Microsoft.Net.Http 2.2.19'.
Successfully installed 'Microsoft.Net.Http 2.2.19'.
Adding 'Microsoft.Bcl.Build 1.0.14' to HttpPortable.
Successfully added 'Microsoft.Bcl.Build 1.0.14' to HttpPortable.
Adding 'Microsoft.Bcl 1.1.7' to HttpPortable.
Successfully added 'Microsoft.Bcl 1.1.7' to HttpPortable.
Adding 'Microsoft.Net.Http 2.2.19' to HttpPortable.
Successfully added 'Microsoft.Net.Http 2.2.19' to HttpPortable.

As you see, Microsoft.Net.Http dragged two other packages: Microsoft.Bcl and Microsoft.Bcl.Build. Then applications successfully built and ran.

Next I added Silverlight to the set of supported platforms (Profile158). Silverlight belongs to a legacy surface area, which causes physical generation of code representing the common APIs, as David wrote above. And it requires installing a new NuGet package, because at first the code didn’t compile:

xamarin-samples\HttpClientPortable\HttpPortable\NetHttp.cs(19,29,19,61): error CS4001: Cannot await 'System.Threading.Tasks.Task<System.IO.Stream>'
xamarin-samples\HttpClientPortable\HttpPortable\NetHttp.cs(19,13,19,62): error CS1502: The best overloaded method match for 'HttpPortable.IRenderer.RenderStream(System.IO.Stream)' has some invalid arguments
xamarin-samples\HttpClientPortable\HttpPortable\NetHttp.cs(19,29,19,61): error CS1503: Argument 1: cannot convert from 'void' to 'System.IO.Stream'

Of course, async/await weren’t originally available on Silverlight. Later Microsoft released another BCL package (Microsoft.Bcl.Async) that I also had to install:

PM> install-package Microsoft.Bcl.Async
Attempting to resolve dependency 'Microsoft.Bcl (≥ 1.0.19)'.
Attempting to resolve dependency 'Microsoft.Bcl.Build (≥ 1.0.10)'.
Installing 'Microsoft.Bcl.Async 1.0.166'.
Successfully installed 'Microsoft.Bcl.Async 1.0.166'.
Adding 'Microsoft.Bcl.Async 1.0.166' to HttpPortable.
Successfully added 'Microsoft.Bcl.Async 1.0.166' to HttpPortable.
After this I was able to build and run the sample applications. I also tried even wider profile (Profile147 with support for .NET 4.0.3) that I was using with Simple.OData.Client, and it built fine using the same set of NuGet packages as Profile158.
 
And I think I’ve made my choice now. I will continue support .NET 4.0 and Silverlight 5 by offering platform-specific assemblies in the Simple.OData.Client NuGet package, but the core PCL assembly will only support .NET 4.5, Windows Store, Windows Phone 8 (and of course Xamarin iOS and Android). This will ensure it will use modern surface area without dragging large amount of extra code.

We need better interoperability between dynamic and statically compiled C#

It’s 2013 now, .NET DLR has been out for more than three years, and there are plenty of great libraries around with clever mix of statically compiled and dynamically evaluated code. I am guilty of one myself.

Unfortunately ‘dynamic’ keyword doesn’t only bring joy to the art of programming. Its power often results in unintended behavior that can usually be explained by digging deep into language implementation, but still looking unreasonable.

Look at the interface below. its first method returns a reference to the interface itself, and the second method returns a result, so both methods can be chained:

public interface IFluentClient
{
    IFluentClient SaveText(string text);
    string GetText();
}

Now in order to be able to use this interface we need a class that implements it. Here it is:

class FluentClient : IFluentClient
{
    private string _text;

    public IFluentClient SaveText(string text)
    {
        _text = text;
        return this;
    }

    public string GetText()
    {
        return _text;
    }
}

This class is not public and we can’t instantiate it in a different assembly, so we will create a factory for it:

public class ClientFactory
{
    public IFluentClient GetFluentClient()
    {
        return new FluentClient();
    }
}

Finally we can write a test for the code above:

[TestMethod]
public void SaveAndGetText()
{
    var client = new ClientFactory().GetFluentClient();
    var text = client.SaveText("a").GetText();
    Assert.AreEqual("a", text);
}

So far so good. The test passes of course. Now we will send a dynamic object to SaveText:

[TestMethod]
public void SaveAndGetText()
{
    dynamic str = "a";
    var client = new ClientFactory().GetFluentClient();
    var text = client.SaveText(str).GetText();
    Assert.AreEqual("a", text);
}

Let’s run the test and it will fail with the following error:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'GetText'

Out of curiosity I tested this code on Mono, and it failed too, with a stranger error:

FluentClient.GetText() is inaccessible due to its protection level

Obviously a string casted to a dynamic object confused the runtime. But why? Eric Lippert in a blog post explained some of the reasons why the DLR-to-CLR interoperability was implemented in a way that makes the runtime treat statically compiled code as dynamic after a dynamic object enters the scene. He defends the decision by stating that “if you and I and the compiler know that overload resolution is going to choose a particular method then why are we making a dynamic call in the first place?” This argument was probably fair enough some time ago when developers were still new to DLR and used dynamic C# only on special occasions. I’d say this is no longer a good argument. It’s easy and convenient to mix statically compiled and dynamic C#, and the language should make their interoperability more natural.

How can we make the failing test work? For example by breaking a fluent call chain:

[TestMethod]
public void SaveAndGetText()
{
    dynamic str = "a";
    var client = new ClientFactory().GetFluentClient();
    client = client.SaveText(str);
    var text = client.GetText();
    Assert.AreEqual("a", text);
}

Suddenly it all works, even with a use of dynamic object. But we can even make the original code work without changing a single line in the test code! The strange error message on Mono that complained about protection level gave me a hint: what if I change the visibility of FluentClass changing its protection level from private to public? Bingo! Suddenly all tests passed. Both on Windows and Mono platforms. But who could expect such behavior?

Use of dynamic code requires more thorough testing. But as you could see in examples above, it sometimes requires rewriting some calls or class definitions without changing any functionality, only because .NET runtime accepts one but not other perfectly valid syntax. This makes interoperability between CLR and DLR fragile. I believe there is a need to make it more predictable and developer-friendly.

Announcing Simple.OData.Client NuGet package for Mono iOS/Android

Release of NuGet 2.5 opens possibilities for targeting Mono iOS/Android platform. The Simple.OData.Client that I maintain is a portable class library, so it was natural step to extend the number of supported frameworks with Xamarin Mono offerings. But as it often happens, I hit a few problems before I could publish the updated package (version 0.15).

One problem I had to deal with was forwarding of the types that are packaged differently in Windows and .NET. Luckily, this problem was addressed earlier by other people, so big thanks to Stuart Lodge (@slodge) and Daniel Plastied (@dsplaisted) for investigating this topic and describing workarounds. Those interested in more details should read this article at StackOverflow. I am now using the same approach that Stuart implemented in MvvmCross, and here is how the file sets for Mono platforms look:

<!—Droid –>
<file src="Simple.OData.Client.Core\bin\Release\Simple.OData.Client.Core.dll" 
      target="lib\MonoAndroid16\Simple.OData.Client.Core.dll" />
<file src="lib\Droid\System.Net.dll" target="lib\MonoAndroid16\System.Net.dll" />

<!-- Touch –>
<file src="Simple.OData.Client.Core\bin\Release\Simple.OData.Client.Core.dll" 
      target="lib\MonoTouch40\Simple.OData.Client.Core.dll" />
<file src="lib\Touch\System.Net.dll" target="lib\MonoTouch40\System.Net.dll" />

Next challenge came from a couple of places in my code where I was using async/await pattern. Since Simple.OData.Client is targeting wide range of platforms including .NET 4.x and Silverlight, I installed Microsoft.Bcl.Async NuGet package that enabled use of async/await keywords when targeting legacy platforms. However, for the time being the files from this package can not be deployed on iOS and Android devices (legal reasons), and Xamarin async/await support is a work in progress. After struggling for a few days with various async issues (only compile-time issues, I haven’t had a single runtime problem with asynchronous operations), I reviewed the code and figured out that it’s so few places where I was using await, that I can rewrite this code replacing await with TPL API almost in no time. So now Simple.OData.Client does not bear any dependency on Microsoft.Bcl.Async.

Finally, I had to write new tests to verify functionality on new platforms. I used an excellent little helper library MonoDroidUnitTest for Android tests, and for iOS there was a Unit Test project template in Xamarin tools. Since I don’t have Mac, I signed in to MacInCloud to test using iOS simulator. It kind of works, but the performance is sluggish so I don’t think this is a good alternative for a serious iOS development (but OK for occasional validation). It was easier with Android – I could simply start a Droid simulator, loaded an app with a few tests, and in a few seconds (well, actually minutes) I could see the following picture:

Android2 

So in case you are doing OData development and need a library that you can use on multiple platforms, have a look at Simple.OData.Client. Now with Mono support.

Cross-platform design-time view models using portable class libraries

Stuart Lodge is working on a fantastic series of videos and blog posts showing how to build cross-platform mobile applications with MvvmCross. One of his tips is about exposing design-time data. His method is straightforward and efficient, but in case you don’t want to copy sample files to a location inside Windows Program Files folder, you may consider other alternatives, such as storing design-time information as project content files or embeding it into an assembly.

This task becomes more complicated in case you want to show some images at design-time, and BitmapImage class is not part of portable class libraries. I used to solve it by representing view model image properties using opaque object class and setting its values in platform-specific part of the view models. The unfortunate consequence of this approach was declaring a view model per platform serving design-time purposes. The platform view models inherited from a common portable view model and only added a tiny bit of non-portable logic – like reading image resources. Here is how I used to show design-time data in my ODataPad application:

public class ServiceViewModel 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string Url { get; set; } 
    public object Image { get; set; } 
} 

public class WinRTDesignHomeViewModel : DesignHomeViewModel 
{ 
    public WinRTDesignHomeViewModel() 
    { 
        foreach (var service in this.Services) 
        { 
            service.Image = new BitmapImage(
                new Uri("ms-appx:///Samples/" + service.Name + ".png")); 
        } 
    } 
} 

public class Net45DesignHomeViewModel : DesignHomeViewModel 
{ 
    public Net45DesignHomeViewModel() 
    { 
        foreach (var service in this.Services) 
        { 
            service.Image = new BitmapImage(
                new Uri(@"pack://application:,,,/ODataPad.UI.Net45;component/Samples/" +
                    service.Name + ".png")); 
        } 
    } 
}

XAML files for Windows Store and WPF applications included Image element with binding to an Image property of ServiceViewModel.

<Image Source="{Binding Image}" Stretch="UniformToFill" />

Here are the screenshots of design-time views:

ODataPadWinRT

ODataPadNet45

ODataPadWP8

This method works but as I already pointed out, it feels heavy because each design-time data set is backed with its own design-time view model – due to non-portability of image .NET types and image management methods.

But there is another way – storing image properties using portable data types, and what can be more portable than a standard string? Enter base64 strings.

Here’s a revised ServiceViewModel class with image data stored as strings:

public class ServiceViewModel 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string Url { get; set; } 
    public string ImageBase64 { get; set; } 
}

We no longer need WinRTDesignHomeViewModel and Net45DesignHomeViewModel classes. Instead we will store all design-time information in a portable class library as an embedded resource. Not that Assembly.GetManifestResourceStream method is part of most of portable class libraries profiles, so we can share the following PCL code between all platforms:

public DesignHomeViewModel()
{
    IEnumerable services = null;
    var namespaceName = typeof(DesignHomeViewModel).Namespace;

    var stream = typeof (DesignHomeViewModel).Assembly
        .GetManifestResourceStream(string.Join(".", namespaceName, "SampleServices.xml"));
    using (var reader = new StreamReader(stream))
    {
        this.Services = SamplesService.ParseSamplesXml(reader.ReadToEnd());
    }
}

Wait, but that can’t be sufficient – our XAML views contain Image elements, we can’t just throw base64 strings at them. Well, almost: it’s all about converters.

Here’s revised XAML code:

<Image Source="{Binding ImageBase64, Converter={StaticResource Base64ToImage}}" 
       Stretch="UniformToFill"/>

And these are converers for Windows Store, WPF and Windows Phone applications:

namespace ODataPad.UI.WinRT.Common
{
    public sealed class Base64ImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, 
                              object parameter, string language)
        {
            return ConvertAsync(value, targetType, parameter, language).Result;
        }

        public object ConvertBack(object value, Type targetType, 
                                  object parameter, string language)
        {
            return null;
        }

        public async Task ConvertAsync(object value, Type targetType, 
                                       object parameter, string language)
        {
            var image = new BitmapImage();

            if (value != null)
            {
                var bytes = System.Convert.FromBase64String((string)value);

                var ras = new InMemoryRandomAccessStream();
                using (var writer = new DataWriter(ras.GetOutputStreamAt(0)))
                {
                    writer.WriteBytes(bytes);
                    await writer.StoreAsync();
                }

                image.SetSource(ras);
            }
            return image;
        }
    }
}

namespace ODataPad.UI.Net45.Common
{
    public class Base64ImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, 
                              object parameter, CultureInfo culture)
        {
            var image = new BitmapImage();
            if (value != null)
            {
                var bytes = System.Convert.FromBase64String((string)value);

                image.BeginInit();
                image.StreamSource = new MemoryStream(bytes);
                image.EndInit();
            }
            return image;
        }

        public object ConvertBack(object value, Type targetType, 
                                  object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}

namespace ODataPad.UI.WP8.Common
{
    public class Base64ImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, 
                              object parameter, CultureInfo culture)
        {
            var image = new BitmapImage();
            if (value != null)
            {
                var bytes = System.Convert.FromBase64String((string)value);
                image.SetSource(new MemoryStream(bytes));
            }
            return image;
        }

        public object ConvertBack(object value, Type targetType, 
                                  object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}

Now all my design-time data are stored in a single portable class library and I display them using a single view model also declared in a PCL. All platform-specific data such as images are stored as strings and only converted to bitmaps when rendering views using value converters.

Introducing Simple.OData.Client: a portable OData client library for .NET4.x, Windows Store, Silverlight 5 and Windows Phone 8

Last week I was busy with my home project: creating an OData portable class library. This project originated from the Simple.Data OData adapter when I needed a library for Windows Store application and didn’t find any suitable one. And since Simple.Data only supports .NET 4.x platforms, I started extracting parts of the adapter to make a PCL.

As it always happens, I spent far longer time to complete this task, but it was worth it even the only outcome was code cleanup. I thought the quality of Simple.Data OData adapter code was pretty good, but when I was forced to separate non-portable portions of it, I realized that this was a separation of concerns. When you are writing code that targets multiple platforms, it’s no longer just your subjective decision of how much responsibility you can delegate to a certain class or module. If your occasionally brought stuff that does not meet portability criteria – logging, creating user credentials, external data access – you will have to remove it. Otherwise your code won’t compile.

Of course running the code through portability check won’t expose all violations of clean code principles, moreover – there may be plenty of reasons for code to not be portable. But in many cases it’s a good check, and we should probably ask yourself a question “why this code is not portable?” more often.

But enough for lessons and principles. The portable OData client library is here, and Mark Rendle was kind enough to let me keep the “Simple” prefix in the library name, although this word is kind of his trademark now. (His remark was “as far as I’m concerned it all grows the brand Smile“). And I hope that simplicity of Simple.OData.Client API is on the level of other members of the family of Simple frameworks.

Simple.OData.Client is an open source library, available at GitHub. In addition, it has a NuGet package. If you install it from NuGet, depending on your project target framework you will get a reference to one of two assemblies:

  • Simple.OData.Client.Net40.dll: for target frameworks .NET 4.0, .NET 4.0.3, .NET 4.5;
  • Simple.OData.Client.Core.dll: for portable libraries targeting .NET 4.0.3, .NET 4.5, Windows Store, Silvelight 5, Windows Phone 8 and for target frameworks Windows Store, Silverlight 5 and Windows Phone 8.

Support for Android and iOS (via Xamarin Mono) is in my plans (in fact, AFAIK the portable version may be used to target Mono for Android).

The project has Wiki pages with many examples, it has two API flavors: basic and fluent. Below is an a example of using its fluent API to retrieve data from NuGet OData feed:

var client = new ODataClient("http://packages.nuget.org/v1/FeedService.svc/");
var x = ODataFilter.Expression;
var packages = client
    .For("Packages)
    .Filter(x.Title == "Simple.OData.Client")
    .FindEntries();

foreach (var package in packages)
{
    Console.WriteLine(package["Title"]);
}

Simple.OData.Client supports all HTTP methods used by OData protocol (GET/POST/PUT/MERGE/DELETE) including support for batch requests.