Skip to content

OpenAPI document generation does not generate correct refs for self-referencing collection properties #58006

Closed
@null-d3v

Description

@null-d3v

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Microsoft.AspNetCore.OpenApi will generate an invalid JSON schema when a parameter has a self-reference collection property. This does not seem to occur if the self reference is not a collection.

Using the following as a parameter:

public class Criteria
{
    public IEnumerable<Criteria> SubCriteria { get; set; } = [ ];
}

[FromBody] Criteria criteria

Will result in the JSON schema:

  "components": {
    "schemas": {
      "Criteria": {
        "type": "object",
        "properties": {
          "subCriteria": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/#"
            }
          }
        }
      }
    }
  },

Which has an invalid reference:

Resolver error at components.schemas.Criteria.properties.subCriteria.items.$ref
Could not resolve reference: Could not resolve pointer: /components/schemas/ does not exist in document

This occurs with both minimal APIs and controllers.

Expected Behavior

I would expect the subCriteria items reference to correctly point at #/components/schemas/Criteria.

Steps To Reproduce

Here is a complete self-contained Program.cs which will generate the invalid OpenAPI document:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi().CacheOutput();

app.MapPost("/item/search", ([FromBody] Criteria criteria) =>
{
    var items = Enumerable
        .Range(1, 5)
        .Select(index =>
            new Item
            {
                Name = index.ToString(),
            })
        .ToArray();
    return items;
})
.WithName("SearchItems")
.WithOpenApi();

app.Run();

public class Item
{
    public string Name { get; set; } = default!;
}

public class Criteria
{
    public IEnumerable<Criteria> SubCriteria { get; set; } = [ ];
}

And the OpenAPI document generated at /openapi/v1.json:

{
  "openapi": "3.0.1",
  "info": {
    "title": "Sample | v1",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "http://localhost:5129"
    }
  ],
  "paths": {
    "/item/search": {
      "post": {
        "tags": [
          "Sample"
        ],
        "operationId": "SearchItems",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Criteria"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Criteria": {
        "type": "object",
        "properties": {
          "subCriteria": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/#"
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Sample"
    }
  ]
}

Exceptions (if any)

No response

.NET Version

9.0.100-rc.1.24452.12

Anything else?

No response

Metadata

Metadata

Assignees

Labels

Needs: Author FeedbackThe author of this issue needs to respond in order for us to continue investigating this issue.area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcarea-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesfeature-openapi

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions