dotnet / dotnet/aspnetcore

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

Open
#64,947 2 comments 1 reaction 0 assignees View on GitHub
area-minimal feature-openapi
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.