Bug 33668 - System.Data.Services.Client.TypeSystem when trying to use a service reference
Summary: System.Data.Services.Client.TypeSystem when trying to use a service reference
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: XI 8.10
Hardware: PC Windows
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2015-09-04 13:39 UTC by Micah
Modified: 2016-07-29 20:24 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Micah 2015-09-04 13:39:04 UTC
We at our company have a Xamarin Forms app that utilizes an OData Service Reference to pull data. We have added a service reference to the PCL class, and it works flawlessly in Android, but not in iOS unless I don't link assemblies, which causes our app to be huge (around 150MB). I've seen similar issues in other bug reports, but my exception differs slightly.

EXCEPTION:
{System.TypeInitializationException: An exception was thrown by the type initializer for System.Data.Services.Client.TypeSystem ---> System.ArgumentNullException: Argument cannot be null.
Parameter name: key
  at System.ThrowHelper.ThrowArgumentNullException (ExceptionArgument argument) [0x00000] in /Users/builder/data/lanes/1977/2c66d2fe/source/mono/external/referencesource/mscorlib/system/throwhelper.cs:82 
  at System.Collections.Generic.Dictionary`2[System.Reflection.MethodInfo,System.String].Insert (System.Reflection.MethodInfo key, System.String value, Boolean add) [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.Dictionary`2[System.Reflection.MethodInfo,System.String].Add (System.Reflection.MethodInfo key, System.String value) [0x00000] in <filename unknown>:0 
  at System.Data.Services.Client.TypeSystem..cctor () [0x0061b] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Data.Services.Client.ResourceBinder+PatternRules.MatchNonPrivateReadableProperty (System.Linq.Expressions.Expression e, System.Reflection.PropertyInfo& propInfo, System.Linq.Expressions.Expression& target) [0x00033] in <filename unknown>:0 
  at System.Data.Services.Client.ResourceBinder.VisitMemberAccess (System.Linq.Expressions.MemberExpression m) [0x00012] in <filename unknown>:0 
  at System.Data.Services.Client.ALinqExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x0011d] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x00055] in <filename unknown>:0 
  at System.Data.Services.Client.ALinqExpressionVisitor.VisitLambda (System.Linq.Expressions.LambdaExpression lambda) [0x00007] in <filename unknown>:0 
  at System.Data.Services.Client.ALinqExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x00137] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x00055] in <filename unknown>:0 
  at System.Data.Services.Client.ALinqExpressionVisitor.VisitUnary (System.Linq.Expressions.UnaryExpression u) [0x00007] in <filename unknown>:0 
  at System.Data.Services.Client.ALinqExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x000cf] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x00055] in <filename unknown>:0 
  at System.Data.Services.Client.ALinqExpressionVisitor.VisitExpressionList (System.Collections.ObjectModel.ReadOnlyCollection`1 original) [0x00015] in <filename unknown>:0 
  at System.Data.Services.Client.ALinqExpressionVisitor.VisitMethodCall (System.Linq.Expressions.MethodCallExpression m) [0x00014] in <filename unknown>:0 
  at System.Data.Services.Client.ResourceBinder.VisitMethodCall (System.Linq.Expressions.MethodCallExpression mce) [0x00025] in <filename unknown>:0 
  at System.Data.Services.Client.ALinqExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x0012a] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x00055] in <filename unknown>:0 
  at System.Data.Services.Client.ResourceBinder.Bind (System.Linq.Expressions.Expression e, System.Data.Services.Client.DataServiceContext context) [0x00007] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceQueryProvider.Translate (System.Linq.Expressions.Expression e) [0x00028] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceQuery`1[Vidant.Mobile.Core.Vidant.Service.Specialty].Translate () [0x00008] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceQuery`1[Vidant.Mobile.Core.Vidant.Service.Specialty].QueryComponents (System.Data.Services.Client.ClientEdmModel model) [0x00000] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceRequest.CreateExecuteResult (System.Object source, System.Data.Services.Client.DataServiceContext context, System.AsyncCallback callback, System.Object state, System.String method) [0x00007] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceRequest.BeginExecute (System.Object source, System.Data.Services.Client.DataServiceContext context, System.AsyncCallback callback, System.Object state, System.String method) [0x00000] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceQuery`1[Vidant.Mobile.Core.Vidant.Service.Specialty].BeginExecute (System.AsyncCallback callback, System.Object state) [0x00008] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceQuery`1[Vidant.Mobile.Core.Vidant.Service.Specialty].BeginExecuteInternal (System.AsyncCallback callback, System.Object state) [0x00000] in <filename unknown>:0 
  at System.Data.Services.Client.DataServiceQuery.BeginExecute (System.AsyncCallback callback, System.Object state) [0x00000] in <filename unknown>:0 
  at System.Threading.Tasks.TaskFactory`1[System.Collections.IEnumerable].FromAsyncImpl (System.Func`3 beginMethod, System.Func`2 endFunction, System.Action`1 endAction, System.Object state, TaskCreationOptions creationOptions) [0x00000] in <filename unknown>:0 }

EXAMPLE CODE:

// AppContext is just a reference to Application.Current

private async Task FilterPhysicianResults()
		{
			var specialty = SelectedSpecialty == "Any" ? "" : SelectedSpecialty;
			var facility = SelectedLocation == "Any" ? "" : SelectedLocation;
			var service = new Container(new Uri("http://services.mydomain.com/api/"));

			try
			{
				DataServiceQuery query;

				if (!String.IsNullOrEmpty(AppContext.NewPhysician.Name))
				{
					var trimmedName = AppContext.NewPhysician.Name.Trim();
					query =
						(DataServiceQuery)
							service.Providers.Where(
								provider =>
									provider.FirstName.StartsWith(trimmedName) || provider.LastName.StartsWith(trimmedName) ||
									provider.FullName.StartsWith(trimmedName));
				}
				else
				{
					query = service.Providers;

					if (!String.IsNullOrEmpty(specialty))
					{
						query =
							(DataServiceQuery)
								((DataServiceQuery<Service.Provider>) query).Where(
									provider =>
										provider.ProviderSpecialties.Any(providerSpecialty => providerSpecialty.Specialty.Name == specialty));
					}

					if (!String.IsNullOrEmpty(facility))
					{
						query =
							(DataServiceQuery)
								((DataServiceQuery<Service.Provider>) query).Where(
									provider => provider.ProviderFacilities.Any(providerFacility => providerFacility.Facility.Name == facility));
					}
				}

				ServicePhysicianCount = ServiceUtil.GetCount(query.RequestUri);

				var filteredPhysicians =
					await
						GetServiceItems<IEnumerable<Service.Provider>>(
							(DataServiceQuery)
								((DataServiceQuery<Service.Provider>) query)
									.Expand("ProviderFacilities/Facility")
									.Expand("ProviderSpecialties/Specialty")
									.OrderBy(physician => physician.FullName)
									.Skip(FilteredPhysicians.Count)
									.Take(10));

				ServicePhysicians.AddRange(filteredPhysicians);

				FilteredPhysicians =
					new ObservableCollection<Physician>(ServicePhysicians.Select(physician => new Physician(physician)));

				HasMoreResults = ServicePhysicianCount > FilteredPhysicians.Count;
				HasResults = FilteredPhysicians.Any();
			}
			catch (Exception e)
			{
// I this all in a try catch to see the exception because my method runs async
			}
		}
Comment 1 Sebastien Pouliot 2015-09-04 15:10:20 UTC
XI 8.4 is rather old, are you sure this is the version you're using ?

The easiest way to get exact version information is to use the "Xamarin Studio" menu, "About Xamarin Studio" item, "Show Details" button and copy/paste the version informations (you can use the "Copy Information" button).
Comment 2 Micah 2015-09-04 15:53:33 UTC
I apologize, I'm targeting iOS 8.4, not Xamarin. I have all the latest stable updates in Xamarin (8.10.4.46 (Enterprise Edition))
Comment 3 Daniel 2015-11-09 15:02:13 UTC
We ran into this exact same error, and managed to figure out its source.

Part of the constructor for the TypeSystem class builds a couple of dictionaries using reflection, which I think are used with Expressions.  One of the methods (Math.Round) doesn't appear to be preserved correctly, which makes the method to get it via reflection return null instead.  The method is used as the key for the dictionary, and of course keys can't be null.

The workaround we discovered was just to have calls to both Math.Round  overloads (decimal and double) somewhere in the code, and then we were able to build with the Link SDK Assemblies option.
Comment 4 Sebastien Pouliot 2016-06-10 17:35:55 UTC
That was fixed a while ago. The linker should not eliminate [1] Math.Round methods when TypeSystem is used.

If you still have that issue please re-open the bug and attach a test case so we can see what else could be missing. Thanks!

[1] https://github.com/xamarin/xamarin-macios/blob/master/tools/linker/MobileMarkStep.cs#L434
Comment 5 brian.reynolds 2016-07-29 20:24:04 UTC
Daniel, how did you figure out that it was the Math.Round method that was an issue? We are having a similar issue with our app. We're not using Math.round, so it's something similar, but different.