Skip to content

When using JsonPolymorphic with derived types that share a common base class and have similar property structures, the OpenAPI generator throws an exception during schema generation. #62068

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

Open
1 task done
LiHaoGit opened this issue May 22, 2025 · 0 comments
Labels
area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc feature-openapi

Comments

@LiHaoGit
Copy link

LiHaoGit commented May 22, 2025

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When using JsonPolymorphic with derived types that share a common base class and have similar property structures, the OpenAPI generator throws an exception during schema generation.

Data.cs

using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.HttpResults;

public class StepAnswer
{
    public List<Base> Answers { get; set; } = [];
}

public static class Api
{
    public static Ok<StepAnswer> Api1()
    {
        throw new NotImplementedException();
    }
    public static Ok<Base> Api2()
    {
        throw new NotImplementedException();
    }
}


[JsonPolymorphic(TypeDiscriminatorPropertyName = "_t")]
[JsonDerivedType(typeof(BaseA), typeDiscriminator: "BaseA")]
[JsonDerivedType(typeof(BaseB), typeDiscriminator: "BaseB")]
public abstract class Base
{
}


public class BaseA : Base
{
    public Dictionary<string, List<string>>? Input { get; set; }
}

public class BaseB : Base
{
    public Dictionary<string, List<string>>? Input { get; set; }
}

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var app = builder.Build();

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

app.MapGet("/api1", Api.Api1);
app.MapGet("/api2", Api.Api2);

app.Run();

Expected Behavior

OpenAPI schema should be generated without throwing an exception.

Steps To Reproduce

reproduce
dotnet run
curl http://localhost:5148/openapi/v1.json

Exceptions (if any)

System.ArgumentException: An item with the same key has already been added. Key: BaseBaseB
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Microsoft.AspNetCore.OpenApi.OpenApiSchemaReferenceTransformer.TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.ApplyTransformersAsync(OpenApiDocument document, IServiceProvider scopedServiceProvider, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiDocumentAsync(IServiceProvider scopedServiceProvider, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiDocumentAsync(IServiceProvider scopedServiceProvider, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.<>c__DisplayClass0_0.<<MapOpenApi>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Http.Generated.<GeneratedRouteBuilderExtensions_g>F56B68D2B55B5B7B373BA2E4796D897848BC0F04A969B1AF6260183E8B9E0BAF2__GeneratedRouteBuilderExtensionsCore.<>c__DisplayClass2_0.<<MapGet0>g__RequestHandler|5>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

.NET Version

9.0.201

Anything else?

Microsoft.AspNetCore.OpenApi 9.03

@github-actions github-actions bot added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label May 22, 2025
@LiHaoGit LiHaoGit changed the title ArgumentException: An item with the same key has already been added OpenApi:ArgumentException: An item with the same key has already been added May 22, 2025
@LiHaoGit LiHaoGit changed the title OpenApi:ArgumentException: An item with the same key has already been added When using JsonPolymorphic with derived types that share a common base class and have similar property structures, the OpenAPI generator throws an exception during schema generation. May 22, 2025
@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 May 22, 2025
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

2 participants