-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Is there an existing issue for this?
- I have searched the existing issues
Is your feature request related to a problem? Please describe the problem.
When open api docs are generated, if you have two types: MyOrg.App1.ContactView and MyOrg.App2.ContactView, these both get put into open api docs as "ContactView", even if there are differences between them.
In Swagger it was easy to disambiguate this:
options.CustomSchemaIds(x => x.ToString());There is a method to customize these with Open API, but it requires copying the source code and modifying it to change one aspect of it. Or else you end up with a bunch of extraneous types like System.Collections.Generic.List showing in open api docs.
options.CreateSchemaReferenceId = t => t.Type.ToString();The default implementation here has a lot of logic to get rid of these types, so I need to duplicate all that logic to make one small change to the naming convention for my types.
Describe the solution you'd like
Provide a func that allows developers to use type.ToString() instead of type.Name to disambiguate type name collisions in Open API, without having to replicate all the logic in OpenApiOptions.CreateDefaultSchemaReferenceId()
This is the code that needs to change, it's using type.Name, and I want to be able to choose to do type.ToString() instead.
aspnetcore/src/OpenApi/src/Extensions/JsonTypeInfoExtensions.cs
Lines 119 to 132 in fc6e3fb
| if (type.IsGenericType) | |
| { | |
| // We need to handle the case where the generic type is a nested type, | |
| // so we check if the name contains a backtick already. | |
| // For more information: https://github.com/dotnet/aspnetcore/issues/59092 | |
| var backtickIndex = type.Name.LastIndexOf('`'); | |
| var isNestedGenericType = backtickIndex == -1; | |
| var genericTypeName = isNestedGenericType ? type.Name : type.Name[..backtickIndex]; | |
| var genericArguments = type.GetGenericArguments(); | |
| var argumentNames = string.Join("And", genericArguments.Select(arg => arg.GetSchemaReferenceId(options))); | |
| return $"{genericTypeName}Of{argumentNames}"; | |
| } | |
| return type.Name; |
Example of working code that solves the problem, with small refactors to use a local variable baseTypeName (typeName is used in another scope in this method)
//var baseTypeName = type.Name; //existing functionality to replace
var baseTypeName = type.ToString(); //this solves the namespace problem
if (type.IsGenericType)
{
// We need to handle the case where the generic type is a nested type,
// so we check if the name contains a backtick already.
// For more information: https://github.com/dotnet/aspnetcore/issues/59092
var backtickIndex = baseTypeName.LastIndexOf('`');
var isNestedGenericType = backtickIndex == -1;
var genericTypeName = isNestedGenericType ? baseTypeName : baseTypeName[..backtickIndex];
var genericArguments = type.GetGenericArguments();
var argumentNames = string.Join("And", genericArguments.Select(arg => arg.GetSchemaReferenceId(options)));
return $"{genericTypeName}Of{argumentNames}";
}
return baseTypeName;Requested Solution
Allow that top line of code to be provided as a Func<Type, string> in open api options and used in these lines. This allows me to have a one line fix to this, rather than have to copy all of the json extension methods used to generate these names with this one change.
//option 1- new property in the OpenApiOptions
options.CreateSchemaReferenceIdSelector = t => t.ToString();
//option 2- new overload for the "DefaultSchema" method that allows specifying how to get name from System.Type
options.CreateSchemaReferenceId = OpenApiOptions.CreateDefaultSchemaReferenceId(t => t.ToString());Additional context
No response