Adam
Adam

Reputation: 16199

Error after upgrading to Azure Mobile Services 1.3.1

I have a Xamarin.iOS project and recently upgraded that plus my PCL project to have Windows Azure Mobile Services SDK 1.3.1.

However I now get an error when it tries to create a new MobileServiceClient.

{System.NullReferenceException: Object reference not set to an instance     an object
at Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.GetUserAgentHeader () [0x0002e] in d:\jw\ZumoSDKBuild_Dev\source\sdk\Managed\src\Microsoft.WindowsAzure.MobileServices\Http\MobileServiceHttpClient.cs:683 
at Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient..ctor (IEnumerable`1 handlers, System.Uri applicationUri, System.String installationId, System.String applicationKey) [0x0004e] in d:\jw\ZumoSDKBuild_Dev\source\sdk\Managed\src\Microsoft.WindowsAzure.MobileServices\Http\MobileServiceHttpClient.cs:138 
at Microsoft.WindowsAzure.MobileServices.MobileServiceClient..ctor (System.Uri applicationUri, System.String applicationKey, System.Net.Http.HttpMessageHandler[] handlers) [0x00040] in d:\jw\ZumoSDKBuild_Dev\source\sdk\Managed\src\Microsoft.WindowsAzure.MobileServices\MobileServiceClient.cs:199 
at Microsoft.WindowsAzure.MobileServices.MobileServiceClient..ctor (System.Uri applicationUri, System.String applicationKey) [0x00000] in d:\jw\ZumoSDKBuild_Dev\source\sdk\Managed\src\Microsoft.WindowsAzure.MobileServices\MobileServiceClient.cs:150 
at Microsoft.WindowsAzure.MobileServices.MobileServiceClient..ctor (System.String applicationUrl, System.String applicationKey) [0x00000] in d:\jw\ZumoSDKBuild_Dev\source\sdk\Managed\src\Microsoft.WindowsAzure.MobileServices\MobileServiceClient.cs:135 
at MyApp.App..ctor () [0x00009] in c:\Users\adam\Documents\Visual Studio 2013\Projects\MyApp\App.cs:30 }

Looking at the source code of the MobileServiceClient here is the function it is failing on

            private string GetUserAgentHeader() 
678         { 
679             AssemblyFileVersionAttribute fileVersionAttribute = typeof(MobileServiceClient).GetTypeInfo().Assembly 
680                                                                         .GetCustomAttributes(typeof(AssemblyFileVersionAttribute)) 
681                                                                         .Cast<AssemblyFileVersionAttribute>() 
682                                                                         .FirstOrDefault(); 
683             string fileVersion = fileVersionAttribute.Version; 
684             string sdkVersion = string.Join(".", fileVersion.Split('.').Take(2)); // Get just the major and minor versions 
685 

686             IPlatformInformation platformInformation = Platform.Instance.PlatformInformation; 
687             return string.Format( 
688                 CultureInfo.InvariantCulture, 
689                 "ZUMO/{0} (lang={1}; os={2}; os_version={3}; arch={4}; version={5})", 
690                 sdkVersion, 
691                 "Managed", 
692                 platformInformation.OperatingSystemName, 
693                 platformInformation.OperatingSystemVersion, 
694                 platformInformation.OperatingSystemArchitecture, 
695                 fileVersion); 
696         } 

I have no idea on what is specifically causing the error. Any help appreciated.

Update

If I run the following code, just in my app before I try to initialize the MobileServiceClient

AssemblyFileVersionAttribute fileVersionAttribute = typeof(MobileServiceClient).GetTypeInfo().Assembly 
                                                                        .GetCustomAttributes(typeof(AssemblyFileVersionAttribute)) 
                                                                        .Cast<AssemblyFileVersionAttribute>() 
                                                                         .FirstOrDefault(); 
             string fileVersion = fileVersionAttribute.Version; 

With Don't Link it works perfectly. If I run it with Link SDK or Link All then assembly is equal to null.

Where to go from here I am not sure yet.

Upvotes: 0

Views: 615

Answers (3)

NovaJoe
NovaJoe

Reputation: 4625

The intent of linking is to reduce overall app size by excluding unused namespaces, classes, and members. Linking most apps will require a manual iterative process of:

  1. Enable full linking for whatever build config you're concerned with.
  2. Clean and build the app.
  3. Run the app, and observe what runtime exceptions occur as a result of missing types and methods (including constructors).
  4. Add rules either to your mtouch command arguments or the link description XML file in order to skip linking on the namespaces, types, and classes that you find are throwing exceptions.

In order to link an app that uses the Azure Mobile Services Client PCL, you follow the same iterative process I just stated.

I prefer the XML-based config file strategy of linking preservation: https://developer.xamarin.com/guides/cross-platform/advanced/custom_linking/

The XML file is commonly known as a link definition file. It allows you to control the linker in a declarative fashion, without adding [Preserve] attributes everywhere in your code; and for third-party libraries, without muddying up the mtouch arguments of Xamarin.iOS projects or the csproj file of Xamarin.Android projects. It can be named whatever you want, as long as you properly tell your platform project about it.

An appropriate configuration could look like this:

<?xml version="1.0" encoding="UTF-8" ?>
<linker>
    <assembly fullname="Microsoft.WindowsAzure.Mobile">
        <type fullname="Microsoft*" />
    </assembly>
    <assembly fullname="Microsoft.WindowsAzure.Mobile.Ext">
        <type fullname="Microsoft*" />
    </assembly>
</linker>

In each assembly node, you describe the types or members you want to preserve. For the sake of simplicity here, I've used a wildcard to include all types that begin with "Microsoft". That's matched by fully qualified name, including namespace.

However, as stated, you will encounter a runtime problem with the GetUserAgentHeader() method in the MobileServiceHttpClient class: enter image description here

Fortunately, the source code is available. So, I pulled down the source and referenced it in my project. The exception occurs on line 699, where the the Version property of the fileVersionAttribute var is attempted to be retrieved. But fileVersionAttribute is null!...when linked. The LINQ statement that begins on line 695 returns null when linking is enabled. It does return a valid value when not linked; a value of "1.0.0.0".

WHY? I'm not quite sure yet. But that's the root cause of the exception.

Anyway, for now I'll have to include the Azure Mobile Service source in my project, and artificially set that value to "1.0.0.0"...which is dirty, and I'm not happy about it.

string fileVersion = fileVersionAttribute?.Version ?? "1.0.0.0";

EDIT:

Issue raised on github: https://github.com/Azure/azure-mobile-services/issues/855

Upvotes: 2

Dimse
Dimse

Reputation: 1506

I have finally discovered a way to prevent the linking of the Azure Mobile Services library, without disabling linking for everything else.

You can add

--linkskip=Microsoft.WindowsAzure.Mobile --linkskip=Microsoft.WindowsAzure.Mobile.Ext

to Additional mtouch arguments in the iOS build options under project settings for the iOS project.

This will skip the linker for the azure assemblies, but not the rest. More on the linker can be found at http://developer.xamarin.com/guides/ios/advanced_topics/linker/#Skipping_Assemblies

Upvotes: 1

Adam
Adam

Reputation: 16199

I needed to add

CurrentPlatform.Init(); 

in the AppDelegate in FinishedLaunching

Secondly in the iOS project I needed to go to

Properties > iOS Build > Linker Behavior and set it to "Don't link"

I still don't consider this the answer, its just a poor work around at the moment.

Upvotes: 0

Related Questions