Provide a method to use `type.ToString()` instead of `type.Name` to disambiguate type name collisions in Open API by including namespace in schema name
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
### Is there an existing issue for this?
- [x] 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:
```c#
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.
```c#
options.CreateSchemaReferenceId = t => t.Type.ToString();
```
The default implementation [here](https://github.com/dotnet/aspnetcore/blob/fc6e3fb2068d6bd900240137ceffdc955325f039/src/OpenApi/src/Extensions/JsonTypeInfoExtensions.cs#L53) 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()](https://github.com/dotnet/aspnetcore/blob/fc6e3fb2068d6bd900240137ceffdc955325f039/src/OpenApi/src/Services/OpenApiOptions.cs#L24C27-L24C57)
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.
https://github.com/dotnet/aspnetcore/blob/fc6e3fb2068d6bd900240137ceffdc955325f039/src/OpenApi/src/Extensions/JsonTypeInfoExtensions.cs#L119-L132
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)
```c#
//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` 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.
```C#
//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_
Contributor guide
Assessment
This issue has not been assessed yet.