gRPC JSON transcoding — Unable to resolve descriptor for Enum (deserialize enum from string value)
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the bug
It's impossible to deserialize a string value of protobuf enum using Microsoft.AspNetCore.Grpc.JsonTranscoding 7.0.0.
Received rror:
{
"code": 3,
"message": "Unable to resolve descriptor for Example.Country.Alpha3CountryCode.",
"details": []
}
I think the problem with the method ResolveEnumDescriptor in Microsoft.AspNetCore.Grpc.JsonTranscoding.Internal.Json.EnumConverter<TEnum>. It expects that the enum type is defined as a nested type in a message
private static EnumDescriptor? ResolveEnumDescriptor(Type typeToConvert)
{
var containingType = typeToConvert?.DeclaringType?.DeclaringType;
if (containingType != null)
{
var messageDescriptor = JsonConverterHelper.GetMessageDescriptor(containingType);
if (messageDescriptor != null)
{
for (var i = 0; i < messageDescriptor.EnumTypes.Count; i++)
{
if (messageDescriptor.EnumTypes[i].ClrType == typeToConvert)
{
return messageDescriptor.EnumTypes[i];
}
}
}
}
return null;
}
Setting TypeRegistry in the transcoding options doesn't solve this problem.
Expected Behavior
Both int value and string value can be deserialized from JSON.
Steps To Reproduce
I wrote a small web app to reproduce this issue. Link.
Exceptions (if any)
System.InvalidOperationException: Unable to resolve descriptor for Example.Country.Alpha3CountryCode.
at Microsoft.AspNetCore.Grpc.JsonTranscoding.Internal.Json.EnumConverter`1.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
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)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.Serialization.JsonConverter`1.ReadCoreAsObject(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore[TValue](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo, ReadStack& state)
at System.Text.Json.JsonSerializer.ContinueDeserialize[TValue](ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, JsonTypeInfo jsonTypeInfo)
at System.Text.Json.JsonSerializer.ReadFromStreamAsync[TValue](Stream utf8Json, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Grpc.JsonTranscoding.Internal.JsonRequestHelpers.ReadMessage[TRequest](JsonTranscodingServerCallContext serverCallContext, JsonSerializerOptions serializerOptions)
at Microsoft.AspNetCore.Grpc.JsonTranscoding.Internal.JsonRequestHelpers.ReadMessage[TRequest](JsonTranscodingServerCallContext serverCallContext, JsonSerializerOptions serializerOptions)
info: Grpc.AspNetCore.Grpc.JsonTranscoding.ServerCallHandler[3]
Error status code 'InvalidArgument' with detail 'Unable to resolve descriptor for Example.Country.Alpha3CountryCode.' raised.
System.InvalidOperationException: Unable to resolve descriptor for Example.Country.Alpha3CountryCode.
at Microsoft.AspNetCore.Grpc.JsonTranscoding.Internal.Json.EnumConverter`1.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
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)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.Serialization.JsonConverter`1.ReadCoreAsObject(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore[TValue](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo, ReadStack& state)
at System.Text.Json.JsonSerializer.ContinueDeserialize[TValue](ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, JsonTypeInfo jsonTypeInfo)
at System.Text.Json.JsonSerializer.ReadFromStreamAsync[TValue](Stream utf8Json, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Grpc.JsonTranscoding.Internal.JsonRequestHelpers.ReadMessage[TRequest](JsonTranscodingServerCallContext serverCallContext, JsonSerializerOptions serializerOptions)
at Microsoft.AspNetCore.Grpc.JsonTranscoding.Internal.JsonRequestHelpers.ReadMessage[TRequest](JsonTranscodingServerCallContext serverCallContext, JsonSerializerOptions serializerOptions)
.NET Version
7.0.100
Anything else?
Packages:
<PackageReference Include="Grpc.AspNetCore" Version="2.50.0" />
<PackageReference Include="Grpc.AspNetCore.Server.Reflection" Version="2.50.0" />
<PackageReference Include="Microsoft.AspNetCore.Grpc.JsonTranscoding" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Grpc.Swagger" Version="0.3.0" />
Hi, I took a look at this and non-nested enum values don't work in .NET 7. Unfortunately, there is no way to work around this without changing your proto file. You have to make the enum nested inside a message.
I have a PR to fix this - https://github.com/dotnet/aspnetcore/pull/45273. I will get it backported to .NET 7 so a future service release of .NET 7 gets the fix.
Cool! When is this update going to be released?
It might take a couple of months before it makes it onto NuGet.org in an update.
@AndrewP-GH Attached is an unofficial package from the fix PR. It's one option if you don't want to wait.
Thank you!