Fix OpenAPI enum schema for non-body parameters with naming policy#66228
Open
mikekistler wants to merge 9 commits intodotnet:mainfrom
Open
Fix OpenAPI enum schema for non-body parameters with naming policy#66228mikekistler wants to merge 9 commits intodotnet:mainfrom
mikekistler wants to merge 9 commits intodotnet:mainfrom
Conversation
When a global JsonStringEnumConverter with a naming policy (e.g. KebabCaseLower) is configured, the OpenAPI spec now emits the original C# enum member names for query/path/header parameters instead of the naming-policy-transformed values. This matches the actual binding behavior, which uses Enum.TryParse and only accepts the original member names. The fix adds logic in ApplyParameterInfo to detect non-body enum parameters and replace their schema enum values with Enum.GetNames(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When an enum with a global naming policy is used as both a query parameter and a body property/return type, the query param needs PascalCase values (for Enum.TryParse) while the body needs the naming-policy-transformed values (for JSON serialization). Skip componentization for non-body enum parameters when a naming policy transforms the values, returning an inline schema instead. This preserves the component schema with naming-policy values for body use while giving query/path/header parameters their own inline schema with the original C# member names. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes an OpenAPI/spec mismatch where global JsonStringEnumConverter naming policies were being applied to non-body parameters (query/path/header), even though runtime binding uses Enum.TryParse and only accepts the original C# enum member names.
Changes:
- Adjust enum parameter schemas for non-body parameters to emit original enum member names.
- Avoid schema componentization for affected non-body enum parameters to prevent shared component schemas (used for body serialization) from overwriting corrected parameter schemas.
- Add tests covering query-parameter enums with a global naming policy, including mixed query + response usage of the same enum.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Shared/SharedTypes.cs | Adds a new test enum (Priority) used for global-naming-policy scenarios. |
| src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiSchemaService/OpenApiSchemaService.ParameterSchemas.cs | Adds coverage ensuring query parameter enums use original member names while response bodies keep naming-policy output. |
| src/OpenApi/src/Services/Schemas/OpenApiSchemaService.cs | Skips componentization for affected non-body enum parameters when naming policy transforms enum values. |
| src/OpenApi/src/Extensions/JsonNodeSchemaExtensions.cs | Rewrites enum values for applicable parameter schemas to match Enum.TryParse expectations. |
Add BindingSource.Form and BindingSource.FormFile to IsNonBodyBindingSource so that enum form fields also use original C# member names instead of naming-policy-transformed values. Minimal APIs report [FromForm] enum parameters with BindingSource.FormFile, so both sources are needed. Add test: GetOpenApiRequestBody_EnumFormFieldWithGlobalNamingPolicy_UsesOriginalMemberNames Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3 tasks
This was referenced Apr 12, 2026
Closed
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…y fix Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…dy parameters Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…licy Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #65026
When a global
JsonStringEnumConverterwith a naming policy (e.g.KebabCaseLower) is configured viaConfigureHttpJsonOptions, the OpenAPI spec can emit naming-policy-transformed enum values (e.g.my-value) for non-body parameters. However, query/path/header/form parameter binding useEnum.TryParse, which only accepts the original C# member names (e.g.MyValue). This causes clients following the spec to send values that the server rejects with 400.Changes
JsonNodeSchemaExtensions.ApplyParameterInfo— For non-body enum parameters (query, path, header, and form), replaces the naming-policy-transformed enum values withEnum.GetNames()so the schema matches whatEnum.TryParseaccepts.OpenApiSchemaService.GetOrCreateSchemaAsync— When a naming policy transforms enum values, skips schema componentization for non-body enum parameters and returns an inline schema instead. This prevents the shared component (which retains naming-policy values for body serialization) from overwriting the corrected parameter schema.These two changes work together so that:
Enum.TryParsebehavior)Tests
GetOpenApiParameters_EnumWithGlobalNamingPolicy_UsesOriginalMemberNames— verifies query param enum values are PascalCase when a globalKebabCaseLowerpolicy is configuredGetOpenApiParameters_EnumWithGlobalNamingPolicy_HandlesQueryAndBodyUsage— verifies the same enum type produces PascalCase for query params and kebab-case for body responsesGetOpenApiRequestBody_EnumFormFieldWithGlobalNamingPolicy_UsesOriginalMemberNames— verifies[FromForm]enum values stay in their original C# member formAll 222
OpenApiSchemaServiceTestspass.