Announcing Simple.OData.Client 4.0: support for OData V4 and JSON payload

A few months ago I published a roadmap for Simple.OData.Client development which I was trying to follow. Today I am happy to announce a major revision (in fact major rewrite) of the library that now supports OData protocols from 1 to 4 and both Atom and JSON payload.

To achieve that I based the library parsers and formatters on Microsoft’s ODataLib that exists in two incarnations: for OData versions 1 to 3 (Microsoft.Data.OData) and for OData version 4 (Microsoft.OData.Core). Both ODataLib libraries implement similar sets of classes and interfaces (even with the same names), but they have different type identities which makes them incompatible. To make them transparent to the clients, Simple.OData.Client uses adapters libraries that communicate with respective ODataLib assemblies. These pictures show the libraries dependencies.

In case you use OData from desktop apps, the easiest is just to continue using Simple.OData.Client NuGet package that has everything to consume OData feeds of any OData version. However, mobile applications are usually more cautious about program footprint, and since in most cases an application connects to a specific version of OData service using specific version of OData protocol, there is no need to drag a couple of megabytes of unused dependencies, and in that case I recommend to install a NuGet package of Simple.OData.Client just for the given OData protocol version. Here are the packages:

  • Simple.OData.Client – supports all OData protocol versions, installs both sets of ODataLib components;
  • Simple.OData.V3.Client – supports versions of 1 to 3 of OData protocol, installs Microsoft.Data.OData package and dependencies;
  • Simple.OData.V4.Client – supports version 4 of OData protocol, installs Microsoft.OData.Core package and dependencies;

All packages support both Atom and JSON payload, but Atom payload is currently disabled in ODataLib V4 (should come later), so for the time being V4 clients can only use JSON.

Also note that Simple.OData.Client requires Microsoft.OData.Core 6.7.0 NuGet package and not the latest released 6.8.0. This is due to problems reading schemas with Enum types in the package 6.8.0 which I hope will be fixed soon.

Try it out, and if you find any issues please report them here.

Advertisements

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.