Have managed to get this working.
In the API project this registration would not trigger the read. This is still the registration on the web project.
services.Configure<AbpSystemTextJsonSerializerOptions>(options => c
{
options.JsonSerializerOptions.Converters.Add(new PaymentRequestProductExtraParameterConfigurationJsonConverter());
});
Adding the JsonConverter
in the API project against the JsonOptions
instead of AbpSystemTextJsonSerializerOptions
resolved the issue and the read now trigger.
Configure<JsonOptions>(options =>
{
options.JsonSerializerOptions.Converters.Add(new PaymentRequestProductExtraParameterConfigurationJsonConverter());
});
This did not resolve my issue, I am still experiencing the same error.
I added the new JsonConverter
to my web project.
The API is still throwing the following exception:
Deserialization of interface or abstract types is not supported. Type 'Volo.Payment.IPaymentRequestProductExtraParameterConfiguration'. Path: $.products[0].extraProperties.ZendaPaymentRequestProductExtraParameterConfiguration | LineNumber: 0 | BytePositionInLine: 213
StackTrace:
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(ReadStack& state, Utf8JsonReader& reader, Exception innerException)
at System.Text.Json.ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(JsonTypeInfo typeInfo, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonDictionaryConverter`3.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TDictionary& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.ContinueDeserialize(ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, T& value)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsync(Stream utf8Json, CancellationToken cancellationToken)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsObjectAsync(Stream utf8Json, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object container)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
I also add the same JsonConverter
to the API project where the exception is being thrown.
We are building a microservice-based solution using abp.io and the ABP Payment module.
In our payment workflow, we use PaymentRequestProductCreateDto
, which has an ExtraProperties
property of type Dictionary<string, IPaymentRequestProductExtraParameterConfiguration>
.
We need to pass custom gateway configuration data (e.g., ZendaPaymentRequestProductExtraParameterConfiguration) through this property.
public class ZendaPaymentRequestProductExtraParameterConfiguration : IPaymentRequestProductExtraParameterConfiguration
{
public string RegisterNo { get; set; }
}
However, when sending this DTO between services (e.g., via HTTP), we encounter the following error during deserialization
Deserialization of interface or abstract types is not supported. Type 'Volo.Payment.IPaymentRequestProductExtraParameterConfiguration'. Path: $.products[0].extraProperties.Zenda | LineNumber: 0 | BytePositionInLine: 165.
Expected behaviour: We would like to be able to pass custom configuration objects in ExtraProperties across microservice boundaries without serialization issues, or have guidance on the recommended ABP approach for this scenario.
Question: What is the recommended way to use ExtraProperties for gateway-specific configuration in a microservice environment, given the interface-based dictionary and serialization limitations?