dotnet / dotnet/aspnetcore

gRPC Transcoding: Invalid value for enum error when string enums enabled, integer values in swagger when string enums disabled

Open
#60,898 3 comments 0 reactions 0 assignees View on GitHub
area-grpc
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 5h
Merged PRs (30d)
276

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

I'm attempting to use both GRPC json transcoding and the swagger interface. This application will have both grpc services and traditional web services. I want to use string json values for enums, so I configure json like so:

```CSharp
builder.Services
.AddControllers()
.AddJsonOptions(j =>
{
j.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
```

I also add grpc to the swagger gen:

```CSharp
builder.Services.AddGrpcSwagger();
```

When configuring json transcoding, I use the default `WriteEnumsAsIntegers` set to `false`, but even explicitly setting it the result is the same:

```CSharp
builder.Services
.AddGrpc()
.AddJsonTranscoding(opts =>
{
opts.JsonSettings.WriteEnumsAsIntegers = false;
});
```

Here I'm defining an enum in the proto file:

```
enum EnumParam {
ENUM_PARAM_UNSPECIFIED = 0;
ENUM_PARAM_VALUE1 = 1;
ENUM_PARAM_VALUE2 = 2;
}
```

And here I'm defining an rpc method (the `Request` message is not shown, but has a `param` field of type `EnumParam`):

```
rpc GetMethod(Request) returns (Reply) {
option (google.api.http) = {
get: "/v1/{param}"
};
}
```

When I open up the swagger UI for the API, the UI correctly lists `Value1` and `Value2` as valid values for the `param` argument of the `GetMethod`. However, when making the request through the UI, the following error is given:

```
Invalid value 'Value1' for enum type EnumParam.
```

Now, when I remove the `JsonStringEnumConverter` in the json settings, and go to the swagger page, the dropdown for the enum parameter no longer lists strings values, but rather integer values (in this case 1 and 2 for `Value1` and `Value2`, however the requests parse the enums properly.

### Expected Behavior

When using `JsonStringEnumConverter`, I would expect the values to be parsed correctly when selected in the swagger UI. Further, given that GRPC enums are serialized as strings by default, I think the default behavior, at least when `WriteEnumsAsIntegers` is set to `false`, is to still serialize gRPC json-transcoded endpoints as string values, even without a `JsonStringEnumConverter` specified for Asp.net controllers.

### Steps To Reproduce

Sorry I don't have a repro repo and the original source is under NDA. If you create a basic gRPC service from the template with the above additions/changes described above, you should be able to reproduce this issue, but let me know and I can work on a small repro repo - it will take some time.

### Exceptions (if any)

```
2025-03-12T14:05:49 info: Grpc.AspNetCore.Grpc.JsonTranscoding.ServerCallHandler[7]
2025-03-12T14:05:49 Error reading message.
2025-03-12T14:05:49 System.InvalidOperationException: Invalid value 'Value1' for enum type EnumParam.
2025-03-12T14:05:49 at Grpc.Shared.ServiceDescriptorHelpers.ConvertValue(Object value, FieldDescriptor descriptor)
2025-03-12T14:05:49 at Grpc.Shared.ServiceDescriptorHelpers.SetValue(IMessage message, FieldDescriptor field, Object values)
2025-03-12T14:05:49 at Grpc.Shared.ServiceDescriptorHelpers.RecursiveSetValue(IMessage currentValue, List`1 pathDescriptors, Object values)
2025-03-12T14:05:49 at Microsoft.AspNetCore.Grpc.JsonTranscoding.Internal.JsonRequestHelpers.ReadMessage[TRequest](JsonTranscodingServerCallContext serverCallContext, JsonSerializerOptions serializerOptions)
```

### .NET Version

9.0.200

### Anything else?

```
.NET SDK:
Version: 9.0.200
Commit: 90e8b202f2
Workload version: 9.0.200-manifests.69179adf
MSBuild version: 17.13.8+cbc39bea8

Runtime Environment:
OS Name: Windows
OS Version: 10.0.26100
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.200\

.NET workloads installed:
[wasm-tools-net6]
Installation Source: VS 17.13.35825.156
Manifest Version: 9.0.2/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.workload.mono.toolchain.net6\9.0.2\WorkloadManifest.json
Install Type: Msi

[wasm-tools-net8]
Installation Source: VS 17.13.35825.156
Manifest Version: 9.0.2/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.workload.mono.toolchain.net8\9.0.2\WorkloadManifest.json
Install Type: Msi

[wasm-tools]
Installation Source: VS 17.13.35825.156
Manifest Version: 9.0.2/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.workload.mono.toolchain.current\9.0.2\WorkloadManifest.json
Install Type: Msi

[aspire]
Installation Source: VS 17.13.35825.156
Manifest Version: 8.2.2/8.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.2.2\WorkloadManifest.json
Install Type: Msi

Configured to use loose manifests when installing new manifests.

Host:
Version: 9.0.2
Architecture: x64
Commit: 80aa709f5d

.NET SDKs installed:
9.0.200 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.13 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
Not set

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.