diff --git a/src/OpenApi/src/Extensions/JsonNodeSchemaExtensions.cs b/src/OpenApi/src/Extensions/JsonNodeSchemaExtensions.cs index 8e94a8e8b90c..7152e2d65f64 100644 --- a/src/OpenApi/src/Extensions/JsonNodeSchemaExtensions.cs +++ b/src/OpenApi/src/Extensions/JsonNodeSchemaExtensions.cs @@ -329,8 +329,19 @@ internal static void ApplyParameterInfo(this JsonNode schema, ApiParameterDescri { if (parameterInfo.HasDefaultValue) { - schema.ApplyDefaultValue(parameterInfo.DefaultValue, jsonTypeInfo); + var defaultValue = parameterInfo.DefaultValue; + + // ParameterInfo.DefaultValue returns the underlying integral value for Nullable parameters, + // so convert it back to the enum type before serializing it. + if (defaultValue is not null + && Nullable.GetUnderlyingType(parameterInfo.ParameterType) is { IsEnum: true } enumType) + { + defaultValue = Enum.ToObject(enumType, defaultValue); + } + + schema.ApplyDefaultValue(defaultValue, jsonTypeInfo); } + else if (parameterInfo.GetCustomAttributes().LastOrDefault() is { } defaultValueAttribute) { schema.ApplyDefaultValue(defaultValueAttribute.Value, jsonTypeInfo); diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiSchemaService/OpenApiSchemaService.ParameterSchemas.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiSchemaService/OpenApiSchemaService.ParameterSchemas.cs index 559759290d8b..43e42d4127e5 100644 --- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiSchemaService/OpenApiSchemaService.ParameterSchemas.cs +++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiSchemaService/OpenApiSchemaService.ParameterSchemas.cs @@ -163,6 +163,9 @@ await VerifyOpenApiDocument(builder, document => [(TaskStatus status = TaskStatus.Canceled) => { }, (JsonNode defaultValue) => Assert.Equal(6, defaultValue.GetValue())], // Default value for enums is serialized as string when a converter is registered. [(Status status = Status.Pending) => { }, (JsonNode defaultValue) => Assert.Equal("Pending", defaultValue.GetValue())], + [(Status? status = Status.Pending) => { }, (JsonNode defaultValue) => Assert.Equal("Pending", defaultValue.GetValue())], + [(TaskStatus? status = TaskStatus.Canceled) => { }, (JsonNode defaultValue) => Assert.Equal(6, defaultValue.GetValue())], + [(Status? status = null) => { }, (JsonNode defaultValue) => Assert.True(defaultValue is null)], [([DefaultValue(2)] int id) => { }, (JsonNode defaultValue) => Assert.Equal(2, defaultValue.GetValue())], [([DefaultValue(3f)] float id) => { }, (JsonNode defaultValue) => Assert.Equal(3, defaultValue.GetValue())], [([DefaultValue("test")] string id) => { }, (JsonNode defaultValue) => Assert.Equal("test", defaultValue.GetValue())], @@ -198,6 +201,19 @@ await VerifyOpenApiDocument(builder, document => } #nullable restore + [Fact] + public async Task GetOpenApiRequestBody_HandlesNullableEnumBodyParameterWithDefaultValue() + { + var builder = CreateBuilder(); + builder.MapPost("/api/body", ([FromBody] Status? status = Status.Pending) => status); + + await VerifyOpenApiDocument(builder, document => + { + var op = document.Paths["/api/body"].Operations[HttpMethod.Post]; + Assert.NotNull(op.RequestBody); + }); + } + [Fact] public async Task GetOpenApiParameters_HandlesEnumParameterWithoutConverter() {