Skip to content

OpenAPI Ref invalid when objects cycles #58915

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 task done
Chrille79 opened this issue Nov 13, 2024 · 10 comments
Closed
1 task done

OpenAPI Ref invalid when objects cycles #58915

Chrille79 opened this issue Nov 13, 2024 · 10 comments
Labels
area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc feature-openapi

Comments

@Chrille79
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

If you have an model with types as following Person->Address->Person
The referens get invalid and doesnt point to a type in components

"$ref": "#/components/schemas/#/properties/myAddress/properties/mailOfficer"

Expected Behavior

$refs must reference a valid location in the document

Steps To Reproduce

Example application

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();


app.MapGet("/person", () =>
{
    return new Person();
})
.WithName("GetPerson");

app.Run();

public class Person
{
    public string Name { get; set; } = string.Empty;
    public Address MyAddress { get; set; } = new();
    public Address? MyAltAddress { get; set; }
}
public class Address
{
    public string Street { get; set; } = string.Empty;
    public string? City { get; set; }
    public int Number { get; set; }

    public Person? MailOfficer { get; set; } /* Ref error if included */
}

Schema output

{
  "openapi": "3.0.1",
  "info": {
    "title": "ExploringOAPI | v1",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://localhost:7103"
    },
    {
      "url": "http://localhost:5263"
    }
  ],
  "paths": {
    "/person": {
      "get": {
        "tags": [
          "ExploringOAPI"
        ],
        "operationId": "GetPerson",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Person"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Address": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string"
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "number": {
            "type": "integer",
            "format": "int32"
          },
          "mailOfficer": {
            "$ref": "#/components/schemas/Person2"
          }
        }
      },
      "Address2": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string"
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "number": {
            "type": "integer",
            "format": "int32"
          },
          "mailOfficer": {
            "$ref": "#/components/schemas/#/properties/myAddress/properties/mailOfficer"
          }
        },
        "nullable": true
      },
      "Person": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "myAddress": {
            "$ref": "#/components/schemas/Address"
          },
          "myAltAddress": {
            "$ref": "#/components/schemas/#/properties/myAddress/properties/mailOfficer/properties/myAltAddress"
          }
        }
      },
      "Person2": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "myAddress": {
            "$ref": "#/components/schemas/#/properties/myAddress"
          },
          "myAltAddress": {
            "$ref": "#/components/schemas/Address2"
          }
        },
        "nullable": true
      }
    }
  },
  "tags": [
    {
      "name": "ExploringOAPI"
    }
  ]
}

Exceptions (if any)

No response

.NET Version

9.0.100

Anything else?

No response

@ghost ghost added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label Nov 13, 2024
@martincostello martincostello added feature-openapi area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc and removed needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically labels Nov 13, 2024
@leaHaimovich
Copy link

Use JsonIgnore for Circular Property
or Use a Custom Schema Filter (builder.Services.AddSwaggerGen(c =>
{
c.SchemaFilter();
});
)

@Chrille79
Copy link
Author

Use JsonIgnore for Circular Property or Use a Custom Schema Filter (builder.Services.AddSwaggerGen(c => { c.SchemaFilter(); }); )

This is Microsoft.Openapi and the reference in schema are not RFC3986 compliant. To use AddSwaggerGen from swashbuckle is a workaround, but not a fix on the bug

@ZeroZipZilch
Copy link

ZeroZipZilch commented Nov 18, 2024

It doesn't even have to cycle. It's enough to reference the same class twice in two different collections.

public class WeatherForecast
{
    // Having "Update" in two lists causes the bug to surface.
    public List<Update> RainUpdates { get; set; }
    public List<Update> HurricaneUpdates { get; set; }
}
    
public sealed class Update
{
    public DateOnly Date { get; set; }
    public string Message { get; set; }    
}

@akamor
Copy link

akamor commented Nov 22, 2024

Hitting same issue without cycles. Likely related to #58968.

@kylejuliandev
Copy link

I could reproduce this with another example (see Gist)

public class OrderResponse
{
    public string Id { get; set; }
    public decimal Amount { get; set; }
    public List<Transaction>? Transactions { get; set; }
    public List<Item> Items { get; set; }
}

public class Transaction
{
    public string Id { get; set; }
    public List<Item> Items { get; set; }
}

public class Item
{
    public string Id { get; set; }
}

The swagger editor complains about the following:

  • $ref values must be RFC3986-compliant percent-encoded URIs
  • $refs must reference a valid location in the document

It does not play nicely with collections of the same type

@henning-krause
Copy link

I'm hitting this issue with a non-cycling class. Just two types having a property of type SomeType[]. The references in the "items" property of the OpenAPI document are messed up.

Hope there will be a for .net 9.

@willieburger
Copy link

I am also have the same issue - the generated json files are not usable. Is there any idea on when a fix will be available or a possible workaround?

@captainsafia
Copy link
Member

Closing this in favor of #58968. I believe it's the same issue.

Latest update on this over at #58968 (comment).

@Chrille79
Copy link
Author

Still invalid ref in 9.0.2

@BigBigPlant
Copy link

same error
first object is ok ,other is error

Image

Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc feature-openapi
Projects
None yet
Development

No branches or pull requests

10 participants