Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xamarin.Android - SqlClient connection broken since 5.1.1 #2251

Closed
farlop opened this issue Nov 30, 2023 · 9 comments
Closed

Xamarin.Android - SqlClient connection broken since 5.1.1 #2251

farlop opened this issue Nov 30, 2023 · 9 comments

Comments

@farlop
Copy link

farlop commented Nov 30, 2023

Describe the bug

Until version 5.1.0, a Xamarin Forms application running in Android could connect to an SQL Server database directly.

When tried to upgrade to latest, I've found that some change in 5.1.1 is causing to fail. Reverting to 5.1.0 solves the problem.

Exceptions info:

(System.ArgumentNullException) Value cannot be null.
Parameter name: path1  at System.IO.Path.Combine (System.String path1, System.String path2) [0x00003] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.IO/Path.cs:102 
  at System.Configuration.ClientConfigurationHost.get_MachineConfigFilePath () [0x00014] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ClientConfigurationHost.GetStreamName (System.String configPath) [0x00051] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.Internal.DelegatingConfigHost.GetStreamName (System.String configPath) [0x00006] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ImplicitMachineConfigHost.GetStreamName (System.String configPath) [0x00000] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.BaseConfigurationRecord.InitConfigFromFile () [0x00049] in <860085a6305a40768f26304153de5416>:0 
=======================================================(inner most exception)===
 (1) System.ArgumentNullException
================================================================================
Message:
"Value cannot be null.
Parameter name: path1"
Properties:
  String.ParamName = "path1"
Stack Trace:
  at System.IO.Path.Combine (System.String path1, System.String path2) [0x00003] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.IO/Path.cs:102 
  at System.Configuration.ClientConfigurationHost.get_MachineConfigFilePath () [0x00014] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ClientConfigurationHost.GetStreamName (System.String configPath) [0x00051] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.Internal.DelegatingConfigHost.GetStreamName (System.String configPath) [0x00006] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ImplicitMachineConfigHost.GetStreamName (System.String configPath) [0x00000] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.BaseConfigurationRecord.InitConfigFromFile () [0x00049] in <860085a6305a40768f26304153de5416>:0 
================================================================================
================================================================================
 (2) System.Configuration.ConfigurationErrorsException
================================================================================
Message:
"An error occurred loading a configuration file: Value cannot be null.
Parameter name: path1"
Properties:
  String.Filename = ""
  Int32.Line = "0"
  ICollection.Errors = {
    "System.Configuration.ConfigurationErrorsException: An error occurred loading a configuration file: Value cannot be null.
Parameter name: path1 ---> System.ArgumentNullException: Value cannot be null.
Parameter name: path1
  at System.IO.Path.Combine (System.String path1, System.String path2) [0x00003] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.IO/Path.cs:102 
  at System.Configuration.ClientConfigurationHost.get_MachineConfigFilePath () [0x00014] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ClientConfigurationHost.GetStreamName (System.String configPath) [0x00051] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.Internal.DelegatingConfigHost.GetStreamName (System.String configPath) [0x00006] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ImplicitMachineConfigHost.GetStreamName (System.String configPath) [0x00000] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.BaseConfigurationRecord.InitConfigFromFile () [0x00049] in <860085a6305a40768f26304153de5416>:0 
   --- End of inner exception stack trace ---",
  }
  String.BareMessage = "An error occurred loading a configuration file: Value cannot be null.
Parameter name: path1"
Stack Trace:
  at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors (System.Boolean ignoreLocal) [0x0001d] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors (System.Configuration.ConfigurationSchemaErrors schemaErrors) [0x00011] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.BaseConfigurationRecord.ThrowIfInitErrors () [0x00000] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ClientConfigurationSystem.EnsureInit (System.String configKey) [0x00060] in <860085a6305a40768f26304153de5416>:0 
================================================================================
================================================================================
 (3) System.Configuration.ConfigurationErrorsException
================================================================================
Message:
"Configuration system failed to initialize"
Properties:
  String.Filename = ""
  Int32.Line = "0"
  ICollection.Errors = {
    "System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize ---> System.Configuration.ConfigurationErrorsException: An error occurred loading a configuration file: Value cannot be null.
Parameter name: path1 ---> System.ArgumentNullException: Value cannot be null.
Parameter name: path1
  at System.IO.Path.Combine (System.String path1, System.String path2) [0x00003] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.IO/Path.cs:102 
  at System.Configuration.ClientConfigurationHost.get_MachineConfigFilePath () [0x00014] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ClientConfigurationHost.GetStreamName (System.String configPath) [0x00051] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.Internal.DelegatingConfigHost.GetStreamName (System.String configPath) [0x00006] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ImplicitMachineConfigHost.GetStreamName (System.String configPath) [0x00000] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.BaseConfigurationRecord.InitConfigFromFile () [0x00049] in <860085a6305a40768f26304153de5416>:0 
   --- End of inner exception stack trace ---
  at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors (System.Boolean ignoreLocal) [0x0001d] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors (System.Configuration.ConfigurationSchemaErrors schemaErrors) [0x00011] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.BaseConfigurationRecord.ThrowIfInitErrors () [0x00000] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ClientConfigurationSystem.EnsureInit (System.String configKey) [0x00060] in <860085a6305a40768f26304153de5416>:0 
   --- End of inner exception stack trace ---",
  }
  String.BareMessage = "Configuration system failed to initialize"
Stack Trace:
  at System.Configuration.ConfigurationManager.PrepareConfigSystem () [0x0001a] in <860085a6305a40768f26304153de5416>:0 
  at System.Configuration.ConfigurationManager.GetSection (System.String sectionName) [0x0000a] in <860085a6305a40768f26304153de5416>:0 
  at System.Runtime.Caching.MemoryCacheStatistics.InitializeConfiguration (System.Collections.Specialized.NameValueCollection config) [0x00016] in <a8fc702de12a46699fa97a1cc0178b91>:0 
  at System.Runtime.Caching.MemoryCacheStatistics..ctor (System.Runtime.Caching.MemoryCache memoryCache, System.Collections.Specialized.NameValueCollection config) [0x0002a] in <a8fc702de12a46699fa97a1cc0178b91>:0 
  at System.Runtime.Caching.MemoryCache.InitDisposableMembers (System.Collections.Specialized.NameValueCollection config) [0x0004e] in <a8fc702de12a46699fa97a1cc0178b91>:0 
  at System.Runtime.Caching.MemoryCache.Init (System.Collections.Specialized.NameValueCollection config) [0x00031] in <a8fc702de12a46699fa97a1cc0178b91>:0 
  at System.Runtime.Caching.MemoryCache..ctor (System.String name, System.Collections.Specialized.NameValueCollection config) [0x00058] in <a8fc702de12a46699fa97a1cc0178b91>:0 
  at Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider..cctor () [0x0000a] in <11becafcfd0b40b6ac61fd8694820c39>:0 
================================================================================
================================================================================
 (4) System.TypeInitializationException
================================================================================
Message:
"The type initializer for 'Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider' threw an exception."
Properties:
  String.TypeName = "Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider"
Stack Trace:
  at Microsoft.Data.SqlClient.SqlAuthenticationProviderManager.SetDefaultAuthProviders (Microsoft.Data.SqlClient.SqlAuthenticationProviderManager instance) [0x00003] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.SqlClient.SqlAuthenticationProviderManager..cctor () [0x0000a] in <11becafcfd0b40b6ac61fd8694820c39>:0 
================================================================================
================================================================================
 (5) System.TypeInitializationException
================================================================================
Message:
"The type initializer for 'Microsoft.Data.SqlClient.SqlAuthenticationProviderManager' threw an exception."
Properties:
  String.TypeName = "Microsoft.Data.SqlClient.SqlAuthenticationProviderManager"
Stack Trace:
  at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection (System.Data.Common.DbConnection owningObject, System.UInt32 waitForMultipleObjectsTimeout, System.Boolean allowCreate, System.Boolean onlyOneCheckConnection, Microsoft.Data.Common.DbConnectionOptions userOptions, Microsoft.Data.ProviderBase.DbConnectionInternal& connection) [0x000c4] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection (System.Data.Common.DbConnection owningObject, System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.Common.DbConnectionOptions userOptions, Microsoft.Data.ProviderBase.DbConnectionInternal& connection) [0x0003b] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection (System.Data.Common.DbConnection owningConnection, System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.Common.DbConnectionOptions userOptions, Microsoft.Data.ProviderBase.DbConnectionInternal oldConnection, Microsoft.Data.ProviderBase.DbConnectionInternal& connection) [0x0014d] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal (System.Data.Common.DbConnection outerConnection, Microsoft.Data.ProviderBase.DbConnectionFactory connectionFactory, System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.Common.DbConnectionOptions userOptions) [0x00036] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection (System.Data.Common.DbConnection outerConnection, Microsoft.Data.ProviderBase.DbConnectionFactory connectionFactory, System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.Common.DbConnectionOptions userOptions) [0x00000] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.SqlClient.SqlConnection.TryOpen (System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.SqlClient.SqlConnectionOverrides overrides) [0x000f0] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.SqlClient.SqlConnection.Open (Microsoft.Data.SqlClient.SqlConnectionOverrides overrides) [0x00082] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.SqlClient.SqlConnection.Open () [0x00000] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Honeywell.GWS.Connector.Library.Workflows.Checklist.SqlServer.Behavior.GetOperator (System.String operator) [0x0003d] in C:\DesarrolloNET\GWS-Workflows.Checklist\src\GWS-Workflows.Checklist.SqlServer\Behavior.cs:96 
  at Honeywell.GWS.Connector.Library.Workflows.Checklist.Workflow.ConnectAsync (Honeywell.GWS.Connector.SDK.Interfaces.IDevice device) [0x00000] in C:\DesarrolloNET\GWS-Workflows.Checklist\src\GWS-Workflows.Checklist\Workflow.cs:47 
  at VIO.VIOPluginDataTransport.SignOnAsync (System.String operatorId) [0x00058] in C:\DevKit\GWS App\src\VIOModule\Services\DataService\VIOPluginDataTransport.cs:294 
================================================================================

To reproduce

Include a complete code listing (or project/solution) that we can run to reproduce the issue.

Partial code listings, or multiple fragments of code, will slow down our response or cause us to push the issue back to you to provide code to reproduce the issue.

try
{
    using var cn = new SqlConnection("Server=172.20.18.143, 1433;Database=GWS-Workflows-Checklist;User Id=gws;Password=***;TrustServerCertificate=True;");

    cn.Open();
}
catch (Exception ex)
{
    // Exception is always raised
}

Expected behavior

Connection should be made and exception not be raised

Further technical details

Microsoft.Data.SqlClient version: 5.1.1
.NET target: Xamarin Forms
SQL Server version: SQL Server 2017
Operating system: Android

@farlop farlop changed the title Xamarin.Android - SqlClient library broken since 5.1.1 Xamarin.Android - SqlClient connection broken since 5.1.1 Nov 30, 2023
@DavoudEshtehari
Copy link
Contributor

@farlop can you verify 5.1.2 and 5.2.0-preview3 as well?

@DavoudEshtehari DavoudEshtehari added the 🆕 Triage Needed For new issues, not triaged yet. label Nov 30, 2023
@farlop
Copy link
Author

farlop commented Nov 30, 2023 via email

@farlop
Copy link
Author

farlop commented Dec 1, 2023

Just tested in 5.2.0-preview3 with same results:

================================================================================
 (5) System.TypeInitializationException
================================================================================
Message:
"The type initializer for 'Microsoft.Data.SqlClient.SqlAuthenticationProviderManager' threw an exception."
Properties:
  String.TypeName = "Microsoft.Data.SqlClient.SqlAuthenticationProviderManager"
Stack Trace:
  at (wrapper managed-to-native) System.Object.__icall_wrapper_mono_generic_class_init(intptr)
  at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor (Microsoft.Data.ProviderBase.DbConnectionPoolIdentity identity, Microsoft.Data.SqlClient.SqlConnectionString connectionOptions, Microsoft.Data.SqlClient.SqlCredential credential, System.Object providerInfo, System.String newPassword, System.Security.SecureString newSecurePassword, System.Boolean redirectedUserInstance, Microsoft.Data.SqlClient.SqlConnectionString userConnectionOptions, Microsoft.Data.SqlClient.SessionData reconnectSessionData, System.Boolean applyTransientFaultHandling, System.String accessToken, Microsoft.Data.ProviderBase.DbConnectionPool pool) [0x000b8] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection (Microsoft.Data.Common.DbConnectionOptions options, Microsoft.Data.Common.DbConnectionPoolKey poolKey, System.Object poolGroupProviderInfo, Microsoft.Data.ProviderBase.DbConnectionPool pool, System.Data.Common.DbConnection owningConnection, Microsoft.Data.Common.DbConnectionOptions userOptions) [0x00162] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection (Microsoft.Data.ProviderBase.DbConnectionPool pool, System.Data.Common.DbConnection owningObject, Microsoft.Data.Common.DbConnectionOptions options, Microsoft.Data.Common.DbConnectionPoolKey poolKey, Microsoft.Data.Common.DbConnectionOptions userOptions) [0x0000c] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject (System.Data.Common.DbConnection owningObject, Microsoft.Data.Common.DbConnectionOptions userOptions, Microsoft.Data.ProviderBase.DbConnectionInternal oldConnection) [0x001d5] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest (System.Data.Common.DbConnection owningObject, Microsoft.Data.Common.DbConnectionOptions userOptions, Microsoft.Data.ProviderBase.DbConnectionInternal oldConnection) [0x00040] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection (System.Data.Common.DbConnection owningObject, System.UInt32 waitForMultipleObjectsTimeout, System.Boolean allowCreate, System.Boolean onlyOneCheckConnection, Microsoft.Data.Common.DbConnectionOptions userOptions, Microsoft.Data.ProviderBase.DbConnectionInternal& connection) [0x000f7] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection (System.Data.Common.DbConnection owningObject, System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.Common.DbConnectionOptions userOptions, Microsoft.Data.ProviderBase.DbConnectionInternal& connection) [0x0003b] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection (System.Data.Common.DbConnection owningConnection, System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.Common.DbConnectionOptions userOptions, Microsoft.Data.ProviderBase.DbConnectionInternal oldConnection, Microsoft.Data.ProviderBase.DbConnectionInternal& connection) [0x0014d] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal (System.Data.Common.DbConnection outerConnection, Microsoft.Data.ProviderBase.DbConnectionFactory connectionFactory, System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.Common.DbConnectionOptions userOptions) [0x00036] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection (System.Data.Common.DbConnection outerConnection, Microsoft.Data.ProviderBase.DbConnectionFactory connectionFactory, System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.Common.DbConnectionOptions userOptions) [0x00000] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.SqlClient.SqlConnection.TryOpen (System.Threading.Tasks.TaskCompletionSource`1[TResult] retry, Microsoft.Data.SqlClient.SqlConnectionOverrides overrides) [0x000f0] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.SqlClient.SqlConnection.Open (Microsoft.Data.SqlClient.SqlConnectionOverrides overrides) [0x00082] in <11becafcfd0b40b6ac61fd8694820c39>:0 
  at Microsoft.Data.SqlClient.SqlConnection.Open () [0x00000] in <11becafcfd0b40b6ac61fd8694820c39>:0 

@farlop
Copy link
Author

farlop commented Dec 1, 2023

It seems that the problem may lie here

Here a new MemoryCache instance is being created, but the namespace System.Runtime.Caching is not supported in monoandroid.

From what I've read from other similar issues (here), a possible solution could be migrate to Microsoft.Extensions.Caching package. Or just handle this situation to avoid crashing in Xamarin Android

@kf-gonzalez kf-gonzalez removed the 🆕 Triage Needed For new issues, not triaged yet. label Dec 5, 2023
@farlop
Copy link
Author

farlop commented Feb 22, 2024

Hi! Is there any advance on this issue? We are being pushed to update the library to avoid security bugs already fixed, but unable to do it due to this error

@arellegue
Copy link
Contributor

@farlop We tried to reproduce the issue using MDS versions from 5.1.0, 5.1.1 and up to the latest. However, we are unable to reproduce the issue.

Would you mind sharing the source code including the project file for your repro for us to investigate any further?

@farlop
Copy link
Author

farlop commented Apr 15, 2024

I've created the following repository for the issue:

https://github.com/farlop/SqlClientBugRepro2251

I'm sorry for not noticing before that reproducing the error was not quite straightforward, as the process involves loading assemblies dynamically.

@arellegue
Copy link
Contributor

@farlop. Thank you for providing the reproduction source code. I noticed that you are using a custom loader for the MDS driver.
From version 5.1.1, the MDS driver is supposed to detect the platform is it currently running on and loads the correct dll from the runtime folder. However, in your case, since the target framework for your custom loader is .Netstandard2.1 for some reason the runtime folder is missing and therefore it may not have included the correct dlls for Android in the published distribution.

I tried to replicate your repro using a MAUI app since Xamarin support will end on May 1, 2024. Also, I added a custom loader for MDS driver that targets .Net8.0. the runtime folder did get created in the published distribution. However, it also has the same issue of not loading the correct dll for Android. To fix that, I just copied the dll from the runtime/unix folder into the main folder of the published distribution. If you want to try this option, then in your custom loader, you may want to implement the detection of the platform and load the appropriate dll from the runtime folder as well.

Lastly, since this issue is not directly related to MDS driver, but more in the way how it is used, we will now close this ticket.

@farlop
Copy link
Author

farlop commented Apr 18, 2024

Thanks @arellegue for reviewing my repro and provide a detailed answer. I truly appreciate that. Unfortunately I don't fully agree with the arguments that justify the error.

The problem of having the right assembly published (the one from runtime/Unix folder) is solved by using the RuntimeIdentifier in the publish profile. You can check that when adding that parameter with the Android value, the .ell published is 1,5Mb instead the few Kb version from NetStandard21 that just launched the not supported exception.

The problem with 5.1.1 and beyond is that it introduced the use of MemoryCache from the System.Runtime.Caching namespace, which is not available at mono Android. I referenced that change on my previous comment from December (#2251 (comment)).

Could a version 5.1.0.1 (for example) be released that just upgrades the dependency package to Axite.Identity that has that vulnerability? That would be a perfectly valid solution for us.

If not, is there any chance that some code could be added to avoid referencing that unsupported class in monoandroid?

I don't know it that scenario changes with .Net 8.0 and MAUI. I will give it a try, but unfortunately the migration to MAUI for the product is still an ongoing effort and we need to give support to customers, that are stopping the release.

Thank you again for your attention

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

No branches or pull requests

4 participants