domaindrivendev / Swashbuckle.AspNetCore

Swagger tools for documenting API's built on ASP.NET Core
MIT License
5.17k stars 1.29k forks source link

[Bug]: Breaking change with Dictionary of Enum, when Enum has multiple values with same ordinal #2956

Open MSACATS opened 1 week ago

MSACATS commented 1 week ago

Describe the bug

I suspect that this change causes issues when an enum has multiple values with the same ordinal, and there is a Dictionary<TEnum, TValue> with that enum

I'm guessing it was introduced here: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/2825/

Expected behavior

Expect swagger to start up as expected

Actual behavior

Error at startup:

Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate Operation for action - [ControllerClass].[ApiMethod] ([Project]). See inner exception
 ---> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate schema for type - [POST Body class]. See inner exception
 ---> System.ArgumentException: An item with the same key has already been added. Key: [Enum value]
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.CreateDictionarySchema(DataContract dataContract, SchemaRepository schemaRepository)

Steps to reproduce

I suspect something like this:

public enum Example {
   Unknown = 0,
   PreferredName = 1,
   OldNameForBackwardsCompatibility = PreferredName
}

public class RequestBody {
   public Dictionary<Example, string> ValuesByType {get; set;}
}

public class ExampleController : Controller
{
   [HttpPost]
   public RequestBody Endpoint([FromBody] RequestBody body)
  {
     return Ok(body);
  }
}

Exception(s) (if any)

Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate Operation for action - [ControllerClass].[ApiMethod] ([Project]). See inner exception
 ---> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate schema for type - [POST Body class]. See inner exception
 ---> System.ArgumentException: An item with the same key has already been added. Key: [Enum value]
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.CreateDictionarySchema(DataContract dataContract, SchemaRepository schemaRepository)

Swashbuckle.AspNetCore version

No response

.NET Version

net8.0

Anything else?

In the previous version, if I examine the enum type (down in the "Schemas" section) it would contain only one of the versions, for example it would have "Unknown" and "PreferredName"

I suspect there needs to be a Distinct in the new code (#2825)

martincostello commented 1 week ago

Thanks for reporting this - would you be interested in submitting a PR to add the change to make the values distinct?