- ABP Framework version: v8
- UI Type: Angular /
- Database System: EF Core (SQL Server,)
- Tiered (for MVC) or Auth Server Separated (for Angular): no
- Exception message and full stack trace:
- Steps to reproduce the issue:
Hello ABP team
As a followup on ticket: https://support.abp.io/QA/Questions/2360/Configure-ABP--Swashbuckle-to-represent-enums-as-strings
I just realized that the problem is actually now solved by introducing that package. Basically we want to configure ASP.Core to interpret the enums by their String values, and not integers. This is usually solved by adding:
services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); });
How can we achieve this with ABP?
Just to be clear, using Unchase.Swashbuckle.AspNetCore.Extensions is not the solution, since this will just add explanations to the integer values.
16 Answer(s)
-
0
hi
How can we achieve this with ABP?
services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); })
In abp project.
services.Configure<JsonOptions>(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); });
-
0
Hi,
Thanks for the initial input
I added this in
context.Services.AddOptions<JsonOptions>() .Configure<IServiceProvider>((options, rootServiceProvider) => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); });
in ConfigureServices, at the end. Still, this didn't transform the enums into strings
-
0
hi
Can you share a test template app?
liming.ma@volosoft.com
-
0
hi
I can't build and run your project. Can you check it?
your zip file has error.
-
0
Hi, sorry about posting the project to the wrong ticket.
I checked the build and it looks like you guys didn't fix the base template ( I reported a bug regarding this a long time ago )
Please change in Acme.BookStore.HttpApi.Host.csproj
<ItemGroup> <PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX" Version="3.0.-" /> </ItemGroup>
to <ItemGroup> <PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX" Version="3.0.0" /> </ItemGroup>
-
0
There is no
Program
file inAcme.BookStore.HttpApi.Host
-
0
Hi, yes there is
-
0
-
0
I created a new zip:
-
0
ok, I will check it asap.
-
0
hi
options.UserFriendlyEnums();
private static void ConfigureSwagger(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.AddAbpSwaggerGenWithOAuth( configuration["AuthServer:Authority"]!, new Dictionary<string, string> { {"BookStore", "BookStore API"} }, options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "BookStore API", Version = "v1" }); options.DocInclusionPredicate((docName, description) => true); options.CustomSchemaIds(type => type.FullName); options.UserFriendlyEnums(); }); }
-
0
Hi,
Thanks for your analysis. This solution only fixes the swagger UI, which now shows Enums as strings, but the serialization is still done as int. An example below, that property should have been returned as a string.
In a vanilla asp core + swagger project, this is fixed by using
services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); -
0
hi
I will enhance this in the abp framework.
context.Services.Configure<JsonOptions>(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.Converters.RemoveAll(x => x is AbpStringToEnumFactory); options.JsonSerializerOptions.Converters.Add(new MyAbpStringToEnumFactory()); });
using System; using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; using Volo.Abp.Json.SystemTextJson.JsonConverters; namespace Acme.BookStore; public class MyAbpStringToEnumFactory : JsonConverterFactory { private readonly JsonNamingPolicy? _namingPolicy; private readonly bool _allowIntegerValues; public MyAbpStringToEnumFactory() : this(namingPolicy: null, allowIntegerValues: true) { } public MyAbpStringToEnumFactory(JsonNamingPolicy? namingPolicy, bool allowIntegerValues) { _namingPolicy = namingPolicy; _allowIntegerValues = allowIntegerValues; } public override bool CanConvert(Type typeToConvert) { return typeToConvert.IsEnum; } public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { return (JsonConverter)Activator.CreateInstance( typeof(MyAbpStringToEnumConverter<>).MakeGenericType(typeToConvert), BindingFlags.Instance | BindingFlags.Public, binder: null, new object?[] { _namingPolicy, _allowIntegerValues }, culture: null)!; } } public class MyAbpStringToEnumConverter<T> : JsonConverter<T> where T : struct, Enum { private readonly JsonStringEnumConverter _innerJsonStringEnumConverter; private JsonSerializerOptions? _readJsonSerializerOptions; private JsonSerializerOptions? _writeJsonSerializerOptions; public MyAbpStringToEnumConverter() : this(namingPolicy: null, allowIntegerValues: true) { } public MyAbpStringToEnumConverter(JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true) { _innerJsonStringEnumConverter = new JsonStringEnumConverter(namingPolicy, allowIntegerValues); } public override bool CanConvert(Type typeToConvert) { return typeToConvert.IsEnum; } public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { _readJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(options, x => x == this || x.GetType() == typeof(AbpStringToEnumFactory), _innerJsonStringEnumConverter.CreateConverter(typeToConvert, options)); return JsonSerializer.Deserialize<T>(ref reader, _readJsonSerializerOptions); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { _writeJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(options, x => x == this || x.GetType() == typeof(MyAbpStringToEnumFactory), _innerJsonStringEnumConverter.CreateConverter(typeof(T), options)); JsonSerializer.Serialize(writer, value,_writeJsonSerializerOptions); } public override T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return (T)Enum.Parse(typeToConvert, reader.GetString()!); } public override void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { writer.WritePropertyName(Enum.GetName(typeof(T), value)!); } }
-
0
hi
https://github.com/abpframework/abp/pull/19132
-
0
Hi, Thanks for the support. In the meantime I should use your provided solution with MyAbpStringToEnumConverter ?
-
0
hi
Yes, You should use
MyAbpStringToEnumConverter
until the new version is released.