Skip to content

OpenApi doesn't convert query params to snake_case #60936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 task done
eskild-th opened this issue Mar 14, 2025 · 3 comments
Open
1 task done

OpenApi doesn't convert query params to snake_case #60936

eskild-th opened this issue Mar 14, 2025 · 3 comments
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi

Comments

@eskild-th
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

OpenApi doesn't pickup on ValueProvider changes.
I've replaced the default QueryStringValueProviderFactory with my own SnakeCaseQueryValueProviderFactory. The controller works as expected. But the generated OpenApi spec is still using camelCasing for query params.

Expected Behavior

I expect the OpenApi to pickup on the ValueProvider change and show the correct spec

"parameters": [
  {
      "name": "hello_world", // <----- snake case
      "in": "query",
      "schema": {
          "type": "integer",
          "format": "int32"
      }
  }
],

Steps To Reproduce

// startup

builder
    .Services.AddControllers(options =>
    {
        var index = options.ValueProviderFactories.IndexOf(
            options.ValueProviderFactories.OfType<QueryStringValueProviderFactory>().Single()
        );

        options.ValueProviderFactories[index] = new SnakeCaseQueryValueProviderFactory();
    })

builder.Services.AddOpenApi();

// controller

[HttpGet]
public IResult Get([FromQuery] int helloWorld)

Exceptions (if any)

No response

.NET Version

9.0.201

Anything else?

No response

@martincostello martincostello added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi and removed area-web-frameworks labels Mar 14, 2025
@martincostello
Copy link
Member

You need to configure the JSON serialization options used by OpenAPI to use snake_case:

#60513 (comment)

@martincostello martincostello added the ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. label Mar 14, 2025
@eskild-th
Copy link
Author

I did find that issue. But I think that only deals with json object property names.
The following correctly uses snake_case in the json response

builder.Services.AddControllers(...).AddJsonOptions(options => ConfigureJsonSerializer(options.JsonSerializerOptions));
builder.Services.ConfigureHttpJsonOptions(options => ConfigureJsonSerializer(options.SerializerOptions));

static void ConfigureJsonSerializer(JsonSerializerOptions options)
{
    options.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower;
}

However it doesn't change query parameters ([FromQuery]). And it probably shouldn't as it has to do with json serialization and not binding to a query parameter :)

The currently generated open api spec is as follows:

  "parameters": [
      {
          "name": "helloWorld", // <---- not snake_case
          "in": "query",
          "schema": {
              "type": "integer",
              "format": "int32"
          }
      }
  ],

it should be

  "parameters": [
      {
          "name": "hello_world", // <---- correct
          "in": "query",
          "schema": {
              "type": "integer",
              "format": "int32"
          }
      }
  ],

@martincostello martincostello removed ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Status: Resolved labels Mar 14, 2025
@captainsafia
Copy link
Member

@eskild-th Thanks for filing this issue!

The JsonSerializerOptions will only work for properties within in the schemas that are generated. The issue that you are seeing is with the parameter name.

I suspect that the issue here is actually in MVC, likely in the DefaultApiDescriptionProvider that is used to map MVC's model binding metadata to a set of metadata that the OpenAPI document can introspect.

In this particular case, I suspect that value providers are not correctly resolved by the provider.

We'll need to invetigate further why the ApiDescriptionProvider isn't picking this up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi
Projects
None yet
Development

No branches or pull requests

3 participants