Skip to content

Commit 72c8a21

Browse files
sander1095captainsafia
authored andcommitted
Prevent ArgumentOutOfRangeException when handling nested generic types (#59201)
* Add unit test for the issue * Fix typo * Fix bug * More efficient check with a better variable name
1 parent 59230be commit 72c8a21

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

src/OpenApi/src/Extensions/JsonTypeInfoExtensions.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ internal static class JsonTypeInfoExtensions
6767
}
6868

6969
// Although arrays are enumerable types they are not encoded correctly
70-
// with JsonTypeInfoKind.Enumerable so we handle the Enumerble type
70+
// with JsonTypeInfoKind.Enumerable so we handle the Enumerable type
7171
// case here.
7272
if (jsonTypeInfo is JsonTypeInfo { Kind: JsonTypeInfoKind.Enumerable } || type.IsArray)
7373
{
@@ -104,7 +104,13 @@ internal static string GetSchemaReferenceId(this Type type, JsonSerializerOption
104104
// Generic types become a concatenation of the generic type name and the type arguments
105105
if (type.IsGenericType)
106106
{
107-
var genericTypeName = type.Name[..type.Name.LastIndexOf('`')];
107+
// We need to handle the case where the generic type is a nested type,
108+
// so we check if the name contains a backtick already.
109+
// For more information: https://github.com/dotnet/aspnetcore/issues/59092
110+
var backtickIndex = type.Name.LastIndexOf('`');
111+
var isNestedGenericType = backtickIndex == -1;
112+
113+
var genericTypeName = isNestedGenericType ? type.Name : type.Name[..backtickIndex];
108114
var genericArguments = type.GetGenericArguments();
109115
var argumentNames = string.Join("And", genericArguments.Select(arg => arg.GetSchemaReferenceId(options)));
110116
return $"{genericTypeName}Of{argumentNames}";

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Extensions/JsonTypeInfoExtensionsTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@ private class Container
1717
internal delegate void ContainedTestDelegate(int x, int y);
1818
}
1919

20+
/// <remarks>
21+
/// https://github.com/dotnet/aspnetcore/issues/59092
22+
/// </remarks>
23+
public static class Foo<T>
24+
{
25+
public static class Bar<TT>
26+
{
27+
public class Baz
28+
{
29+
public required T One { get; set; }
30+
public required TT Two { get; set; }
31+
}
32+
}
33+
}
34+
2035
/// <summary>
2136
/// This data is used to test the <see cref="TypeExtensions.GetSchemaReferenceId"/> method
2237
/// which is used to generate reference IDs for OpenAPI schemas in the OpenAPI document.
@@ -58,6 +73,7 @@ private class Container
5873
[typeof(Dictionary<string, string[]>), null],
5974
[typeof(Dictionary<string, List<string[]>>), null],
6075
[typeof(Dictionary<string, IEnumerable<string[]>>), null],
76+
[typeof(Foo<int>.Bar<string>.Baz), "BazOfintAndstring"],
6177
];
6278

6379
[Theory]

0 commit comments

Comments
 (0)