Skip to content

OpenAPI: Circular reference in specific order gives empty schema #63503

@desjoerd

Description

@desjoerd

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When having a circular model with a reference, the reference schema will be empty when the properties are in a specific order.

Expected Behavior

Regardless of property order the referenced schema should be generated.

Steps To Reproduce

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Sample.Endpoints;

public static class CircularEndpointsExtensions
{
    public static IEndpointRouteBuilder MapCircularEndpoints1(this IEndpointRouteBuilder endpointRouteBuilder)
    {
        var circularSchemaRoutes = endpointRouteBuilder.MapGroup("circular1")
            .WithGroupName("circular1");

        circularSchemaRoutes.MapGet("/model", () => TypedResults.Ok(new CircularModel1()));

        return circularSchemaRoutes;
    }
    public static IEndpointRouteBuilder MapCircularEndpoints2(this IEndpointRouteBuilder endpointRouteBuilder)
    {
        var circularSchemaRoutes = endpointRouteBuilder.MapGroup("circular2")
            .WithGroupName("circular2");

        circularSchemaRoutes.MapGet("/model", () => TypedResults.Ok(new CircularModel2()));

        return circularSchemaRoutes;
    }

    public class CircularModel1
    {
        public ReferencedModel Referenced { get; set; } = null!;
        public CircularModel1 Self { get; set; } = null!;
    }

    public class CircularModel2
    {
        public CircularModel2 Self { get; set; } = null!;
        public ReferencedModel Referenced { get; set; } = null!;
    }

    public class ReferencedModel
    {
        public int Id { get; set; }
    }
}

Output of circular1:

openapi: '3.1.1'
info:
  title: Sample | circular1
  version: 1.0.0
servers:
  - url: https://localhost:7174/
paths:
  /circular1/model:
    get:
      tags:
        - Sample
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CircularModel1'
components:
  schemas:
    CircularModel1:
      type: object
      properties:
        referenced:
          $ref: '#/components/schemas/ReferencedObject'
        self:
          $ref: '#/components/schemas/CircularModel1'
    ReferencedObject: { }
tags:
  - name: Sample

Output of circular2

openapi: '3.1.1'
info:
  title: Sample | circular2
  version: 1.0.0
servers:
  - url: https://localhost:7174/
paths:
  /circular2/model:
    get:
      tags:
        - Sample
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CircularModel2'
components:
  schemas:
    CircularModel2:
      type: object
      properties:
        self:
          $ref: '#/components/schemas/CircularModel2'
        referenced:
          $ref: '#/components/schemas/ReferencedObject'
    ReferencedObject:
      type: object
      properties:
        id:
          type: integer
          format: int32
tags:
  - name: Sample

Exceptions (if any)

No response

.NET Version

main branch (commit bb2d778)

Anything else?

Related PR which fixes a lot already on this part. #63256

The issue is very specific. When the ReferencedModel is used somewhere else it gets generated correctly. So the workaround would be either:

  • Change the order of the properties
  • Have another endpoint which uses the ReferencedModel
  • Use GetOrCreateSchemaAsync for the ReferencedModel

Tagging @captainsafia 😊.

I also got a question, it feels like the SchemaExporter of dotnet is kind of flawed when it comes to referenced schemas. Would it not be possible to use the GetOrCreateSchemaAsync method to handle nested properties/referenced types instead?

Metadata

Metadata

Assignees

Labels

area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapi

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions