1

I have a .NET Core GraphQL backend service consumed in a Blazor web assembly app with a GetData GraphQL query with an enum like this:

public enum SomeEnumTypes : byte
{
    None,
    First,
    SecondItem
} 

When the data is returned from the backend in that query, SecondItem from enum is returned as SECOND_ITEM to client but it results in an error:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Error converting value "SECOND_ITEM" to type 'SomeEnumTypes'. Path 'data.GetData[0].someEnumType', line 1, position 1375.

Newtonsoft.Json.JsonSerializationException: Error converting value "SECOND_ITEM" to type 'SomeEnumTypes'. Path 'data.GetData[0].someEnumType', line 1, position 1375.

System.ArgumentException: Requested value 'SECOND_ITEM' was not found.

at Newtonsoft.Json.Utilities.EnumUtils.ParseEnum(Type enumType, NamingStrategy namingStrategy, String value, Boolean disallowNumber)
at Newtonsoft.Json.Converters.StringEnumConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)

SomeEnumTypes enum is in a third party nuget library so I can't make any changes to the enum directly.

I tried multiple ways including writing custom converters for the Newtonsoft serializer with regex to handle underscores and even creating a dictionary for that enum to convert in the converter but no use.

_graphqlClient = new GraphQLHttpClient(_configuration.GetValue<string>("SomeKey"), new NewtonsoftJsonSerializer(options =>
{
    options.Converters.Add(new SomeConverter())
}));

Is there something I am missing? Help would be appreciated.

0

1 Answer 1

2

You appear to have found a bug with GraphQL.Client.Serializer.Newtonsoft:

  1. Json.NET applies converters in the order they are added to the JsonSerializerSettings.Converters list.

  2. NewtonsoftJsonSerializer adds a converter, ConstantCaseEnumConverter, to the beginning of the list, thereby superseding your SomeConverter converter which you add to the end.

  3. ConstantCaseEnumConverter is broken:

    • It serializes enums in CONSTANT_CASE but it deserializes them without any case policy at all, so an enum value like SecondItem => SECOND_ITEM cannot be round-tripped.
    • It applies its casing policy incorrectly for [Flags] enums, which should be comma-delimited like so: "FLAG_ITEM_ONE, FLAG_ITEM_THREE".

Honestly I can't figure out why GraphQL implemented their converter this way when it would have been much simpler to create a constant case naming strategy and set it on StringEnumConverter.NamingStrategy. I can only guess that they wanted to disable support for EnumMemberAttribute, which is not supported by SystemTextJsonSerializer.

As a workaround, you can create a fixed enum converter and insert it at the beginning of the converters list.

As long as you don't have [EnumMember("some name")] applied to any of your enums, the simplest way to create a fixed converter is to create your own custom naming strategy and use it with the Newtonsoft's built-in StringEnumConverter:

using GraphQL.Client.Abstractions.Utilities;

public sealed class ConstantCaseNamingStrategy : NamingStrategy
{
    protected override string ResolvePropertyName(string name) => name.ToConstantCase();
}

Then insert it at the beginning as follows:

new NewtonsoftJsonSerializer(
    options => 
        options.Converters.Insert(
            0, new StringEnumConverter(new ConstantCaseNamingStrategy())));

And you should be able to round-trip your SomeEnumTypes successfully.

Mockup fiddle here.

Sign up to request clarification or add additional context in comments.

1 Comment

This is interesting, I thought it to be too simple of a case to be missed. Thanks for your suggestions seems like have to do what you said.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.