diff --git a/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs b/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs index e20b60bf54..4d79779dd1 100644 --- a/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs +++ b/framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Reflection; using Castle.DynamicProxy; using JetBrains.Annotations; -using Polly; using Volo.Abp; using Volo.Abp.Castle.DynamicProxy; using Volo.Abp.Http.Client; @@ -30,23 +29,15 @@ namespace Microsoft.Extensions.DependencyInjection /// /// True, to register the HTTP client proxy as the default implementation for the services. /// - /// - /// A delegate that is used to configure an . - /// public static IServiceCollection AddHttpClientProxies( [NotNull] this IServiceCollection services, [NotNull] Assembly assembly, [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, - bool asDefaultServices = true, - Action configureHttpClientBuilder = null) + bool asDefaultServices = true) { Check.NotNull(services, nameof(assembly)); - AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder); - - //TODO: Make a configuration option and add remoteServiceName inside it! - - var serviceTypes = assembly.GetTypes().Where(IsSuitableForDynamicClientProxying); + var serviceTypes = assembly.GetTypes().Where(IsSuitableForDynamicClientProxying).ToArray(); foreach (var serviceType in serviceTypes) { @@ -72,17 +63,11 @@ namespace Microsoft.Extensions.DependencyInjection /// /// True, to register the HTTP client proxy as the default implementation for the service . /// - /// - /// A delegate that is used to configure an . - /// public static IServiceCollection AddHttpClientProxy( [NotNull] this IServiceCollection services, [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, - bool asDefaultService = true, - Action configureHttpClientBuilder = null) + bool asDefaultService = true) { - AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder); - return services.AddHttpClientProxy( typeof(T), remoteServiceConfigurationName, @@ -90,37 +75,6 @@ namespace Microsoft.Extensions.DependencyInjection ); } - /// - /// Use IHttpClientFactory and polly - /// - /// Service collection - /// - /// The name of the remote service configuration to be used by the HTTP Client proxies. - /// See . - /// - /// - /// A delegate that is used to configure an . - /// - public static IServiceCollection AddHttpClientFactoryAndPolicy( - [NotNull] this IServiceCollection services, - [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, - Action configureHttpClientBuilder = null) - { - var httpClientBuilder = services.AddHttpClient(remoteServiceConfigurationName); - if (configureHttpClientBuilder == null) - { - httpClientBuilder.AddTransientHttpErrorPolicy(builder => - // retry 3 times - builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i)))); - } - else - { - configureHttpClientBuilder.Invoke(httpClientBuilder); - } - - return services; - } - /// /// Registers HTTP Client Proxy for given service . /// @@ -143,6 +97,8 @@ namespace Microsoft.Extensions.DependencyInjection Check.NotNull(type, nameof(type)); Check.NotNullOrWhiteSpace(remoteServiceConfigurationName, nameof(remoteServiceConfigurationName)); + AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName); + services.Configure(options => { options.HttpClientProxies[type] = new DynamicHttpClientProxyConfig(type, remoteServiceConfigurationName); @@ -189,13 +145,36 @@ namespace Microsoft.Extensions.DependencyInjection return services; } + private static IServiceCollection AddHttpClientFactoryAndPolicy( + [NotNull] this IServiceCollection services, + [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName) + { + var preOptions = services.ExecutePreConfiguredActions(); + + if (preOptions.ConfiguredProxyClients.Contains(remoteServiceConfigurationName)) + { + return services; + } + + var clientBuilder = services.AddHttpClient(remoteServiceConfigurationName); + + foreach (var clientBuildAction in preOptions.ProxyClientBuildActions) + { + clientBuildAction(remoteServiceConfigurationName, clientBuilder); + } + + preOptions.ConfiguredProxyClients.Add(remoteServiceConfigurationName); + + return services; + } + /// /// Checks wether the type is suitable to use with the dynamic proxying. /// Currently the type is checked statically against some fixed conditions. /// /// Type to check /// True, if the type is suitable for dynamic proxying. Otherwise false. - static bool IsSuitableForDynamicClientProxying(Type type) + private static bool IsSuitableForDynamicClientProxying(Type type) { //TODO: Add option to change type filter diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientBuilderOptions.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientBuilderOptions.cs new file mode 100644 index 0000000000..7f11a6be12 --- /dev/null +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientBuilderOptions.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.Http.Client +{ + public class AbpHttpClientBuilderOptions + { + public List> ProxyClientBuildActions { get; } + + internal HashSet ConfiguredProxyClients { get; } + + public AbpHttpClientBuilderOptions() + { + ProxyClientBuildActions = new List>(); + ConfiguredProxyClients = new HashSet(); + } + } +} diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs index e2e5b7b9fe..e4e4f3e802 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs @@ -1,11 +1,11 @@ -using System.Linq; +using System; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Http; using Volo.Abp.Castle; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; using Volo.Abp.Validation; +using Polly; namespace Volo.Abp.Http.Client { @@ -18,29 +18,26 @@ namespace Volo.Abp.Http.Client )] public class AbpHttpClientModule : AbpModule { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - Configure(configuration); - } - - public override void PostConfigureServices(ServiceConfigurationContext context) + public override void PreConfigureServices(ServiceConfigurationContext context) { - Configure(options => + PreConfigure(options => { - if (options.HttpClientActions.Any()) + options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) => { - var httpClientNames = options.HttpClientProxies.Select(x => x.Value.RemoteServiceName); - foreach (var httpClientName in httpClientNames) - { - foreach (var httpClientAction in options.HttpClientActions) - { - context.Services.Configure(httpClientName, - x => x.HttpClientActions.Add(httpClientAction.Invoke(httpClientName))); - } - } - } + clientBuilder.AddTransientHttpErrorPolicy(policyBuilder => + policyBuilder.WaitAndRetryAsync( + 3, + i => TimeSpan.FromSeconds(Math.Pow(2, i)) + ) + ); + }); }); } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + Configure(configuration); + } } } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs index 54cc4eb624..2e6cd3798d 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Net.Http; using Volo.Abp.Http.Client.DynamicProxying; namespace Volo.Abp.Http.Client @@ -9,12 +8,9 @@ namespace Volo.Abp.Http.Client { public Dictionary HttpClientProxies { get; set; } - public List>> HttpClientActions { get; } - public AbpHttpClientOptions() { HttpClientProxies = new Dictionary(); - HttpClientActions = new List>>(); } } }