Skip to content

OpenAPI: Context.GetOrCreateSchemaAsync used in IOpenApiDocumentTransformer doesnt resolve some references #67657

Description

@MattInternet

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Our application has some POCOs that are used over SignalR that we like to include in our openAPI specs so clients can use them, for most classes this isnt necessary because the POCOs are used in a controller so they are exported to the spec already.

To do this we added an attribute that is picked up on by an IOpenApiDocumentTransformer that adds the schema to the openAPI spec (ExtraOpenApiSchemasDocumentTransformer below).

We've run into an issue where we have two POCOs, StartCheckinDto and StoreCheckinDto, that both reference an enum CheckinType. The StartCheckinDto is used in a controller and correctly used a reference for the property it has that is of type CheckinType:

Image

The StoreCheckinDto, which uses our attribute & document transformer to be included in the schema without being used in a controller, does not use a reference in the spec and instead re-declares the CheckinType enum:

Image

I did come across issue 63598 which seems related, but I'm not quite sure...

Inside of our IOpenApiDocumentTransformer I checked and the x-schema-id for both the CheckinType that is properly declared and referenced by StartCheckinDto and the one used while generating the StoreCheckinDto match and are both "CheckinType"

Expected Behavior

Both StartCheckinDto and StoreCheckinDto should reference the same CheckinType in the spec

Steps To Reproduce

Here are the various classes described above:

/// <summary>
/// Adds any entities with the <see cref="IncludeInOpenApiSchemaAttribute"/> to the
/// OpenAPI Document if they are not present.
/// </summary>
internal class ExtraOpenApiSchemasDocumentTransformer : IOpenApiDocumentTransformer
{
    public async Task TransformAsync(
        OpenApiDocument document,
        OpenApiDocumentTransformerContext context,
        CancellationToken cancellationToken
    )
    {
        document.Components ??= new OpenApiComponents();
        document.Components.Schemas ??= new Dictionary<string, IOpenApiSchema>();

        foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
        {
            if (type.GetCustomAttributes(typeof(IncludeInOpenApiSchemaAttribute), true).Length > 0)
            {
                if (!document.Components.Schemas.ContainsKey(type.Name))
                {
                    var openApiSchema = await context.GetOrCreateSchemaAsync(
                        type,
                        null,
                        cancellationToken
                    );
                    document.Components.Schemas.Add(type.Name, openApiSchema);
                }
            }
        }
    }
}

public enum CheckinType
{
    Shop,
    Vend,
}

public class Checkin : BaseEntity
{
    public required Guid StoreId { get; set; }

    public required Guid CustomerId { get; set; }

    public required CheckinType Type { get; set; }
}

public class StartCheckinDto
{
    public required Guid CustomerId { get; set; }

    public required CheckinType Type { get; set; }
}

[IncludeInOpenApiSchema]
public record StoreCheckinDto
{
    public required Guid CheckinId { get; set; }
    public required CheckinType CheckinType { get; set; }
    public required Guid CustomerId { get; set; }
}

Exceptions (if any)

No response

.NET Version

10.0.103

Anything else?

Microsoft.AspNetCore.OpenApi @ 10.0.9
Microsoft.OpenApi @ 2.9.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions