diff --git a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/DiagnosticDescriptors.cs b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/DiagnosticDescriptors.cs
index 53842cfcd9ce..298ac3eb4e90 100644
--- a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/DiagnosticDescriptors.cs
+++ b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/DiagnosticDescriptors.cs
@@ -125,4 +125,13 @@ internal static class DiagnosticDescriptors
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: GetHelpLinkUrl("RDG013"));
+
+ public static DiagnosticDescriptor InvalidAsParametersEnumerableType { get; } = new(
+ "RDG014",
+ new LocalizableResourceString(nameof(Resources.InvalidAsParametersEnumerableType_Title), Resources.ResourceManager, typeof(Resources)),
+ new LocalizableResourceString(nameof(Resources.InvalidAsParametersEnumerableType_Message), Resources.ResourceManager, typeof(Resources)),
+ "Usage",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true,
+ helpLinkUri: GetHelpLinkUrl("RDG014"));
}
diff --git a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/Resources.resx b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/Resources.resx
index ba39a95278ac..a83fbe4a38df 100644
--- a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/Resources.resx
+++ b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/Resources.resx
@@ -195,4 +195,10 @@
The [FromKeyedServices] attribute is not supported on parameters that are also annotated with IFromServiceMetadata. For more information, please see https://aka.ms/aspnet/rdg-known-issues
+
+ Invalid enumerable type
+
+
+ The enumerable type '{0}' is not supported. For more information, please see https://aka.ms/aspnet/rdg-known-issues
+
diff --git a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/StaticRouteHandlerModel/EndpointParameter.cs b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/StaticRouteHandlerModel/EndpointParameter.cs
index 8bea8558fea4..301e1d524d71 100644
--- a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/StaticRouteHandlerModel/EndpointParameter.cs
+++ b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/StaticRouteHandlerModel/EndpointParameter.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
@@ -168,7 +169,7 @@ private void ProcessEndpointParameterSource(Endpoint endpoint, ISymbol symbol, I
}
if (symbol is IPropertySymbol ||
Type is not INamedTypeSymbol namedTypeSymbol ||
- !TryGetAsParametersConstructor(endpoint, namedTypeSymbol, out var isDefaultConstructor, out var matchedProperties))
+ !TryGetAsParametersConstructor(endpoint, namedTypeSymbol, wellKnownTypes, out var isDefaultConstructor, out var matchedProperties))
{
if (symbol is IPropertySymbol)
{
@@ -454,7 +455,7 @@ private static string GetEscapedParameterName(AttributeData attribute, string pa
}
}
- private static bool TryGetAsParametersConstructor(Endpoint endpoint, INamedTypeSymbol type, out bool? isDefaultConstructor, [NotNullWhen(true)] out IEnumerable? matchedProperties)
+ private static bool TryGetAsParametersConstructor(Endpoint endpoint, INamedTypeSymbol type, WellKnownTypes wellKnownTypes, out bool? isDefaultConstructor, [NotNullWhen(true)] out IEnumerable? matchedProperties)
{
isDefaultConstructor = null;
matchedProperties = null;
@@ -466,6 +467,12 @@ private static bool TryGetAsParametersConstructor(Endpoint endpoint, INamedTypeS
return false;
}
+ if (type.Implements(wellKnownTypes.Get(WellKnownType.System_Collections_IEnumerable)))
+ {
+ endpoint.Diagnostics.Add(Diagnostic.Create(DiagnosticDescriptors.InvalidAsParametersEnumerableType, location, parameterTypeString));
+ return false;
+ }
+
var constructors = type.Constructors.Where(constructor => constructor.DeclaredAccessibility == Accessibility.Public && !constructor.IsStatic);
var numOfConstructors = constructors.Count();
// When leveraging parameterless constructors, we want to ensure we only emit for writable
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/CompileTimeCreationTests.AsParameters.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/CompileTimeCreationTests.AsParameters.cs
index ced9bb67a029..a42149b8286a 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/CompileTimeCreationTests.AsParameters.cs
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/CompileTimeCreationTests.AsParameters.cs
@@ -50,6 +50,9 @@ static string GetNoContructorsError(Type type)
static string GetInvalidConstructorError(Type type)
=> $"The public parameterized constructor must contain only parameters that match the declared public properties for type '{TypeNameHelper.GetTypeDisplayName(type, fullName: false)}'. For more information, please see https://aka.ms/aspnet/rdg-known-issues";
+ static string GetEnumerableTypeError(Type type)
+ => $"The enumerable type '{TypeNameHelper.GetTypeDisplayName(type, fullName: false)}' is not supported. For more information, please see https://aka.ms/aspnet/rdg-known-issues";
+
return new []
{
new object[] { "BadArgumentListRecord", DiagnosticDescriptors.InvalidAsParametersSingleConstructorOnly.Id, GetMultipleContructorsError(typeof(BadArgumentListRecord)) },
@@ -57,6 +60,9 @@ static string GetInvalidConstructorError(Type type)
new object[] { "BadArgumentListClassMultipleCtors", DiagnosticDescriptors.InvalidAsParametersSingleConstructorOnly.Id, GetMultipleContructorsError(typeof(BadArgumentListClassMultipleCtors)) },
new object[] { "BadAbstractArgumentListClass", DiagnosticDescriptors.InvalidAsParametersAbstractType.Id, GetAbstractTypeError(typeof(BadAbstractArgumentListClass)) },
new object[] { "BadNoPublicConstructorArgumentListClass", DiagnosticDescriptors.InvalidAsParametersNoConstructorFound.Id, GetNoContructorsError(typeof(BadNoPublicConstructorArgumentListClass)) },
+ new object[] { "List", DiagnosticDescriptors.InvalidAsParametersEnumerableType.Id, GetEnumerableTypeError(typeof(List)) },
+ new object[] { "List", DiagnosticDescriptors.InvalidAsParametersEnumerableType.Id, GetEnumerableTypeError(typeof(List)) },
+ new object[] { "Dictionary", DiagnosticDescriptors.InvalidAsParametersEnumerableType.Id, GetEnumerableTypeError(typeof(Dictionary)) }
};
}
}
diff --git a/src/Shared/RoslynUtils/WellKnownTypeData.cs b/src/Shared/RoslynUtils/WellKnownTypeData.cs
index 7a4fa428c105..494357b17a3a 100644
--- a/src/Shared/RoslynUtils/WellKnownTypeData.cs
+++ b/src/Shared/RoslynUtils/WellKnownTypeData.cs
@@ -32,6 +32,7 @@ public enum WellKnownType
Microsoft_AspNetCore_Http_IFormCollection,
Microsoft_AspNetCore_Http_IFormFileCollection,
Microsoft_AspNetCore_Http_IFormFile,
+ System_Collections_IEnumerable,
System_DateOnly,
System_DateTimeOffset,
System_IO_Stream,
@@ -146,6 +147,7 @@ public enum WellKnownType
"Microsoft.AspNetCore.Http.IFormCollection",
"Microsoft.AspNetCore.Http.IFormFileCollection",
"Microsoft.AspNetCore.Http.IFormFile",
+ "System.Collections.IEnumerable",
"System.DateOnly",
"System.DateTimeOffset",
"System.IO.Stream",