daniil.poiarkov@happentechnologies.com的活动

Hi,

Yes, it is available when you extend the object, but the entity is difficult to do because of the database provider.

As we are using MongoDb we found a solution using same collection for entity, which inherits from build-in one, where we are able to easily expand it witout extension methods and have all necessary properties in one place. Hope it can be usefull if someone will have same problem

Hi,

You need to remove the AbpStringToEnumFactory

Just an example:

public class EnumToStringConverterFactory : JsonConverterFactory 
{ 
    public override bool CanConvert(Type typeToConvert) 
    { 
        return typeToConvert.IsEnum; 
    } 
 
    public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) 
    { 
        return (JsonConverter)Activator.CreateInstance( 
            typeof(MyEnumToStringConverter<>).MakeGenericType(typeToConvert), 
            BindingFlags.Instance | BindingFlags.Public, 
            binder: null, 
            new object?[] { }, 
            culture: null)!; 
    } 
} 
 
public class MyEnumToStringConverter<T> : JsonConverter<T> 
    where T : struct, Enum 
{ 
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 
    { 
        return Enum.Parse<T>(reader.GetString()!); 
    } 
 
    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) 
    { 
        writer.WriteStringValue(value.ToString()); 
    } 
} 
 
Configure<AbpSystemTextJsonSerializerOptions>(options => 
{ 
    var stringToEnumFactory = options.JsonSerializerOptions.Converters.Single(x => x.GetType() == typeof(AbpStringToEnumFactory)); 
    options.JsonSerializerOptions.Converters.Remove(stringToEnumFactory); 
    options.JsonSerializerOptions.Converters.Add(new EnumToStringConverterFactory()); 
}); 
 
Configure<JsonOptions>(options => 
{ 
    var stringToEnumFactory = options.JsonSerializerOptions.Converters.Single(x => x.GetType() == typeof(AbpStringToEnumFactory)); 
    options.JsonSerializerOptions.Converters.Remove(stringToEnumFactory); 
    options.JsonSerializerOptions.Converters.Add(new EnumToStringConverterFactory()); 
}); 

Thanks a lot, removing AbpStringToEnumFactory solved my problem)

Hi,

Could you provide the full steps to reproduce the problem? I will check it. thanks

Sure,

  1. Configure Mvc.JsonOptions via Configure method (HttpApi.Host module)
  2. Dto
  3. Response

And this is how response look like with [JsonConvert(typeof(JsonStringEnumConverter))] attribute for SubscriptionType field

Our goal is to achive this without attribute specification

HI, Liangshiwei Yea, I tried to configure Mvc.JsonOptions as well, but still I need to use JsonConverter attribute. I'm wonder if it is possible to achieve this without specifying attribute on each enum property.

You can check this: https://github.com/abpframework/abp/issues/13010

Hi, I'm trying to globally configure json serialization options to return enum properties as strings in response body. I tried to configure AbpSystemTextJsonSerializerOptions and AbpSystemTextJsonSerializerModifiersOptions, but the one way it worked using [JsonConvert(typeof(...))] atrribute. We want to find a way to make it work without attribute usage. Is it possible in current version or maybe I missed something?

  • ABP Framework version: v7.4.0
  • UI Type: Angular
  • Database System: MongoDB
  • Tiered (for MVC) or Auth Server Separated (for Angular): no
  • Exception message and full stack trace:
  • Steps to reproduce the issue:

Hi,

This is the limit of ExtraProperties, it only supports primitives.

Thank you very much for clarifying. I was confused that in docs it says that we can set and get it using non-generic method, but no info that we can't persist it

I tried to extend IdentityUser using ExtraProperties. It works fine with primitives, but it throws exception when setting complex object ObjectExtensionManager.Instance has been configured for IdentityUser as well. Is it even possible to store class or it's not supposed to used like this with Identity?

  • ABP Framework version: v7.4.0
  • UI Type: Angular
  • Database System: MongoDB
  • Tiered (for MVC) or Auth Server Separated (for Angular): no
  • Exception message and full stack trace:
  • An error occurred while serializing the ExtraProperties property of class Volo.Abp.Domain.Entities.AggregateRoot1[[System.Guid, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]: .NET type SBX.Identity.UserProfile cannot be mapped to a BsonValue. MongoDB.Bson.BsonSerializationException: An error occurred while serializing the ExtraProperties property of class Volo.Abp.Domain.Entities.AggregateRoot1[[System.Guid, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]: .NET type SBX.Identity.UserProfile cannot be mapped to a BsonValue. ---> System.ArgumentException: .NET type SBX.Identity.UserProfile cannot be mapped to a BsonValue. at MongoDB.Bson.BsonTypeMapper.MapToBsonValue(Object value) at MongoDB.Bson.Serialization.BsonClassMapSerializer1.SerializeExtraElements(BsonSerializationContext context, Object obj, BsonMemberMap extraElementsMemberMap) at MongoDB.Bson.Serialization.BsonClassMapSerializer1.SerializeMember(BsonSerializationContext context, Object obj, BsonMemberMap memberMap) --- End of inner exception stack trace --- at MongoDB.Bson.Serialization.BsonClassMapSerializer1.SerializeMember(BsonSerializationContext context, Object obj, BsonMemberMap memberMap) at MongoDB.Bson.Serialization.BsonClassMapSerializer1.SerializeClass(BsonSerializationContext context, BsonSerializationArgs args, TClass document) at MongoDB.Bson.Serialization.BsonClassMapSerializer1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TClass value) at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value) at MongoDB.Bson.Serialization.Serializers.BsonDocumentWrapperSerializer.SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, BsonDocumentWrapper value) at MongoDB.Bson.Serialization.Serializers.BsonValueSerializerBase1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TBsonValue value) at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value) at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize[TValue](IBsonSerializer1 serializer, BsonSerializationContext context, TValue value) at MongoDB.Driver.Core.Operations.RetryableUpdateCommandOperation.UpdateRequestSerializer.SerializeUpdate(BsonSerializationContext context, BsonSerializationArgs args, UpdateRequest request) at MongoDB.Driver.Core.Operations.RetryableUpdateCommandOperation.UpdateRequestSerializer.SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, UpdateRequest value) at MongoDB.Bson.Serialization.Serializers.SealedClassSerializerBase1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value) at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value) at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteType1Section(BsonBinaryWriter writer, Type1CommandMessageSection section, Int64 messageStartPosition) at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteSection(BsonBinaryWriter writer, CommandMessageSection section, Int64 messageStartPosition) at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteSections(BsonBinaryWriter writer, IEnumerable1 sections, Int64 messageStartPosition) at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteMessage(CommandMessage message) at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandRequestMessageBinaryEncoder.WriteMessage(CommandRequestMessage message) at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandRequestMessageBinaryEncoder.MongoDB.Driver.Core.WireProtocol.Messages.Encoders.IMessageEncoder.WriteMessage(MongoDBMessage message) at MongoDB.Driver.Core.Connections.BinaryConnection.SendMessagesHelper.EncodeMessages(CancellationToken cancellationToken, List1& sentMessages) at MongoDB.Driver.Core.Connections.BinaryConnection.SendMessagesAsync(IEnumerable1 messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) at MongoDB.Driver.Core.ConnectionPools.ExclusiveConnectionPool.PooledConnection.SendMessagesAsync(IEnumerable1 messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol1.ExecuteAsync(IConnection connection, CancellationToken cancellationToken) at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocolAsync[TResult](IWireProtocol1 protocol, ICoreSession session, CancellationToken cancellationToken) at MongoDB.Driver.Core.Operations.RetryableWriteOperationExecutor.ExecuteAsync[TResult](IRetryableWriteOperation1 operation, RetryableWriteContext context, CancellationToken cancellationToken) at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase1.ExecuteBatchAsync(RetryableWriteContext context, Batch batch, CancellationToken cancellationToken) at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase1.ExecuteBatchesAsync(RetryableWriteContext context, CancellationToken cancellationToken) at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.ExecuteBatchAsync(RetryableWriteContext context, Batch batch, CancellationToken cancellationToken) at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.ExecuteAsync(IWriteBinding binding, CancellationToken cancellationToken) at MongoDB.Driver.OperationExecutor.ExecuteWriteOperationAsync[TResult](IWriteBinding binding, IWriteOperation1 operation, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl1.ExecuteWriteOperationAsync[TResult](IClientSessionHandle session, IWriteOperation1 operation, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl1.BulkWriteAsync(IClientSessionHandle session, IEnumerable1 requests, BulkWriteOptions options, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl1.UsingImplicitSessionAsync[TResult](Func2 funcAsync, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionBase1.ReplaceOneAsync(FilterDefinition1 filter, TDocument replacement, ReplaceOptions options, Func3 bulkWriteAsync) at Volo.Abp.Domain.Repositories.MongoDB.MongoDbRepository2.UpdateAsync(TEntity entity, Boolean autoSave, CancellationToken cancellationToken) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Volo.Abp.Identity.IdentityUserStore.UpdateAsync(IdentityUser user, CancellationToken cancellationToken) at Microsoft.AspNetCore.Identity.UserManager1.UpdateUserAsync(TUser user) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at SBX.UserManagement.AAAUserProfileTestService.Test(String email, String aboutMe) in C:\Users\HP\source\repos\sbx\aspnet-core\src\SBX.Application\UserManagement\AAAUserProfileTestService.cs:line 31 at lambda_method2998(Closure, Object) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.

Steps to reproduce:

  1. Fetch user from database using IdentityUserManager
  2. Set new extra property using user-defined class
  3. Call UpdateAsync using IdentityUserManager
显示 7 个条目中的 1 到 7 个.
Made with ❤️ on ABP v8.2.0-preview Updated on 三月 25, 2024, 15:11