Skip to content

Commit 68d5b6f

Browse files
committed
Respect IModelNameProvider when matching OpenAPI parameters
1 parent 2831dc0 commit 68d5b6f

10 files changed

+429
-19
lines changed

src/OpenApi/gen/XmlCommentGenerator.Emitter.cs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ namespace Microsoft.AspNetCore.OpenApi.Generated
5757
using System.Threading.Tasks;
5858
using Microsoft.AspNetCore.OpenApi;
5959
using Microsoft.AspNetCore.Mvc.Controllers;
60+
using Microsoft.AspNetCore.Mvc.ModelBinding;
6061
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
6162
using Microsoft.Extensions.DependencyInjection;
6263
using Microsoft.OpenApi;
@@ -389,7 +390,12 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
389390
foreach (var parameterComment in methodComment.Parameters)
390391
{
391392
var parameterInfo = methodInfo.GetParameters().SingleOrDefault(info => info.Name == parameterComment.Name);
392-
var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name);
393+
if (parameterInfo is null)
394+
{
395+
continue;
396+
}
397+
398+
var operationParameter = GetOperationParameter(operation, parameterInfo);
393399
if (operationParameter is not null)
394400
{
395401
var targetOperationParameter = UnwrapOpenApiParameter(operationParameter);
@@ -499,6 +505,41 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
499505
return Task.CompletedTask;
500506
}
501507
508+
private static IOpenApiParameter? GetOperationParameter(OpenApiOperation operation, ParameterInfo parameterInfo)
509+
{
510+
if (operation.Parameters is null)
511+
{
512+
return null;
513+
}
514+
515+
var names = parameterInfo.GetCustomAttributes(inherit: false)
516+
.OfType<IModelNameProvider>()
517+
.Select(x => x.Name)
518+
.Append(parameterInfo.Name)
519+
.ToHashSet();
520+
521+
foreach (var operationParameter in operation.Parameters)
522+
{
523+
// Optimize for the most common case
524+
if (operationParameter.Name == parameterInfo.Name)
525+
{
526+
return operationParameter;
527+
}
528+
529+
// Check all attributes implementing IModelNameProvider for custom names
530+
foreach (var modelNameProvider in parameterInfo.GetCustomAttributes(inherit: false).OfType<IModelNameProvider>())
531+
{
532+
var modelName = modelNameProvider.Name;
533+
if (!string.IsNullOrEmpty(modelName) && operationParameter.Name == modelName)
534+
{
535+
return operationParameter;
536+
}
537+
}
538+
}
539+
540+
return null;
541+
}
542+
502543
private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter)
503544
{
504545
if (sourceParameter is OpenApiParameterReference parameterReference)

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//HintName: OpenApiXmlCommentSupport.generated.cs
1+
//HintName: OpenApiXmlCommentSupport.generated.cs
22
//------------------------------------------------------------------------------
33
// <auto-generated>
44
// This code was generated by a tool.
@@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.OpenApi.Generated
3939
using System.Threading.Tasks;
4040
using Microsoft.AspNetCore.OpenApi;
4141
using Microsoft.AspNetCore.Mvc.Controllers;
42+
using Microsoft.AspNetCore.Mvc.ModelBinding;
4243
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
4344
using Microsoft.Extensions.DependencyInjection;
4445
using Microsoft.OpenApi;
@@ -371,7 +372,12 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
371372
foreach (var parameterComment in methodComment.Parameters)
372373
{
373374
var parameterInfo = methodInfo.GetParameters().SingleOrDefault(info => info.Name == parameterComment.Name);
374-
var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name);
375+
if (parameterInfo is null)
376+
{
377+
continue;
378+
}
379+
380+
var operationParameter = GetOperationParameter(operation, parameterInfo);
375381
if (operationParameter is not null)
376382
{
377383
var targetOperationParameter = UnwrapOpenApiParameter(operationParameter);
@@ -481,6 +487,41 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
481487
return Task.CompletedTask;
482488
}
483489

490+
private static IOpenApiParameter? GetOperationParameter(OpenApiOperation operation, ParameterInfo parameterInfo)
491+
{
492+
if (operation.Parameters is null)
493+
{
494+
return null;
495+
}
496+
497+
var names = parameterInfo.GetCustomAttributes(inherit: false)
498+
.OfType<IModelNameProvider>()
499+
.Select(x => x.Name)
500+
.Append(parameterInfo.Name)
501+
.ToHashSet();
502+
503+
foreach (var operationParameter in operation.Parameters)
504+
{
505+
// Optimize for the most common case
506+
if (operationParameter.Name == parameterInfo.Name)
507+
{
508+
return operationParameter;
509+
}
510+
511+
// Check all attributes implementing IModelNameProvider for custom names
512+
foreach (var modelNameProvider in parameterInfo.GetCustomAttributes(inherit: false).OfType<IModelNameProvider>())
513+
{
514+
var modelName = modelNameProvider.Name;
515+
if (!string.IsNullOrEmpty(modelName) && operationParameter.Name == modelName)
516+
{
517+
return operationParameter;
518+
}
519+
}
520+
}
521+
522+
return null;
523+
}
524+
484525
private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter)
485526
{
486527
if (sourceParameter is OpenApiParameterReference parameterReference)

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//HintName: OpenApiXmlCommentSupport.generated.cs
1+
//HintName: OpenApiXmlCommentSupport.generated.cs
22
//------------------------------------------------------------------------------
33
// <auto-generated>
44
// This code was generated by a tool.
@@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.OpenApi.Generated
3939
using System.Threading.Tasks;
4040
using Microsoft.AspNetCore.OpenApi;
4141
using Microsoft.AspNetCore.Mvc.Controllers;
42+
using Microsoft.AspNetCore.Mvc.ModelBinding;
4243
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
4344
using Microsoft.Extensions.DependencyInjection;
4445
using Microsoft.OpenApi;
@@ -400,7 +401,12 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
400401
foreach (var parameterComment in methodComment.Parameters)
401402
{
402403
var parameterInfo = methodInfo.GetParameters().SingleOrDefault(info => info.Name == parameterComment.Name);
403-
var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name);
404+
if (parameterInfo is null)
405+
{
406+
continue;
407+
}
408+
409+
var operationParameter = GetOperationParameter(operation, parameterInfo);
404410
if (operationParameter is not null)
405411
{
406412
var targetOperationParameter = UnwrapOpenApiParameter(operationParameter);
@@ -510,6 +516,41 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
510516
return Task.CompletedTask;
511517
}
512518

519+
private static IOpenApiParameter? GetOperationParameter(OpenApiOperation operation, ParameterInfo parameterInfo)
520+
{
521+
if (operation.Parameters is null)
522+
{
523+
return null;
524+
}
525+
526+
var names = parameterInfo.GetCustomAttributes(inherit: false)
527+
.OfType<IModelNameProvider>()
528+
.Select(x => x.Name)
529+
.Append(parameterInfo.Name)
530+
.ToHashSet();
531+
532+
foreach (var operationParameter in operation.Parameters)
533+
{
534+
// Optimize for the most common case
535+
if (operationParameter.Name == parameterInfo.Name)
536+
{
537+
return operationParameter;
538+
}
539+
540+
// Check all attributes implementing IModelNameProvider for custom names
541+
foreach (var modelNameProvider in parameterInfo.GetCustomAttributes(inherit: false).OfType<IModelNameProvider>())
542+
{
543+
var modelName = modelNameProvider.Name;
544+
if (!string.IsNullOrEmpty(modelName) && operationParameter.Name == modelName)
545+
{
546+
return operationParameter;
547+
}
548+
}
549+
}
550+
551+
return null;
552+
}
553+
513554
private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter)
514555
{
515556
if (sourceParameter is OpenApiParameterReference parameterReference)

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//HintName: OpenApiXmlCommentSupport.generated.cs
1+
//HintName: OpenApiXmlCommentSupport.generated.cs
22
//------------------------------------------------------------------------------
33
// <auto-generated>
44
// This code was generated by a tool.
@@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.OpenApi.Generated
3939
using System.Threading.Tasks;
4040
using Microsoft.AspNetCore.OpenApi;
4141
using Microsoft.AspNetCore.Mvc.Controllers;
42+
using Microsoft.AspNetCore.Mvc.ModelBinding;
4243
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
4344
using Microsoft.Extensions.DependencyInjection;
4445
using Microsoft.OpenApi;
@@ -498,7 +499,12 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
498499
foreach (var parameterComment in methodComment.Parameters)
499500
{
500501
var parameterInfo = methodInfo.GetParameters().SingleOrDefault(info => info.Name == parameterComment.Name);
501-
var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name);
502+
if (parameterInfo is null)
503+
{
504+
continue;
505+
}
506+
507+
var operationParameter = GetOperationParameter(operation, parameterInfo);
502508
if (operationParameter is not null)
503509
{
504510
var targetOperationParameter = UnwrapOpenApiParameter(operationParameter);
@@ -608,6 +614,41 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
608614
return Task.CompletedTask;
609615
}
610616

617+
private static IOpenApiParameter? GetOperationParameter(OpenApiOperation operation, ParameterInfo parameterInfo)
618+
{
619+
if (operation.Parameters is null)
620+
{
621+
return null;
622+
}
623+
624+
var names = parameterInfo.GetCustomAttributes(inherit: false)
625+
.OfType<IModelNameProvider>()
626+
.Select(x => x.Name)
627+
.Append(parameterInfo.Name)
628+
.ToHashSet();
629+
630+
foreach (var operationParameter in operation.Parameters)
631+
{
632+
// Optimize for the most common case
633+
if (operationParameter.Name == parameterInfo.Name)
634+
{
635+
return operationParameter;
636+
}
637+
638+
// Check all attributes implementing IModelNameProvider for custom names
639+
foreach (var modelNameProvider in parameterInfo.GetCustomAttributes(inherit: false).OfType<IModelNameProvider>())
640+
{
641+
var modelName = modelNameProvider.Name;
642+
if (!string.IsNullOrEmpty(modelName) && operationParameter.Name == modelName)
643+
{
644+
return operationParameter;
645+
}
646+
}
647+
}
648+
649+
return null;
650+
}
651+
611652
private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter)
612653
{
613654
if (sourceParameter is OpenApiParameterReference parameterReference)

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsRouteParametersFromControllers#OpenApiXmlCommentSupport.generated.verified.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//HintName: OpenApiXmlCommentSupport.generated.cs
1+
//HintName: OpenApiXmlCommentSupport.generated.cs
22
//------------------------------------------------------------------------------
33
// <auto-generated>
44
// This code was generated by a tool.
@@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.OpenApi.Generated
3939
using System.Threading.Tasks;
4040
using Microsoft.AspNetCore.OpenApi;
4141
using Microsoft.AspNetCore.Mvc.Controllers;
42+
using Microsoft.AspNetCore.Mvc.ModelBinding;
4243
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
4344
using Microsoft.Extensions.DependencyInjection;
4445
using Microsoft.OpenApi;
@@ -372,7 +373,12 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
372373
foreach (var parameterComment in methodComment.Parameters)
373374
{
374375
var parameterInfo = methodInfo.GetParameters().SingleOrDefault(info => info.Name == parameterComment.Name);
375-
var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name);
376+
if (parameterInfo is null)
377+
{
378+
continue;
379+
}
380+
381+
var operationParameter = GetOperationParameter(operation, parameterInfo);
376382
if (operationParameter is not null)
377383
{
378384
var targetOperationParameter = UnwrapOpenApiParameter(operationParameter);
@@ -482,6 +488,41 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
482488
return Task.CompletedTask;
483489
}
484490

491+
private static IOpenApiParameter? GetOperationParameter(OpenApiOperation operation, ParameterInfo parameterInfo)
492+
{
493+
if (operation.Parameters is null)
494+
{
495+
return null;
496+
}
497+
498+
var names = parameterInfo.GetCustomAttributes(inherit: false)
499+
.OfType<IModelNameProvider>()
500+
.Select(x => x.Name)
501+
.Append(parameterInfo.Name)
502+
.ToHashSet();
503+
504+
foreach (var operationParameter in operation.Parameters)
505+
{
506+
// Optimize for the most common case
507+
if (operationParameter.Name == parameterInfo.Name)
508+
{
509+
return operationParameter;
510+
}
511+
512+
// Check all attributes implementing IModelNameProvider for custom names
513+
foreach (var modelNameProvider in parameterInfo.GetCustomAttributes(inherit: false).OfType<IModelNameProvider>())
514+
{
515+
var modelName = modelNameProvider.Name;
516+
if (!string.IsNullOrEmpty(modelName) && operationParameter.Name == modelName)
517+
{
518+
return operationParameter;
519+
}
520+
}
521+
}
522+
523+
return null;
524+
}
525+
485526
private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter)
486527
{
487528
if (sourceParameter is OpenApiParameterReference parameterReference)

0 commit comments

Comments
 (0)