diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs index 9b9c8e804c..6f8b5da376 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs @@ -18,17 +18,21 @@ namespace Volo.Abp.Http.Client.DynamicProxying protected IApiDescriptionCache Cache { get; } + protected IParameterTypeComparer ParameterTypeComparer { get; } + private static readonly JsonSerializerSettings SharedJsonSerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; public ApiDescriptionFinder( - IApiDescriptionCache cache, - IDynamicProxyHttpClientFactory httpClientFactory) + IApiDescriptionCache cache, + IDynamicProxyHttpClientFactory httpClientFactory, + IParameterTypeComparer parameterTypeComparer) { Cache = cache; HttpClientFactory = httpClientFactory; + ParameterTypeComparer = parameterTypeComparer; CancellationTokenProvider = NullCancellationTokenProvider.Instance; } @@ -57,7 +61,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying for (int i = 0; i < methodParameters.Length; i++) { - if (action.ParametersOnMethod[i].TypeAsString != methodParameters[i].ParameterType.GetFullNameWithAssemblyName()) + if (!ParameterTypeComparer.TypeMatches(action.ParametersOnMethod[i], methodParameters[i])) { found = false; break; diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/CrossPlatformParameterTypeComparer.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/CrossPlatformParameterTypeComparer.cs new file mode 100644 index 0000000000..e9142ffe3f --- /dev/null +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/CrossPlatformParameterTypeComparer.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Modeling; + +namespace Volo.Abp.Http.Client.DynamicProxying +{ + /// + /// Compares the server-side parameter-type with the local parameter-type considering differences between + /// the .net-core and the traditional .net-framework. + /// Inspired by 'https://github.com/akkadotnet/akka.net/pull/2947/files' + /// + public class CrossPlatformParameterTypeComparer : ParameterTypeComparer, ITransientDependency + { + const string Placeholder = "%COREFX%"; + const string NetCoreLib = "System.Private.CoreLib"; + const string NetFxLib = "mscorlib"; + + static readonly bool runsOnNetFx; + + static CrossPlatformParameterTypeComparer() + { + runsOnNetFx = string.IsNullOrEmpty(EnvironmentHelper.RuntimeNetCoreVersion); + } + + public override bool TypeMatches(MethodParameterApiDescriptionModel actionParameter, ParameterInfo methodParameter) + { + if (runsOnNetFx) + { + // Compare the server's DotnetCore type relative to the current, traditional framework type + // by replacing framework assemblies with an placeholder string. + return actionParameter.TypeAsString.Replace(NetCoreLib, Placeholder) + == methodParameter.ParameterType.GetFullNameWithAssemblyName().Replace(NetFxLib, Placeholder); + } + else + { + return base.TypeMatches(actionParameter, methodParameter); + } + } + } +} diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/EnvironmentHelper.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/EnvironmentHelper.cs new file mode 100644 index 0000000000..0ed914e419 --- /dev/null +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/EnvironmentHelper.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace Volo.Abp.Http.Client.DynamicProxying +{ + /// + /// Provide helpers to check the environment where the current ABP app is currently running + /// + static class EnvironmentHelper + { + /// + /// Initializes the class. + /// + static EnvironmentHelper() + { + RuntimeNetCoreVersion = GetNetCoreVersion(); + } + + /// + /// Gets the runtime net core version. + /// + /// + /// If the is null the app is running on a .net Classic environment + /// + public static string RuntimeNetCoreVersion { get; } + + /// + /// Gets the net core version. + /// + static string GetNetCoreVersion() + { + var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly; + var assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); + int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App"); + if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2) + { + return assemblyPath[netCoreAppIndex + 1]; + } + return null; + } + } +} diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/IParameterTypeComparer.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/IParameterTypeComparer.cs new file mode 100644 index 0000000000..079029bf93 --- /dev/null +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/IParameterTypeComparer.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Volo.Abp.Http.Modeling; + +namespace Volo.Abp.Http.Client.DynamicProxying +{ + public interface IParameterTypeComparer + { + /// + /// Compares the given parameters. + /// + /// The parameter description retreived from the server (depends on the server's runtime) + /// The local parameter info (depends on the client's runtime) + /// + public bool TypeMatches(MethodParameterApiDescriptionModel actionParameter, ParameterInfo methodParameter); + } +} diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ParameterTypeComparer.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ParameterTypeComparer.cs new file mode 100644 index 0000000000..6551ba3108 --- /dev/null +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ParameterTypeComparer.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Volo.Abp.Http.Modeling; + +namespace Volo.Abp.Http.Client.DynamicProxying +{ + public class ParameterTypeComparer : IParameterTypeComparer + { + public virtual bool TypeMatches(MethodParameterApiDescriptionModel actionParameter, ParameterInfo methodParameter) + { + return actionParameter.TypeAsString == methodParameter.ParameterType.GetFullNameWithAssemblyName(); + } + } +}