Is there an existing issue for this?
Describe the bug
I was migrating an ASP.NET Core Web API from .NET 8.0 to .NET 9.0.
As part of the migration, I was replacing AddSwaggerGen() with AddOpenApi() and seeing this critical issue. This basically inserts duplicated schema to OpenAPI specification. Solid OpenAPI specification is critical when integrating with services like APIM and hence subject is marked with Critical.
Consider the following minimal reproducible example.
csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="7.2.0" />
</ItemGroup>
</Project>
Startup.cs
namespace WebApplication3;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddOpenApi();
services.AddControllers();
}
public void Configure(IApplicationBuilder app)
{
app.UseSwaggerUI(x =>
{
x.SwaggerEndpoint("/openapi/v1.json", "My API");
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapOpenApi();
endpoints.MapControllers();
});
}
}
Program.cs
namespace WebApplication3;
public class Program
{
public static void Main(string[] args)
{
IHost host = CreateHostBuilder(args).Build();
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
WeatherForecastController.cs
using Microsoft.AspNetCore.Mvc;
namespace WebApplication3.Controllers;
[ApiController]
[Route("/api/[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
public ActionResult<IEnumerable<WeatherForecast>> Get()
{
return Ok();
}
[HttpPost]
public ActionResult<WeatherForecast> Create([FromBody] WeatherForecast weatherForecast)
{
return weatherForecast;
}
}
Up to here, it's pretty standard.
Now carefully review the following WeatherForecast type.
namespace WebApplication3;
public class WeatherForecast
{
public int Id { get; set; }
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public LocationDto Location { get; set; }
}
public class LocationDto
{
public string Name { get; set; }
public AddressDto Address { get; set; }
}
public class AddressDto
{
string AddressLine { get; set; }
// A circular reference, but not getting any errors
public LocationDto RelatedLocation { get; set; }
}
When I run this:

Note the highlighted schema.
OpenAPI specification
{
"openapi": "3.0.1",
"info": {
"title": "WebApplication3 | v1",
"version": "1.0.0"
},
"servers": [
{
"url": "https://localhost:7286/"
},
{
"url": "http://localhost:5013/"
}
],
"paths": {
"/api/WeatherForecast": {
"get": {
"tags": [
"WeatherForecast"
],
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
},
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
},
"text/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
}
}
}
}
},
"post": {
"tags": [
"WeatherForecast"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WeatherForecast2"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/WeatherForecast2"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/WeatherForecast2"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/WeatherForecast2"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/WeatherForecast2"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/WeatherForecast2"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"AddressDto": {
"type": "object",
"properties": {
"relatedLocation": {
"$ref": "#/components/schemas/LocationDto2"
}
}
},
"AddressDto2": {
"type": "object",
"properties": {
"relatedLocation": {
"$ref": "#/components/schemas/LocationDto4"
}
}
},
"LocationDto": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"address": {
"$ref": "#/components/schemas/AddressDto"
}
}
},
"LocationDto2": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"address": {
"$ref": "#/components/schemas/#/items/properties/location/properties/address"
}
}
},
"LocationDto3": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"address": {
"$ref": "#/components/schemas/AddressDto2"
}
}
},
"LocationDto4": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"address": {
"$ref": "#/components/schemas/#/properties/location/properties/address"
}
}
},
"WeatherForecast": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"date": {
"type": "string",
"format": "date"
},
"temperatureC": {
"type": "integer",
"format": "int32"
},
"location": {
"$ref": "#/components/schemas/LocationDto"
}
}
},
"WeatherForecast2": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"date": {
"type": "string",
"format": "date"
},
"temperatureC": {
"type": "integer",
"format": "int32"
},
"location": {
"$ref": "#/components/schemas/LocationDto3"
}
}
}
}
},
"tags": [
{
"name": "WeatherForecast"
}
]
}
Expected Behavior
Under components.schemas, there should be only 3 schemas
- AddressDto
- LocationDto
- WeatherForecast
Steps To Reproduce
https://github.com/jaliyaudagedara/aspnetcore-minimal-repros/tree/main/openapi-dup-schemas
Exceptions (if any)
N/A
.NET Version
9.0.200-preview.0.24575.35
Anything else?
N/A
Is there an existing issue for this?
Describe the bug
I was migrating an ASP.NET Core Web API from
.NET 8.0to.NET 9.0.As part of the migration, I was replacing
AddSwaggerGen()withAddOpenApi()and seeing this critical issue. This basically inserts duplicated schema to OpenAPI specification. Solid OpenAPI specification is critical when integrating with services like APIM and hence subject is marked with Critical.Consider the following minimal reproducible example.
csproj
Startup.cs
Program.cs
WeatherForecastController.cs
Up to here, it's pretty standard.
Now carefully review the following
WeatherForecasttype.When I run this:

Note the highlighted schema.
OpenAPI specification
{ "openapi": "3.0.1", "info": { "title": "WebApplication3 | v1", "version": "1.0.0" }, "servers": [ { "url": "https://localhost:7286/" }, { "url": "http://localhost:5013/" } ], "paths": { "/api/WeatherForecast": { "get": { "tags": [ "WeatherForecast" ], "responses": { "200": { "description": "OK", "content": { "text/plain": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/WeatherForecast" } } }, "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/WeatherForecast" } } }, "text/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/WeatherForecast" } } } } } } }, "post": { "tags": [ "WeatherForecast" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WeatherForecast2" } }, "text/json": { "schema": { "$ref": "#/components/schemas/WeatherForecast2" } }, "application/*+json": { "schema": { "$ref": "#/components/schemas/WeatherForecast2" } } }, "required": true }, "responses": { "200": { "description": "OK", "content": { "text/plain": { "schema": { "$ref": "#/components/schemas/WeatherForecast2" } }, "application/json": { "schema": { "$ref": "#/components/schemas/WeatherForecast2" } }, "text/json": { "schema": { "$ref": "#/components/schemas/WeatherForecast2" } } } } } } } }, "components": { "schemas": { "AddressDto": { "type": "object", "properties": { "relatedLocation": { "$ref": "#/components/schemas/LocationDto2" } } }, "AddressDto2": { "type": "object", "properties": { "relatedLocation": { "$ref": "#/components/schemas/LocationDto4" } } }, "LocationDto": { "type": "object", "properties": { "name": { "type": "string" }, "address": { "$ref": "#/components/schemas/AddressDto" } } }, "LocationDto2": { "type": "object", "properties": { "name": { "type": "string" }, "address": { "$ref": "#/components/schemas/#/items/properties/location/properties/address" } } }, "LocationDto3": { "type": "object", "properties": { "name": { "type": "string" }, "address": { "$ref": "#/components/schemas/AddressDto2" } } }, "LocationDto4": { "type": "object", "properties": { "name": { "type": "string" }, "address": { "$ref": "#/components/schemas/#/properties/location/properties/address" } } }, "WeatherForecast": { "type": "object", "properties": { "id": { "type": "integer", "format": "int32" }, "date": { "type": "string", "format": "date" }, "temperatureC": { "type": "integer", "format": "int32" }, "location": { "$ref": "#/components/schemas/LocationDto" } } }, "WeatherForecast2": { "type": "object", "properties": { "id": { "type": "integer", "format": "int32" }, "date": { "type": "string", "format": "date" }, "temperatureC": { "type": "integer", "format": "int32" }, "location": { "$ref": "#/components/schemas/LocationDto3" } } } } }, "tags": [ { "name": "WeatherForecast" } ] }Expected Behavior
Under
components.schemas, there should be only 3 schemasSteps To Reproduce
https://github.com/jaliyaudagedara/aspnetcore-minimal-repros/tree/main/openapi-dup-schemas
Exceptions (if any)
N/A
.NET Version
9.0.200-preview.0.24575.35
Anything else?
N/A