diff --git a/src/clients/Elsa.Api.Client/Converters/TypeJsonConverter.cs b/src/clients/Elsa.Api.Client/Converters/TypeJsonConverter.cs
new file mode 100644
index 000000000..60602c7bc
--- /dev/null
+++ b/src/clients/Elsa.Api.Client/Converters/TypeJsonConverter.cs
@@ -0,0 +1,56 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Elsa.Api.Client.Extensions;
+using JetBrains.Annotations;
+
+namespace Elsa.Api.Client.Converters;
+
+///
+/// Converts objects to and from their assembly-qualified name.
+///
+[UsedImplicitly]
+public class TypeJsonConverter : JsonConverter
+{
+ ///
+ public override bool CanConvert(Type typeToConvert)
+ {
+ return typeToConvert == typeof(Type) || typeToConvert.FullName == "System.RuntimeType";
+ }
+
+ ///
+ public override Type? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ var typeName = reader.GetString()!;
+
+ // Handle collection types.
+ if (typeName.EndsWith("[]"))
+ {
+ var elementTypeName = typeName[..^"[]".Length];
+ var elementType = Type.GetType(elementTypeName)!;
+ return typeof(List<>).MakeGenericType(elementType);
+ }
+
+ return Type.GetType(typeName);
+ }
+
+ ///
+ public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options)
+ {
+ // Handle collection types.
+ if (value is { IsGenericType: true, GenericTypeArguments.Length: 1 })
+ {
+ var elementType = value.GenericTypeArguments.First();
+ var typedEnumerable = typeof(IEnumerable<>).MakeGenericType(elementType);
+
+ if (typedEnumerable.IsAssignableFrom(value))
+ {
+ var elementTypeName = value.GetSimpleAssemblyQualifiedName();
+ JsonSerializer.Serialize(writer, $"{elementTypeName}[]", options);
+ return;
+ }
+ }
+
+ var typeName = value.GetSimpleAssemblyQualifiedName();
+ JsonSerializer.Serialize(writer, typeName, options);
+ }
+}
\ No newline at end of file
diff --git a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs
index 1dec341fd..e7bed4507 100644
--- a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs
+++ b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs
@@ -124,7 +124,7 @@ public static class DependencyInjectionExtensions
/// An options object that can be used to configure the HTTP client builder.
public static IServiceCollection AddApi(this IServiceCollection services, Type apiType, ElsaClientBuilderOptions? httpClientBuilderOptions = default)
{
- var builder = services.AddRefitClient(apiType, _ => CreateRefitSettings(), apiType.Name).ConfigureHttpClient(ConfigureElsaApiHttpClient);
+ var builder = services.AddRefitClient(apiType, sp => CreateRefitSettings(sp, httpClientBuilderOptions?.ConfigureJsonSerializerOptions), apiType.Name).ConfigureHttpClient(ConfigureElsaApiHttpClient);
httpClientBuilderOptions?.ConfigureHttpClientBuilder(builder);
httpClientBuilderOptions?.ConfigureRetryPolicy?.Invoke(builder);
return services;
@@ -139,7 +139,7 @@ public static class DependencyInjectionExtensions
public static void AddApiWithoutRetryPolicy(this IServiceCollection services, ElsaClientBuilderOptions? httpClientBuilderOptions = default) where T : class
{
var builder = services
- .AddRefitClient(_ => CreateRefitSettings(), typeof(T).Name)
+ .AddRefitClient(sp => CreateRefitSettings(sp), typeof(T).Name)
.ConfigureHttpClient(ConfigureElsaApiHttpClient);
httpClientBuilderOptions?.ConfigureHttpClientBuilder(builder);
}
@@ -156,7 +156,7 @@ public static class DependencyInjectionExtensions
/// Creates an API client for the specified API type.
public static T CreateApi(this IServiceProvider serviceProvider, HttpClient httpClient) where T : class
{
- return RestService.For(httpClient, CreateRefitSettings());
+ return RestService.For(httpClient, CreateRefitSettings(serviceProvider));
}
private static void ConfigureElsaApiHttpClient(IServiceProvider serviceProvider, HttpClient httpClient)
diff --git a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs
index ec47e8710..8a87220a3 100644
--- a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs
+++ b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs
@@ -10,17 +10,12 @@ namespace Elsa.Api.Client;
///
public static class RefitSettingsHelper
{
- private static JsonSerializerOptions? _jsonSerializerOptions;
-
///
/// Creates a instance configured for Elsa.
///
- public static RefitSettings CreateRefitSettings()
+ public static RefitSettings CreateRefitSettings(IServiceProvider serviceProvider, Action? configureJsonSerializerOptions = null)
{
- var settings = new RefitSettings
- {
- ContentSerializer = new SystemTextJsonContentSerializer(CreateJsonSerializerOptions())
- };
+ var settings = new RefitSettings { ContentSerializer = new SystemTextJsonContentSerializer(CreateJsonSerializerOptions(serviceProvider, configureJsonSerializerOptions)) };
return settings;
}
@@ -28,11 +23,8 @@ public static class RefitSettingsHelper
///
/// Creates a instance configured for Elsa.
///
- public static JsonSerializerOptions CreateJsonSerializerOptions()
+ public static JsonSerializerOptions CreateJsonSerializerOptions(IServiceProvider serviceProvider, Action? configureJsonSerializerOptions = null)
{
- if (_jsonSerializerOptions != null)
- return _jsonSerializerOptions;
-
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
@@ -40,7 +32,10 @@ public static class RefitSettingsHelper
options.Converters.Add(new JsonStringEnumConverter());
options.Converters.Add(new VersionOptionsJsonConverter());
+ options.Converters.Add(new TypeJsonConverter());
- return _jsonSerializerOptions = options;
+ configureJsonSerializerOptions?.Invoke(serviceProvider, options);
+
+ return options;
}
}
\ No newline at end of file
diff --git a/src/clients/Elsa.Api.Client/Options/ElsaClientBuilderOptions.cs b/src/clients/Elsa.Api.Client/Options/ElsaClientBuilderOptions.cs
index a7312eb60..52b0b1b77 100644
--- a/src/clients/Elsa.Api.Client/Options/ElsaClientBuilderOptions.cs
+++ b/src/clients/Elsa.Api.Client/Options/ElsaClientBuilderOptions.cs
@@ -1,3 +1,4 @@
+using System.Text.Json;
using Elsa.Api.Client.HttpMessageHandlers;
using Microsoft.Extensions.DependencyInjection;
using Polly;
@@ -39,4 +40,9 @@ public class ElsaClientBuilderOptions
/// Gets or sets a delegate that can be used to configure the retry policy.
///
public Action? ConfigureRetryPolicy { get; set; } = builder => builder.AddTransientHttpErrorPolicy(p => p.WaitAndRetryAsync(3, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt))));
+
+ ///
+ /// Gets or sets a delegate that can be used to configure the JSON serializer options.
+ ///
+ public Action? ConfigureJsonSerializerOptions { get; set; }
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs
index 3442a9c11..dee636927 100644
--- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs
+++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/TypeJsonConverter.cs
@@ -9,7 +9,7 @@ namespace Elsa.Workflows.Serialization.Converters;
///
/// Serializes objects to a simple alias representing the type.
///
-[PublicAPI]
+[UsedImplicitly]
public class TypeJsonConverter : JsonConverter
{
private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry;