Skip to content

Commit fcf853f

Browse files
[OpenApi] Support derived FromKeyedServices
- Support attributes derived from `FromKeyedServicesAttribute`. - Add test for existing support for attributes derived from `FromServicesAttribute`. Resolves #58739.
1 parent b83721c commit fcf853f

File tree

5 files changed

+36
-3
lines changed

5 files changed

+36
-3
lines changed

src/Mvc/Mvc.ApiExplorer/src/EndpointMetadataApiDescriptionProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ private static ParameterDescriptor CreateParameterDescriptor(ParameterInfo param
274274
{
275275
return (BindingSource.FormFile, fromFormAttribute.Name ?? parameter.Name ?? string.Empty, false, parameterType);
276276
}
277-
else if (parameter.ParameterInfo.CustomAttributes.Any(a => typeof(IFromServiceMetadata).IsAssignableFrom(a.AttributeType) || typeof(FromKeyedServicesAttribute) == a.AttributeType) ||
277+
else if (parameter.ParameterInfo.CustomAttributes.Any(a => typeof(IFromServiceMetadata).IsAssignableFrom(a.AttributeType) || typeof(FromKeyedServicesAttribute).IsAssignableFrom(a.AttributeType)) ||
278278
parameterType == typeof(HttpContext) ||
279279
parameterType == typeof(HttpRequest) ||
280280
parameterType == typeof(HttpResponse) ||

src/Mvc/Mvc.ApiExplorer/test/DefaultApiDescriptionProviderTest.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using System.Globalization;
99
using System.Reflection;
1010
using System.Text;
11-
using System.Xml.Linq;
1211
using Microsoft.AspNetCore.Http;
1312
using Microsoft.AspNetCore.Mvc.Abstractions;
1413
using Microsoft.AspNetCore.Mvc.ActionConstraints;
@@ -1521,6 +1520,20 @@ public void GetApiDescription_ParameterDescription_SourceFromServices()
15211520
Assert.Empty(description.ParameterDescriptions);
15221521
}
15231522

1523+
[Fact]
1524+
public void GetApiDescription_ParameterDescription_SourceFromDerivedServices()
1525+
{
1526+
// Arrange
1527+
var action = CreateActionDescriptor(nameof(AcceptsFormatters_DerivedServices));
1528+
1529+
// Act
1530+
var descriptions = GetApiDescriptions(action);
1531+
1532+
// Assert
1533+
var description = Assert.Single(descriptions);
1534+
Assert.Empty(description.ParameterDescriptions);
1535+
}
1536+
15241537
[Fact]
15251538
public void GetApiDescription_ParameterDescription_SourceFromCustomModelBinder()
15261539
{
@@ -2509,6 +2522,10 @@ private void AcceptsFormatters_Services([FromServices] ITestService tempDataProv
25092522
{
25102523
}
25112524

2525+
private void AcceptsFormatters_DerivedServices([CustomFromServices] ITestService tempDataProvider, [CustomFromKeyedServices("foo")] ITestService keyedTempDataProvider)
2526+
{
2527+
}
2528+
25122529
private void AcceptsProductChangeDTO(ProductChangeDTO dto)
25132530
{
25142531
}
@@ -2953,4 +2970,8 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c
29532970
return base.ConvertFrom(context, culture, value);
29542971
}
29552972
}
2973+
2974+
private class CustomFromKeyedServicesAttribute(object key) : FromKeyedServicesAttribute(key);
2975+
2976+
private class CustomFromServicesAttribute : FromServicesAttribute;
29562977
}

src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,9 @@ public void DoesNotAddFromServiceParameterAsService()
795795
{
796796
Assert.Empty(GetApiDescription((IInferredServiceInterface foo) => { }).ParameterDescriptions);
797797
Assert.Empty(GetApiDescription(([FromServices] InferredServiceClass foo) => { }).ParameterDescriptions);
798+
Assert.Empty(GetApiDescription(([CustomFromServices] InferredServiceClass foo) => { }).ParameterDescriptions);
798799
Assert.Empty(GetApiDescription(([FromKeyedServices("foo")] InferredServiceClass foo) => { }).ParameterDescriptions);
800+
Assert.Empty(GetApiDescription(([CustomFromKeyedServices("foo")] InferredServiceClass foo) => { }).ParameterDescriptions);
799801
Assert.Empty(GetApiDescription((HttpContext context) => { }).ParameterDescriptions);
800802
Assert.Empty(GetApiDescription((HttpRequest request) => { }).ParameterDescriptions);
801803
Assert.Empty(GetApiDescription((HttpResponse response) => { }).ParameterDescriptions);
@@ -1918,4 +1920,8 @@ private class TestServiceProvider : IServiceProvider
19181920
}
19191921

19201922
private class GenericClass<TType> { public required TType Value { get; set; } }
1923+
1924+
private class CustomFromKeyedServicesAttribute(object key) : FromKeyedServicesAttribute(key);
1925+
1926+
private class CustomFromServicesAttribute : FromServicesAttribute;
19211927
}

src/OpenApi/src/Services/OpenApiGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ private List<IOpenApiParameter> GetOpenApiParameters(MethodInfo methodInfo, Rout
424424
{
425425
return (true, null, null);
426426
}
427-
else if (parameter.CustomAttributes.Any(a => typeof(IFromServiceMetadata).IsAssignableFrom(a.AttributeType) || typeof(FromKeyedServicesAttribute) == a.AttributeType) ||
427+
else if (parameter.CustomAttributes.Any(a => typeof(IFromServiceMetadata).IsAssignableFrom(a.AttributeType) || typeof(FromKeyedServicesAttribute).IsAssignableFrom(a.AttributeType)) ||
428428
parameter.ParameterType == typeof(HttpContext) ||
429429
parameter.ParameterType == typeof(HttpRequest) ||
430430
parameter.ParameterType == typeof(HttpResponse) ||

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiGeneratorTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,9 @@ public void DoesNotAddFromServiceParameterAsService()
413413
{
414414
Assert.Empty(GetOpenApiOperation((IInferredServiceInterface foo) => { }).Parameters);
415415
Assert.Empty(GetOpenApiOperation(([FromServices] int foo) => { }).Parameters);
416+
Assert.Empty(GetOpenApiOperation(([CustomFromServices] int foo) => { }).Parameters);
416417
Assert.Empty(GetOpenApiOperation(([FromKeyedServices("foo")] int foo) => { }).Parameters);
418+
Assert.Empty(GetOpenApiOperation(([CustomFromKeyedServices("foo")] int foo) => { }).Parameters);
417419
Assert.Empty(GetOpenApiOperation((HttpContext context) => { }).Parameters);
418420
Assert.Empty(GetOpenApiOperation((HttpRequest request) => { }).Parameters);
419421
Assert.Empty(GetOpenApiOperation((HttpResponse response) => { }).Parameters);
@@ -1144,4 +1146,8 @@ public override Endpoint Build()
11441146
throw new NotImplementedException();
11451147
}
11461148
}
1149+
1150+
private class CustomFromKeyedServicesAttribute(object key) : FromKeyedServicesAttribute(key);
1151+
1152+
private class CustomFromServicesAttribute : FromServicesAttribute;
11471153
}

0 commit comments

Comments
 (0)