Skip to content

OpenAPI document generation fails for a Guid property initialized from an optional constructor parameter with default value #134620

Description

@dmartinezfernandez

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Microsoft.AspNetCore.OpenApi fails to generate the OpenAPI document when a response type has an optional primary constructor parameter of type Guid whose default value is specified as default.

The following declaration is valid C#:

public class Class1(int id, Guid code = default)
{
    public int Id { get; set; } = id;
    public Guid Code { get; set; } = code;
}

default(Guid) evaluates to Guid.Empty, which is a valid Guid value. However, requesting /openapi/v1.json throws the following exception:

System.Text.Json.JsonException: The JSON value could not be converted to System.Guid.

The exception occurs while Microsoft.AspNetCore.OpenApi is generating the JSON schema for the response type.

This may be related to dotnet/aspnetcore#60019, but this case does not involve assigning a value of an incompatible type. The declared parameter type is Guid, and its default value is also a Guid.

Expected Behavior

The OpenAPI document should be generated successfully.

If the constructor parameter's default value is included in the schema, it should be represented as the JSON serialization of Guid.Empty:

"00000000-0000-0000-0000-000000000000"

Alternatively, the default value may be omitted from the schema, but OpenAPI document generation should not fail.

Steps To Reproduce

Create a minimal ASP.NET Core application using the following project file:

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net10.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.12" />
    </ItemGroup>

</Project>

Replace the contents of Program.cs with the following code:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();

app.MapGet("/test", () =>
{
    return new Class1(Random.Shared.Next(0, 100), Guid.NewGuid());
})
.WithName("GetTest");

app.Run();

public class Class1(int id, Guid code = default)
{
    public int Id { get; set; } = id;
    public Guid Code { get; set; } = code;
}

Run the application and request:

/openapi/v1.json

The request fails with a System.Text.Json.JsonException while generating the OpenAPI schema for Class1.

Removing the default value from the constructor parameter prevents the exception:

public class Class1(int id, Guid code)
{
    public int Id { get; set; } = id;
    public Guid Code { get; set; } = code;
}

Exceptions (if any)

System.Text.Json.JsonException: The JSON value could not be converted to System.Guid.
   at System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType)
   at System.Text.Json.JsonSerializer.UnboxOnWrite[T](Object value)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsObject(Utf8JsonWriter writer, Object rootValue)
   at System.Text.Json.JsonSerializer.WriteNodeAsObject(Object value, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.Schema.JsonSchemaExporter.MapJsonSchemaCore(GenerationState& state, JsonTypeInfo typeInfo, JsonPropertyInfo propertyInfo, JsonConverter customConverter, Nullable`1 customNumberHandling, JsonTypeInfo parentPolymorphicTypeInfo, Boolean parentPolymorphicTypeContainsTypesWithoutDiscriminator, Boolean parentPolymorphicTypeIsNonNullable, Nullable`1 typeDiscriminator, Boolean cacheResult)
   at System.Text.Json.Schema.JsonSchemaExporter.GetJsonSchemaAsNode(JsonTypeInfo typeInfo, JsonSchemaExporterOptions exporterOptions)
   at Microsoft.AspNetCore.OpenApi.OpenApiSchemaService.CreateSchema(Type type)
   at Microsoft.AspNetCore.OpenApi.OpenApiSchemaService.GetOrCreateUnresolvedSchemaAsync(OpenApiDocument document, Type type, IServiceProvider scopedServiceProvider, IOpenApiSchemaTransformer[] schemaTransformers, ApiParameterDescription parameterDescription, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiSchemaService.GetOrCreateSchemaAsync(OpenApiDocument document, Type type, IServiceProvider scopedServiceProvider, IOpenApiSchemaTransformer[] schemaTransformers, ApiParameterDescription parameterDescription, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetResponseAsync(OpenApiDocument document, ApiDescription apiDescription, Int32 statusCode, ApiResponseType apiResponseType, IServiceProvider scopedServiceProvider, IOpenApiSchemaTransformer[] schemaTransformers, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetResponsesAsync(OpenApiDocument document, ApiDescription description, IServiceProvider scopedServiceProvider, IOpenApiSchemaTransformer[] schemaTransformers, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOperationAsync(ApiDescription description, OpenApiDocument document, IServiceProvider scopedServiceProvider, IOpenApiSchemaTransformer[] schemaTransformers, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOperationsAsync(IGrouping`2 descriptions, OpenApiDocument document, IServiceProvider scopedServiceProvider, IOpenApiOperationTransformer[] operationTransformers, IOpenApiSchemaTransformer[] schemaTransformers, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiPathsAsync(OpenApiDocument document, IServiceProvider scopedServiceProvider, IOpenApiOperationTransformer[] operationTransformers, IOpenApiSchemaTransformer[] schemaTransformers, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiDocumentAsync(IServiceProvider scopedServiceProvider, HttpRequest httpRequest, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.<>c__DisplayClass0_0.<<MapOpenApi>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Http.Generated.<GeneratedRouteBuilderExtensions_g>F0399B8B15BE443123F4BECEE84B112C1912EE3F44D9DDD7BFA38E371FB917343__GeneratedRouteBuilderExtensionsCore.<>c__DisplayClass2_0.<<MapGet0>g__RequestHandler|5>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

.NET Version

10.0.204

Anything else?

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions