diff --git a/.azure/pipelines/ci-public.yml b/.azure/pipelines/ci-public.yml
index 124806b65edd..2f506299bbb5 100644
--- a/.azure/pipelines/ci-public.yml
+++ b/.azure/pipelines/ci-public.yml
@@ -556,9 +556,6 @@ stages:
beforeBuild:
- powershell: "& ./src/Servers/IIS/tools/UpdateIISExpressCertificate.ps1; & ./src/Servers/IIS/tools/update_schema.ps1"
displayName: Setup IISExpress test certificates and schema
- afterBuild:
- - powershell: ./eng/scripts/CompareMinifiedJsFiles.ps1
- displayName: Check for changes in generated minified .js files
artifacts:
- name: Windows_Test_Logs_Attempt_$(System.JobAttempt)
path: artifacts/log/
diff --git a/AspNetCore.sln b/AspNetCore.sln
index a9c2857c4182..aba0325d0351 100644
--- a/AspNetCore.sln
+++ b/AspNetCore.sln
@@ -1674,8 +1674,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResultsOfTGenerator", "src\
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OpenApi", "OpenApi", "{2299CCD8-8F9C-4F2B-A633-9BF4DA81022B}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.OpenApi.Tests", "src\OpenApi\test\Microsoft.AspNetCore.OpenApi.Tests.csproj", "{3AEFB466-6310-4F3F-923F-9154224E3629}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.OpenApi", "src\OpenApi\src\Microsoft.AspNetCore.OpenApi.csproj", "{EFC8EA45-572D-4D8D-A597-9045A2D8EC40}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.RateLimiting", "src\Middleware\RateLimiting\src\Microsoft.AspNetCore.RateLimiting.csproj", "{8EE73488-2B92-42BD-96C9-0DD65405C828}"
@@ -1818,6 +1816,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GetDocumentSample", "src\To
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorUnitedApp.Client", "src\Components\Samples\BlazorUnitedApp.Client\BlazorUnitedApp.Client.csproj", "{757CBDE0-5D0A-4FD8-99F3-6C20BDDD4E63}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B32FF7A7-9CB3-4DCD-AE97-3B2594DB9DAC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.OpenApi.Tests", "src\OpenApi\test\Microsoft.AspNetCore.OpenApi.Tests\Microsoft.AspNetCore.OpenApi.Tests.csproj", "{B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -10147,22 +10149,6 @@ Global
{9716D0D0-2251-44DD-8596-67D253EEF41C}.Release|x64.Build.0 = Release|Any CPU
{9716D0D0-2251-44DD-8596-67D253EEF41C}.Release|x86.ActiveCfg = Release|Any CPU
{9716D0D0-2251-44DD-8596-67D253EEF41C}.Release|x86.Build.0 = Release|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Debug|arm64.ActiveCfg = Debug|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Debug|arm64.Build.0 = Debug|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Debug|x64.ActiveCfg = Debug|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Debug|x64.Build.0 = Debug|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Debug|x86.ActiveCfg = Debug|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Debug|x86.Build.0 = Debug|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Release|Any CPU.Build.0 = Release|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Release|arm64.ActiveCfg = Release|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Release|arm64.Build.0 = Release|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Release|x64.ActiveCfg = Release|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Release|x64.Build.0 = Release|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Release|x86.ActiveCfg = Release|Any CPU
- {3AEFB466-6310-4F3F-923F-9154224E3629}.Release|x86.Build.0 = Release|Any CPU
{EFC8EA45-572D-4D8D-A597-9045A2D8EC40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EFC8EA45-572D-4D8D-A597-9045A2D8EC40}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EFC8EA45-572D-4D8D-A597-9045A2D8EC40}.Debug|arm64.ActiveCfg = Debug|Any CPU
@@ -10995,6 +10981,22 @@ Global
{757CBDE0-5D0A-4FD8-99F3-6C20BDDD4E63}.Release|x64.Build.0 = Release|Any CPU
{757CBDE0-5D0A-4FD8-99F3-6C20BDDD4E63}.Release|x86.ActiveCfg = Release|Any CPU
{757CBDE0-5D0A-4FD8-99F3-6C20BDDD4E63}.Release|x86.Build.0 = Release|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Debug|arm64.ActiveCfg = Debug|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Debug|arm64.Build.0 = Debug|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Debug|x64.Build.0 = Debug|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Debug|x86.Build.0 = Debug|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Release|arm64.ActiveCfg = Release|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Release|arm64.Build.0 = Release|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Release|x64.ActiveCfg = Release|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Release|x64.Build.0 = Release|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Release|x86.ActiveCfg = Release|Any CPU
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -11824,7 +11826,6 @@ Global
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7} = {AA5ABFBC-177C-421E-B743-005E0FD1248B}
{9716D0D0-2251-44DD-8596-67D253EEF41C} = {323C3EB6-1D15-4B3D-918D-699D7F64DED9}
{2299CCD8-8F9C-4F2B-A633-9BF4DA81022B} = {017429CC-C5FB-48B4-9C46-034E29EE2F06}
- {3AEFB466-6310-4F3F-923F-9154224E3629} = {2299CCD8-8F9C-4F2B-A633-9BF4DA81022B}
{EFC8EA45-572D-4D8D-A597-9045A2D8EC40} = {2299CCD8-8F9C-4F2B-A633-9BF4DA81022B}
{8EE73488-2B92-42BD-96C9-0DD65405C828} = {1D865E78-7A66-4CA9-92EE-2B350E45281F}
{41FF4F96-98D2-4482-A2A7-4B179E80D285} = {1D865E78-7A66-4CA9-92EE-2B350E45281F}
@@ -11893,6 +11894,8 @@ Global
{6A19D94D-2BC6-4198-BE2E-342688FDBA4B} = {A1B75FC7-A777-4412-A635-D0C9ED8FE7A0}
{D8F7091E-A2D1-4E81-BA7C-97EAE392D683} = {A1B75FC7-A777-4412-A635-D0C9ED8FE7A0}
{757CBDE0-5D0A-4FD8-99F3-6C20BDDD4E63} = {5FE1FBC1-8CE3-4355-9866-44FE1307C5F1}
+ {B32FF7A7-9CB3-4DCD-AE97-3B2594DB9DAC} = {2299CCD8-8F9C-4F2B-A633-9BF4DA81022B}
+ {B9BBC1A8-7F58-4F43-94C3-5F3CB125CEF7} = {B32FF7A7-9CB3-4DCD-AE97-3B2594DB9DAC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
diff --git a/eng/RequiresDelayedBuildProjects.props b/eng/RequiresDelayedBuildProjects.props
index 3c1626ba53bf..1a771e0d5e74 100644
--- a/eng/RequiresDelayedBuildProjects.props
+++ b/eng/RequiresDelayedBuildProjects.props
@@ -20,6 +20,7 @@
+
diff --git a/eng/TrimmableProjects.props b/eng/TrimmableProjects.props
index 6ba207ac1852..199d65af1b49 100644
--- a/eng/TrimmableProjects.props
+++ b/eng/TrimmableProjects.props
@@ -85,6 +85,9 @@
+
+
+
diff --git a/eng/testing/linker/SupportFiles/Directory.Build.targets b/eng/testing/linker/SupportFiles/Directory.Build.targets
index 8d7674b8923a..0b4c65ac90c2 100644
--- a/eng/testing/linker/SupportFiles/Directory.Build.targets
+++ b/eng/testing/linker/SupportFiles/Directory.Build.targets
@@ -75,6 +75,8 @@
+
+
diff --git a/eng/testing/linker/project.csproj.template b/eng/testing/linker/project.csproj.template
index 8efde8d4b648..1affe37e05ef 100644
--- a/eng/testing/linker/project.csproj.template
+++ b/eng/testing/linker/project.csproj.template
@@ -11,6 +11,11 @@
99.9
<_ExtraTrimmerArgs>{ExtraTrimmerArgs} $(_ExtraTrimmerArgs)
+ $(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated
+
+ false
+
+ $(NoWarn);IL2104
{AdditionalProperties}
@@ -21,5 +26,20 @@
{AdditionalProjectReferences}
-
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
diff --git a/src/Http/Http.Abstractions/src/Metadata/IParameterBindingMetadata.cs b/src/Http/Http.Abstractions/src/Metadata/IParameterBindingMetadata.cs
new file mode 100644
index 000000000000..1ca1c6448ec2
--- /dev/null
+++ b/src/Http/Http.Abstractions/src/Metadata/IParameterBindingMetadata.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection;
+
+namespace Microsoft.AspNetCore.Http.Metadata;
+
+///
+/// Exposes metadata about the parameter binding details associated with a parameter
+/// in the endpoints handler.
+///
+///
+/// This metadata is injected by the RequestDelegateFactory and RequestDelegateGenerator components
+/// and is primarily intended for consumption by the EndpointMetadataApiDescriptionProvider in
+/// ApiExplorer.
+///
+public interface IParameterBindingMetadata
+{
+ ///
+ /// The name of the parameter.
+ ///
+ string Name { get; }
+
+ ///
+ /// is the parameter is associated with a type that implements or exposes a TryParse method.
+ ///
+ bool HasTryParse { get; }
+
+ ///
+ /// if the parameter is associated with a type that implements a BindAsync method.
+ ///
+ bool HasBindAsync { get; }
+
+ ///
+ /// The associated with the parameter.
+ ///
+ ParameterInfo ParameterInfo { get; }
+
+ ///
+ /// if the parameter is optional.
+ ///
+ bool IsOptional { get; }
+}
diff --git a/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt b/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt
index f31484140679..0d2aab25f97d 100644
--- a/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt
+++ b/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt
@@ -5,3 +5,9 @@ Microsoft.AspNetCore.Http.HostString.HostString(string? value) -> void
Microsoft.AspNetCore.Http.HostString.Value.get -> string?
Microsoft.AspNetCore.Http.HttpValidationProblemDetails.HttpValidationProblemDetails(System.Collections.Generic.IEnumerable>! errors) -> void
Microsoft.AspNetCore.Http.Metadata.IDisableHttpMetricsMetadata
+Microsoft.AspNetCore.Http.Metadata.IParameterBindingMetadata
+Microsoft.AspNetCore.Http.Metadata.IParameterBindingMetadata.HasBindAsync.get -> bool
+Microsoft.AspNetCore.Http.Metadata.IParameterBindingMetadata.HasTryParse.get -> bool
+Microsoft.AspNetCore.Http.Metadata.IParameterBindingMetadata.IsOptional.get -> bool
+Microsoft.AspNetCore.Http.Metadata.IParameterBindingMetadata.Name.get -> string!
+Microsoft.AspNetCore.Http.Metadata.IParameterBindingMetadata.ParameterInfo.get -> System.Reflection.ParameterInfo!
diff --git a/src/Http/Http.Extensions/gen/RequestDelegateGenerator.cs b/src/Http/Http.Extensions/gen/RequestDelegateGenerator.cs
index ac8bbdd3a175..f4e2ad0e8e33 100644
--- a/src/Http/Http.Extensions/gen/RequestDelegateGenerator.cs
+++ b/src/Http/Http.Extensions/gen/RequestDelegateGenerator.cs
@@ -5,14 +5,12 @@
using System.Globalization;
using System.IO;
using System.Linq;
-using System.Text;
using Microsoft.AspNetCore.Analyzers.Infrastructure;
using Microsoft.AspNetCore.App.Analyzers.Infrastructure;
using Microsoft.AspNetCore.Http.RequestDelegateGenerator.StaticRouteHandlerModel;
using Microsoft.AspNetCore.Http.RequestDelegateGenerator.StaticRouteHandlerModel.Emitters;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Operations;
namespace Microsoft.AspNetCore.Http.RequestDelegateGenerator;
@@ -243,6 +241,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var hasJsonBody = endpoints.Any(endpoint => endpoint.EmitterContext.HasJsonBody || endpoint.EmitterContext.HasJsonBodyOrService || endpoint.EmitterContext.HasJsonBodyOrQuery);
var hasResponseMetadata = endpoints.Any(endpoint => endpoint.EmitterContext.HasResponseMetadata);
var requiresPropertyAsParameterInfo = endpoints.Any(endpoint => endpoint.EmitterContext.RequiresPropertyAsParameterInfo);
+ var requiresParameterBindingMetadataClass = endpoints.Any(endpoint => endpoint.EmitterContext.RequiresParameterBindingMetadataClass);
using var stringWriter = new StringWriter(CultureInfo.InvariantCulture);
using var codeWriter = new CodeWriter(stringWriter, baseIndent: 0);
@@ -262,6 +261,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
codeWriter.WriteLine(RequestDelegateGeneratorSources.PropertyAsParameterInfoClass);
}
+ if (requiresParameterBindingMetadataClass)
+ {
+ codeWriter.WriteLine(RequestDelegateGeneratorSources.ParameterBindingMetadataClass);
+ }
+
return stringWriter.ToString();
});
diff --git a/src/Http/Http.Extensions/gen/RequestDelegateGeneratorSources.cs b/src/Http/Http.Extensions/gen/RequestDelegateGeneratorSources.cs
index b3e629a5cdee..d7c7a480446c 100644
--- a/src/Http/Http.Extensions/gen/RequestDelegateGeneratorSources.cs
+++ b/src/Http/Http.Extensions/gen/RequestDelegateGeneratorSources.cs
@@ -449,6 +449,36 @@ public override bool IsDefined(Type attributeType, bool inherit)
}
""";
+ public static string ParameterBindingMetadataClass = $$"""
+ {{GeneratedCodeAttribute}}
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
+""";
+
public static string AntiforgeryMetadataType = """
file sealed class AntiforgeryMetadata : IAntiforgeryMetadata
{
diff --git a/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/Emitters/EmitterContext.cs b/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/Emitters/EmitterContext.cs
index 43c0906df211..ce950dc54bfe 100644
--- a/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/Emitters/EmitterContext.cs
+++ b/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/Emitters/EmitterContext.cs
@@ -12,6 +12,7 @@ internal sealed class EmitterContext
public bool HasBindAsync { get; set; }
public bool HasParsable { get; set; }
public bool RequiresPropertyAsParameterInfo { get; set; }
+ public bool RequiresParameterBindingMetadataClass { get; set; }
public bool RequiresLoggingHelper { get; set; }
public bool HasEndpointMetadataProvider { get; set; }
public bool HasEndpointParameterMetadataProvider { get; set; }
diff --git a/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/EndpointParameter.cs b/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/EndpointParameter.cs
index 4854c72937d2..1eca598bc655 100644
--- a/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/EndpointParameter.cs
+++ b/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/EndpointParameter.cs
@@ -47,7 +47,7 @@ private EndpointParameter(Endpoint endpoint, IPropertySymbol property, IParamete
PropertyAsParameterInfoConstruction = parameter is not null
? $"new PropertyAsParameterInfo({(IsOptional ? "true" : "false")}, {propertyInfo}, {parameter.GetParameterInfoFromConstructorCode()})"
: $"new PropertyAsParameterInfo({(IsOptional ? "true" : "false")}, {propertyInfo})";
- endpoint.EmitterContext.RequiresPropertyAsParameterInfo = IsProperty && IsEndpointParameterMetadataProvider;
+ endpoint.EmitterContext.RequiresPropertyAsParameterInfo = IsProperty;
ProcessEndpointParameterSource(endpoint, property, attributeBuilder.ToImmutable(), wellKnownTypes);
}
diff --git a/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/StaticRouteHandlerModel.Emitter.cs b/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/StaticRouteHandlerModel.Emitter.cs
index 7a206872d797..bd22c645025b 100644
--- a/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/StaticRouteHandlerModel.Emitter.cs
+++ b/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/StaticRouteHandlerModel.Emitter.cs
@@ -8,6 +8,7 @@
using Microsoft.AspNetCore.Analyzers.RouteEmbeddedLanguage.Infrastructure;
using Microsoft.AspNetCore.Http.RequestDelegateGenerator.StaticRouteHandlerModel.Emitters;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
namespace Microsoft.AspNetCore.Http.RequestDelegateGenerator.StaticRouteHandlerModel;
@@ -199,21 +200,26 @@ public static void EmitFilteredRequestHandler(this Endpoint endpoint, CodeWriter
private static void EmitBuiltinResponseTypeMetadata(this Endpoint endpoint, CodeWriter codeWriter)
{
- if (endpoint.Response is not { } response || response.ResponseType is not { } responseType)
+ if (endpoint.Response is not { } response)
{
return;
}
- if (response.HasNoResponse || response.IsIResult)
+ if (!endpoint.Response.IsAwaitable && (response.HasNoResponse || response.IsIResult))
{
return;
}
- if (responseType.SpecialType == SpecialType.System_String)
+ endpoint.EmitterContext.HasResponseMetadata = true;
+ if (response.ResponseType?.SpecialType == SpecialType.System_String)
{
- codeWriter.WriteLine("options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));");
+ codeWriter.WriteLine($"options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));");
}
- else
+ else if (response.IsAwaitable && response.ResponseType == null)
+ {
+ codeWriter.WriteLine($"options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(void), contentTypes: GeneratedMetadataConstants.PlaintextContentType));");
+ }
+ else if (response.ResponseType is { } responseType)
{
codeWriter.WriteLine($$"""options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof({{responseType.ToDisplayString(EmitterConstants.DisplayFormatWithoutNullability)}}), contentTypes: GeneratedMetadataConstants.JsonContentType));""");
}
@@ -358,9 +364,39 @@ public static void EmitAcceptsMetadata(this Endpoint endpoint, CodeWriter codeWr
}
}
+ public static void EmitParameterBindingMetadata(this Endpoint endpoint, CodeWriter codeWriter)
+ {
+ foreach (var parameter in endpoint.Parameters)
+ {
+ endpoint.EmitterContext.RequiresParameterBindingMetadataClass = true;
+ if (parameter.EndpointParameters is not null)
+ {
+ foreach (var propertyAsParameter in parameter.EndpointParameters)
+ {
+ EmitParameterBindingMetadataForParameter(propertyAsParameter, codeWriter);
+ }
+ }
+ else
+ {
+ EmitParameterBindingMetadataForParameter(parameter, codeWriter);
+ }
+ }
+
+ static void EmitParameterBindingMetadataForParameter(EndpointParameter parameter, CodeWriter codeWriter)
+ {
+ var parameterName = SymbolDisplay.FormatLiteral(parameter.SymbolName, true);
+ var parameterInfo = parameter.IsProperty ? parameter.PropertyAsParameterInfoConstruction : $"methodInfo.GetParameters()[{parameter.Ordinal}]";
+ var hasTryParse = parameter.IsParsable ? "true" : "false";
+ var hasBindAsync = parameter.Source == EndpointParameterSource.BindAsync ? "true" : "false";
+ var isOptional = parameter.IsOptional ? "true" : "false";
+ codeWriter.WriteLine($"options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata({parameterName}, {parameterInfo}, hasTryParse: {hasTryParse}, hasBindAsync: {hasBindAsync}, isOptional: {isOptional}));");
+ }
+ }
+
public static void EmitEndpointMetadataPopulation(this Endpoint endpoint, CodeWriter codeWriter)
{
endpoint.EmitAcceptsMetadata(codeWriter);
+ endpoint.EmitParameterBindingMetadata(codeWriter);
endpoint.EmitBuiltinResponseTypeMetadata(codeWriter);
endpoint.EmitCallsToMetadataProvidersForParameters(codeWriter);
endpoint.EmitCallToMetadataProviderForResponse(codeWriter);
diff --git a/src/Http/Http.Extensions/src/ParameterBindingMetadata.cs b/src/Http/Http.Extensions/src/ParameterBindingMetadata.cs
new file mode 100644
index 000000000000..6bc15b868aef
--- /dev/null
+++ b/src/Http/Http.Extensions/src/ParameterBindingMetadata.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection;
+
+namespace Microsoft.AspNetCore.Http.Metadata;
+
+internal sealed class ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false) : IParameterBindingMetadata
+{
+ public string Name => name;
+
+ public bool HasTryParse => hasTryParse;
+
+ public bool HasBindAsync => hasBindAsync;
+
+ public ParameterInfo ParameterInfo => parameterInfo;
+
+ public bool IsOptional => isOptional;
+}
diff --git a/src/Http/Http.Extensions/src/RequestDelegateFactory.cs b/src/Http/Http.Extensions/src/RequestDelegateFactory.cs
index c2e2b1ea0d28..f30dbe63ca10 100644
--- a/src/Http/Http.Extensions/src/RequestDelegateFactory.cs
+++ b/src/Http/Http.Extensions/src/RequestDelegateFactory.cs
@@ -38,8 +38,6 @@ namespace Microsoft.AspNetCore.Http;
[RequiresDynamicCode("RequestDelegateFactory performs object creation, serialization and deserialization on the delegates and its parameters. This cannot be statically analyzed.")]
public static partial class RequestDelegateFactory
{
- private static readonly ParameterBindingMethodCache ParameterBindingMethodCache = new();
-
private static readonly MethodInfo ExecuteTaskWithEmptyResultMethod = typeof(RequestDelegateFactory).GetMethod(nameof(ExecuteTaskWithEmptyResult), BindingFlags.NonPublic | BindingFlags.Static)!;
private static readonly MethodInfo ExecuteValueTaskWithEmptyResultMethod = typeof(RequestDelegateFactory).GetMethod(nameof(ExecuteValueTaskWithEmptyResult), BindingFlags.NonPublic | BindingFlags.Static)!;
private static readonly MethodInfo ExecuteTaskOfTMethod = typeof(RequestDelegateFactory).GetMethod(nameof(ExecuteTaskOfT), BindingFlags.NonPublic | BindingFlags.Static)!;
@@ -648,8 +646,18 @@ private static Expression[] CreateArguments(ParameterInfo[]? parameters, Request
for (var i = 0; i < parameters.Length; i++)
{
- args[i] = CreateArgument(parameters[i], factoryContext);
+ args[i] = CreateArgument(parameters[i], factoryContext, out var hasTryParse, out var hasBindAsync, out var isAsParameters);
+ if (!isAsParameters)
+ {
+ factoryContext.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata(
+ name: parameters[i].Name!,
+ parameterInfo: parameters[i],
+ hasTryParse: hasTryParse,
+ hasBindAsync: hasBindAsync,
+ isOptional: IsOptionalParameter(parameters[i], factoryContext)
+ ));
+ }
factoryContext.ArgumentTypes[i] = parameters[i].ParameterType;
factoryContext.BoxedArgs[i] = Expression.Convert(args[i], typeof(object));
}
@@ -675,8 +683,11 @@ private static Expression[] CreateArguments(ParameterInfo[]? parameters, Request
return args;
}
- private static Expression CreateArgument(ParameterInfo parameter, RequestDelegateFactoryContext factoryContext)
+ private static Expression CreateArgument(ParameterInfo parameter, RequestDelegateFactoryContext factoryContext, out bool hasTryParse, out bool hasBindAsync, out bool isAsParameters)
{
+ hasTryParse = false;
+ hasBindAsync = false;
+ isAsParameters = false;
if (parameter.Name is null)
{
throw new InvalidOperationException($"Encountered a parameter of type '{parameter.ParameterType}' without a name. Parameters must have a name.");
@@ -770,8 +781,9 @@ private static Expression CreateArgument(ParameterInfo parameter, RequestDelegat
var useSimpleBinding = parameter.ParameterType == typeof(string) ||
parameter.ParameterType == typeof(StringValues) ||
parameter.ParameterType == typeof(StringValues?) ||
- ParameterBindingMethodCache.HasTryParseMethod(parameter.ParameterType) ||
- (parameter.ParameterType.IsArray && ParameterBindingMethodCache.HasTryParseMethod(parameter.ParameterType.GetElementType()!));
+ ParameterBindingMethodCache.Instance.HasTryParseMethod(parameter.ParameterType) ||
+ (parameter.ParameterType.IsArray && ParameterBindingMethodCache.Instance.HasTryParseMethod(parameter.ParameterType.GetElementType()!));
+ hasTryParse = useSimpleBinding;
return useSimpleBinding
? BindParameterFromFormItem(parameter, formAttribute.Name ?? parameter.Name, factoryContext)
: BindComplexParameterFromFormItem(parameter, string.IsNullOrEmpty(formAttribute.Name) ? parameter.Name : formAttribute.Name, factoryContext);
@@ -797,6 +809,7 @@ private static Expression CreateArgument(ParameterInfo parameter, RequestDelegat
}
else if (parameterCustomAttributes.OfType().Any())
{
+ isAsParameters = true;
if (parameter is PropertyAsParameterInfo)
{
throw new NotSupportedException(
@@ -845,12 +858,14 @@ private static Expression CreateArgument(ParameterInfo parameter, RequestDelegat
{
return RequestPipeReaderExpr;
}
- else if (ParameterBindingMethodCache.HasBindAsyncMethod(parameter))
+ else if (ParameterBindingMethodCache.Instance.HasBindAsyncMethod(parameter))
{
+ hasBindAsync = true;
return BindParameterFromBindAsync(parameter, factoryContext);
}
- else if (parameter.ParameterType == typeof(string) || ParameterBindingMethodCache.HasTryParseMethod(parameter.ParameterType))
+ else if (parameter.ParameterType == typeof(string) || ParameterBindingMethodCache.Instance.HasTryParseMethod(parameter.ParameterType))
{
+ hasTryParse = true;
// 1. We bind from route values only, if route parameters are non-null and the parameter name is in that set.
// 2. We bind from query only, if route parameters are non-null and the parameter name is NOT in that set.
// 3. Otherwise, we fallback to route or query if route parameters is null (it means we don't know what route parameters are defined). This case only happens
@@ -878,10 +893,10 @@ private static Expression CreateArgument(ParameterInfo parameter, RequestDelegat
parameter.ParameterType == typeof(string[]) ||
parameter.ParameterType == typeof(StringValues) ||
parameter.ParameterType == typeof(StringValues?) ||
- (parameter.ParameterType.IsArray && ParameterBindingMethodCache.HasTryParseMethod(parameter.ParameterType.GetElementType()!))))
+ (parameter.ParameterType.IsArray && ParameterBindingMethodCache.Instance.HasTryParseMethod(parameter.ParameterType.GetElementType()!))))
{
// We only infer parameter types if you have an array of TryParsables/string[]/StringValues/StringValues?, and DisableInferredFromBody is true
-
+ hasTryParse = true;
factoryContext.TrackedParameters.Add(parameter.Name, RequestDelegateFactoryConstants.QueryStringParameter);
return BindParameterFromProperty(parameter, QueryExpr, QueryIndexerProperty, parameter.Name, factoryContext, "query string");
}
@@ -1009,20 +1024,26 @@ private static void PopulateBuiltInResponseTypeMetadata(Type returnType, Endpoin
throw GetUnsupportedReturnTypeException(returnType);
}
+ var isAwaitable = false;
if (CoercedAwaitableInfo.IsTypeAwaitable(returnType, out var coercedAwaitableInfo))
{
returnType = coercedAwaitableInfo.AwaitableInfo.ResultType;
+ isAwaitable = true;
}
// Skip void returns and IResults. IResults might implement IEndpointMetadataProvider but otherwise we don't know what it might do.
- if (returnType == typeof(void) || typeof(IResult).IsAssignableFrom(returnType))
+ if (!isAwaitable && (returnType == typeof(void) || typeof(IResult).IsAssignableFrom(returnType)))
{
return;
}
if (returnType == typeof(string))
{
- builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(type: null, statusCode: 200, PlaintextContentType));
+ builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(type: typeof(string), statusCode: 200, PlaintextContentType));
+ }
+ else if (returnType == typeof(void))
+ {
+ builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(returnType, statusCode: 200, PlaintextContentType));
}
else
{
@@ -1542,7 +1563,7 @@ private static Expression BindParameterFromProperties(ParameterInfo parameter, R
}
var argumentExpression = Expression.Variable(parameter.ParameterType, $"{parameter.Name}_local");
- var (constructor, parameters) = ParameterBindingMethodCache.FindConstructor(parameterType);
+ var (constructor, parameters) = ParameterBindingMethodCache.Instance.FindConstructor(parameterType);
Expression initExpression;
@@ -1556,8 +1577,10 @@ private static Expression BindParameterFromProperties(ParameterInfo parameter, R
{
var parameterInfo =
new PropertyAsParameterInfo(parameters[i].PropertyInfo, parameters[i].ParameterInfo, factoryContext.NullabilityContext);
- constructorArguments[i] = CreateArgument(parameterInfo, factoryContext);
+ Debug.Assert(parameterInfo.Name != null, "Parameter name must be set for parameters resolved from properties.");
+ constructorArguments[i] = CreateArgument(parameterInfo, factoryContext, out var hasTryParse, out var hasBindAsync, out var _);
factoryContext.Parameters.Add(parameterInfo);
+ factoryContext.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata(parameterInfo.Name, parameterInfo, hasTryParse: hasTryParse, hasBindAsync: hasBindAsync, isOptional: parameterInfo.IsOptional));
}
initExpression = Expression.New(constructor, constructorArguments);
@@ -1579,8 +1602,10 @@ private static Expression BindParameterFromProperties(ParameterInfo parameter, R
if (properties[i].CanWrite && properties[i].GetSetMethod(nonPublic: false) != null)
{
var parameterInfo = new PropertyAsParameterInfo(properties[i], factoryContext.NullabilityContext);
- bindings.Add(Expression.Bind(properties[i], CreateArgument(parameterInfo, factoryContext)));
+ Debug.Assert(parameterInfo.Name != null, "Parameter name must be set for parameters resolved from properties.");
+ bindings.Add(Expression.Bind(properties[i], CreateArgument(parameterInfo, factoryContext, out var hasTryParse, out var hasBindAsync, out var _)));
factoryContext.Parameters.Add(parameterInfo);
+ factoryContext.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata(parameterInfo.Name, parameterInfo, hasTryParse: hasTryParse, hasBindAsync: hasBindAsync, isOptional: parameterInfo.IsOptional));
}
}
@@ -1649,7 +1674,7 @@ private static Expression BindParameterFromValue(ParameterInfo parameter, Expres
var isNotNullable = underlyingNullableType is null;
var nonNullableParameterType = underlyingNullableType ?? targetParseType;
- var tryParseMethodCall = ParameterBindingMethodCache.FindTryParseMethod(nonNullableParameterType);
+ var tryParseMethodCall = ParameterBindingMethodCache.Instance.FindTryParseMethod(nonNullableParameterType);
if (tryParseMethodCall is null)
{
@@ -1947,7 +1972,7 @@ private static Expression BindParameterFromBindAsync(ParameterInfo parameter, Re
var isOptional = IsOptionalParameter(parameter, factoryContext);
// Get the BindAsync method for the type.
- var bindAsyncMethod = ParameterBindingMethodCache.FindBindAsyncMethod(parameter);
+ var bindAsyncMethod = ParameterBindingMethodCache.Instance.FindBindAsyncMethod(parameter);
// We know BindAsync exists because there's no way to opt-in without defining the method on the type.
Debug.Assert(bindAsyncMethod.Expression is not null);
diff --git a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs
index 452eeb6c0674..2afff2e67bd7 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs
+++ b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs
@@ -2548,7 +2548,7 @@ public void Create_AddPlaintextResponseType_AsMetadata()
var responseMetadata = Assert.IsAssignableFrom(Assert.Single(result.EndpointMetadata));
Assert.Equal("text/plain", Assert.Single(responseMetadata.ContentTypes));
- Assert.Null(responseMetadata.Type);
+ Assert.Equal(typeof(string), responseMetadata.Type);
}
[Fact]
@@ -2567,6 +2567,7 @@ public void Create_DoesNotAddAnythingBefore_ThePassedInEndpointMetadata()
// but we just specified our CustomEndpointMetadata in this test.
Assert.Collection(result.EndpointMetadata,
m => Assert.Same(customMetadata, m),
+ m => Assert.True(m is IParameterBindingMetadata { HasBindAsync : true }),
m => Assert.True(m is ParameterNameMetadata { Name: "param1" }),
m => Assert.True(m is CustomEndpointMetadata { Source: MetadataSource.Parameter }));
}
@@ -2704,8 +2705,9 @@ public void Create_CombinesDefaultMetadata_AndMetadataFromTaskWrappedReturnTypes
// Assert
Assert.Contains(result.EndpointMetadata, m => m is CustomEndpointMetadata { Source: MetadataSource.Caller });
- // Expecting '1' because only initial metadata will be in the metadata list when this metadata item is added
- Assert.Contains(result.EndpointMetadata, m => m is MetadataCountMetadata { Count: 1 });
+ Assert.Contains(result.EndpointMetadata, m => m is ProducesResponseTypeMetadata { Type: { } type } && type == typeof(CountsDefaultEndpointMetadataResult));
+ // Expecting the custom metadata and the implicit metadata associated with a Task-based return type to be inserted
+ Assert.Contains(result.EndpointMetadata, m => m is MetadataCountMetadata { Count: 2 });
}
[Fact]
@@ -2726,8 +2728,9 @@ public void Create_CombinesDefaultMetadata_AndMetadataFromValueTaskWrappedReturn
// Assert
Assert.Contains(result.EndpointMetadata, m => m is CustomEndpointMetadata { Source: MetadataSource.Caller });
- // Expecting '1' because only initial metadata will be in the metadata list when this metadata item is added
- Assert.Contains(result.EndpointMetadata, m => m is MetadataCountMetadata { Count: 1 });
+ Assert.Contains(result.EndpointMetadata, m => m is ProducesResponseTypeMetadata { Type: { } type } && type == typeof(CountsDefaultEndpointMetadataResult));
+ // Expecting the custom metadata nad hte implicit metadata associated with a Task-based return type to be inserted
+ Assert.Contains(result.EndpointMetadata, m => m is MetadataCountMetadata { Count: 2 });
}
[Fact]
@@ -2748,8 +2751,9 @@ public void Create_CombinesDefaultMetadata_AndMetadataFromFSharpAsyncWrappedRetu
// Assert
Assert.Contains(result.EndpointMetadata, m => m is CustomEndpointMetadata { Source: MetadataSource.Caller });
+ Assert.Contains(result.EndpointMetadata, m => m is IProducesResponseTypeMetadata { Type: { } type } && type == typeof(CountsDefaultEndpointMetadataResult));
// Expecting '1' because only initial metadata will be in the metadata list when this metadata item is added
- Assert.Contains(result.EndpointMetadata, m => m is MetadataCountMetadata { Count: 1 });
+ Assert.Contains(result.EndpointMetadata, m => m is MetadataCountMetadata { Count: 2 });
}
[Fact]
@@ -2818,6 +2822,8 @@ public void Create_CombinesAllMetadata_InCorrectOrder()
m => Assert.True(m is CustomEndpointMetadata { Source: MetadataSource.Caller }),
// Inferred AcceptsMetadata from RDF for complex type
m => Assert.True(m is AcceptsMetadata am && am.RequestType == typeof(AddsCustomParameterMetadata)),
+ // Inferred ParameterBinding metadata
+ m => Assert.True(m is IParameterBindingMetadata { Name: "param1" }),
// Inferred ProducesResopnseTypeMetadata from RDF for complex type
m => Assert.Equal(typeof(CountsDefaultEndpointMetadataPoco), ((IProducesResponseTypeMetadata)m).Type),
// Metadata provided by parameters implementing IEndpointParameterMetadataProvider
@@ -2825,7 +2831,7 @@ public void Create_CombinesAllMetadata_InCorrectOrder()
// Metadata provided by parameters implementing IEndpointMetadataProvider
m => Assert.True(m is CustomEndpointMetadata { Source: MetadataSource.Parameter }),
// Metadata provided by return type implementing IEndpointMetadataProvider
- m => Assert.True(m is MetadataCountMetadata { Count: 5 }));
+ m => Assert.True(m is MetadataCountMetadata { Count: 6 }));
}
[Fact]
@@ -2878,7 +2884,7 @@ public void Create_DoesNotInferMetadata_GivenManuallyConstructedMetadataResult()
var result = RequestDelegateFactory.Create(@delegate, options, metadataResult);
// Assert
- Assert.Empty(result.EndpointMetadata);
+ Assert.Contains(result.EndpointMetadata, m => m is IParameterBindingMetadata { Name: "param1" });
Assert.Same(options.EndpointBuilder.Metadata, result.EndpointMetadata);
// Make extra sure things are running as expected, as this non-InferMetadata path is no longer exercised by RouteEndpointDataSource,
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/HandlesEndpointsWithAndWithoutDiagnostics.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/HandlesEndpointsWithAndWithoutDiagnostics.generated.txt
index 4ba6654a262e..ae38db998901 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/HandlesEndpointsWithAndWithoutDiagnostics.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/HandlesEndpointsWithAndWithoutDiagnostics.generated.txt
@@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_BindAsync_NullableReturn.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_BindAsync_NullableReturn.generated.txt
index 81d768e52b43..b17d8f132c15 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_BindAsync_NullableReturn.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_BindAsync_NullableReturn.generated.txt
@@ -70,7 +70,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("param", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -180,7 +181,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("param", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -368,6 +370,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_BindAsync_Snapshot.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_BindAsync_Snapshot.generated.txt
index e584608eb59d..cd074b2550d4 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_BindAsync_Snapshot.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_BindAsync_Snapshot.generated.txt
@@ -69,7 +69,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -180,7 +182,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -277,7 +280,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -376,7 +381,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -473,7 +479,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -584,7 +592,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -681,7 +690,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -780,7 +791,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -877,7 +889,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -987,7 +1001,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1083,7 +1098,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1181,7 +1198,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1277,7 +1295,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1388,7 +1408,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1485,7 +1506,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1595,7 +1618,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1691,7 +1715,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1802,7 +1828,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1899,7 +1926,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: true, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -2009,7 +2038,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("myBindAsyncParam", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: true, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -2184,6 +2214,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitBodyParam_ComplexReturn_Snapshot.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitBodyParam_ComplexReturn_Snapshot.generated.txt
index c353cec04fe2..e0820c222878 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitBodyParam_ComplexReturn_Snapshot.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitBodyParam_ComplexReturn_Snapshot.generated.txt
@@ -70,6 +70,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: typeof(global::Microsoft.AspNetCore.Http.Generators.Tests.Todo), isOptional: false, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("todo", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
PopulateMetadataForEndpoint>(methodInfo, options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -176,6 +177,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: typeof(global::Microsoft.AspNetCore.Http.Generators.Tests.Todo), isOptional: true, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("todo", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: true));
PopulateMetadataForEndpoint>(methodInfo, options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -417,6 +419,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_ComplexTypeArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_ComplexTypeArrayParam.generated.txt
index 43c52222ed32..9c14ef7fc2a3 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_ComplexTypeArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_ComplexTypeArrayParam.generated.txt
@@ -69,6 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -266,6 +267,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_NullableStringArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_NullableStringArrayParam.generated.txt
index 561816f4614b..338870404d4f 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_NullableStringArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_NullableStringArrayParam.generated.txt
@@ -69,6 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -238,6 +239,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_StringArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_StringArrayParam.generated.txt
index c364250c27de..5c7cdc3d5f31 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_StringArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitHeader_StringArrayParam.generated.txt
@@ -69,6 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -238,6 +239,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_ComplexTypeArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_ComplexTypeArrayParam.generated.txt
index 59a8d8116b8c..7be60ca31fb8 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_ComplexTypeArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_ComplexTypeArrayParam.generated.txt
@@ -69,6 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -266,6 +267,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableStringArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableStringArrayParam.generated.txt
index 225d3564d15d..d1747211273c 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableStringArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableStringArrayParam.generated.txt
@@ -69,6 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -237,6 +238,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam.generated.txt
index 215688d0e1e7..2a4903675562 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam.generated.txt
@@ -69,6 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -237,6 +238,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitServiceParam_SimpleReturn_Snapshot.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitServiceParam_SimpleReturn_Snapshot.generated.txt
index ba54b0c4ad79..0d43f3521412 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitServiceParam_SimpleReturn_Snapshot.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitServiceParam_SimpleReturn_Snapshot.generated.txt
@@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("svc", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -167,7 +168,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("svc", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -265,7 +267,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("svc", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("svcs", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -441,6 +445,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitSource_SimpleReturn_Snapshot.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitSource_SimpleReturn_Snapshot.generated.txt
index 4c9760e42208..ec49a917a460 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitSource_SimpleReturn_Snapshot.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitSource_SimpleReturn_Snapshot.generated.txt
@@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("queryValue", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -181,7 +182,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("headerValue", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -293,7 +295,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("routeValue", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -414,7 +417,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("value", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -607,6 +611,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_ComplexTypeArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_ComplexTypeArrayParam.generated.txt
index 1f4f87e9afca..744cb1967877 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_ComplexTypeArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_ComplexTypeArrayParam.generated.txt
@@ -69,6 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -273,6 +274,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam.generated.txt
index c059050111ec..05f5de4967e7 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam.generated.txt
@@ -84,6 +84,7 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -334,6 +335,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam_EmptyQueryValues.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam_EmptyQueryValues.generated.txt
index c059050111ec..05f5de4967e7 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam_EmptyQueryValues.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam_EmptyQueryValues.generated.txt
@@ -84,6 +84,7 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -334,6 +335,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam_QueryNotPresent.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam_QueryNotPresent.generated.txt
index c059050111ec..05f5de4967e7 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam_QueryNotPresent.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableStringArrayParam_QueryNotPresent.generated.txt
@@ -84,6 +84,7 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -334,6 +335,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam.generated.txt
index 5b5a107e475e..fde7b721a577 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam.generated.txt
@@ -84,6 +84,7 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -334,6 +335,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_JsonBodyOrService_HandlesBothJsonAndService.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_JsonBodyOrService_HandlesBothJsonAndService.generated.txt
index 779efb616d06..7866a45bf43a 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_JsonBodyOrService_HandlesBothJsonAndService.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_JsonBodyOrService_HandlesBothJsonAndService.generated.txt
@@ -85,7 +85,9 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("todo", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("svc", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -351,6 +353,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_MultipleSpecialTypeParam_StringReturn.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_MultipleSpecialTypeParam_StringReturn.generated.txt
index add8e79a859a..ef673881c510 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_MultipleSpecialTypeParam_StringReturn.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_MultipleSpecialTypeParam_StringReturn.generated.txt
@@ -69,7 +69,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("req", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("res", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -240,6 +242,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_MultipleStringParam_StringReturn.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_MultipleStringParam_StringReturn.generated.txt
index b76324c9d0f8..6dcece0634d8 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_MultipleStringParam_StringReturn.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_MultipleStringParam_StringReturn.generated.txt
@@ -69,7 +69,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p1", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p2", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -273,6 +275,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_NoParam_StringReturn_WithFilter.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_NoParam_StringReturn_WithFilter.generated.txt
index 4ba6654a262e..ae38db998901 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_NoParam_StringReturn_WithFilter.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_NoParam_StringReturn_WithFilter.generated.txt
@@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ReturnsString_Has_Metadata.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ReturnsString_Has_Metadata.generated.txt
index 4ba6654a262e..ae38db998901 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ReturnsString_Has_Metadata.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ReturnsString_Has_Metadata.generated.txt
@@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleComplexTypeParam_StringReturn.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleComplexTypeParam_StringReturn.generated.txt
index 8a4e1c8411b1..e11a4e1978b3 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleComplexTypeParam_StringReturn.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleComplexTypeParam_StringReturn.generated.txt
@@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -273,6 +274,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleEnumParam_StringReturn.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleEnumParam_StringReturn.generated.txt
index 4c46221e27a9..00ed02cdf437 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleEnumParam_StringReturn.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleEnumParam_StringReturn.generated.txt
@@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -273,6 +274,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleNullableStringParam_WithEmptyQueryStringValueProvided_StringReturn.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleNullableStringParam_WithEmptyQueryStringValueProvided_StringReturn.generated.txt
index d3a31800ab3f..9d8c1c5ec159 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleNullableStringParam_WithEmptyQueryStringValueProvided_StringReturn.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_SingleNullableStringParam_WithEmptyQueryStringValueProvided_StringReturn.generated.txt
@@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: true));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -245,6 +246,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_TakesCustomMetadataEmitter_Has_Metadata.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_TakesCustomMetadataEmitter_Has_Metadata.generated.txt
index 9ce50bcba1fc..cb8f45469fab 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_TakesCustomMetadataEmitter_Has_Metadata.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_TakesCustomMetadataEmitter_Has_Metadata.generated.txt
@@ -84,6 +84,7 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("x", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
var parameterInfos = methodInfo.GetParameters();
var x_ParameterInfo = parameterInfos[0];
PopulateMetadataForParameter(x_ParameterInfo, options.EndpointBuilder);
@@ -340,6 +341,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_Get_WithArrayQueryString_AndBody_ShouldUseQueryString.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_Get_WithArrayQueryString_AndBody_ShouldUseQueryString.generated.txt
index a4fc77ad1227..1620b5412616 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_Get_WithArrayQueryString_AndBody_ShouldUseQueryString.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_Get_WithArrayQueryString_AndBody_ShouldUseQueryString.generated.txt
@@ -84,7 +84,8 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -341,6 +342,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_PostAndGet_WithArrayQueryString_AndBody_ShouldUseQueryString.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_PostAndGet_WithArrayQueryString_AndBody_ShouldUseQueryString.generated.txt
index a4fc77ad1227..1620b5412616 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_PostAndGet_WithArrayQueryString_AndBody_ShouldUseQueryString.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_PostAndGet_WithArrayQueryString_AndBody_ShouldUseQueryString.generated.txt
@@ -84,7 +84,8 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -341,6 +342,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_PostAndPut_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_PostAndPut_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
index a4fc77ad1227..1620b5412616 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_PostAndPut_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_PostAndPut_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
@@ -84,7 +84,8 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -341,6 +342,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_Post_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_Post_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
index a4fc77ad1227..1620b5412616 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_Post_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapMethods_Post_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
@@ -84,7 +84,8 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -341,6 +342,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapPost_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapPost_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
index 598d3543f866..7ebdfa4be28b 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapPost_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapPost_WithArrayQueryString_AndBody_ShouldUseBody.generated.txt
@@ -84,7 +84,8 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -341,6 +342,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapPost_WithArrayQueryString_ShouldFail.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapPost_WithArrayQueryString_ShouldFail.generated.txt
index 1b03fbb80eab..8444c64d3afa 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapPost_WithArrayQueryString_ShouldFail.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapPost_WithArrayQueryString_ShouldFail.generated.txt
@@ -84,6 +84,7 @@ namespace Microsoft.AspNetCore.Http.Generated
break;
}
}
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
@@ -334,6 +335,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/Multiple_MapAction_NoParam_StringReturn.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/Multiple_MapAction_NoParam_StringReturn.generated.txt
index 484aaefc7f3c..79567d9d3a09 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/Multiple_MapAction_NoParam_StringReturn.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/Multiple_MapAction_NoParam_StringReturn.generated.txt
@@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -161,7 +161,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -255,7 +255,7 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/Multiple_MapAction_WithParams_StringReturn.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/Multiple_MapAction_WithParams_StringReturn.generated.txt
index 17fa1194e78a..5c5b767c4993 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/Multiple_MapAction_WithParams_StringReturn.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/Multiple_MapAction_WithParams_StringReturn.generated.txt
@@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("req", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -164,7 +165,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("res", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -259,7 +261,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("req", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("res", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -430,6 +434,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/RequestDelegateValidateGeneratedFormCode.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/RequestDelegateValidateGeneratedFormCode.generated.txt
index a093bce3d48c..bb30424cb7ff 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/RequestDelegateValidateGeneratedFormCode.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/RequestDelegateValidateGeneratedFormCode.generated.txt
@@ -71,6 +71,11 @@ namespace Microsoft.AspNetCore.Http.Generated
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
options.EndpointBuilder.Metadata.Add(AntiforgeryMetadata.ValidationRequired);
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(contentTypes: GeneratedMetadataConstants.FormFileContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("httpContext", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("file", methodInfo.GetParameters()[1], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("fileCollection", methodInfo.GetParameters()[2], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("collection", methodInfo.GetParameters()[3], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("tryParseRecord", methodInfo.GetParameters()[4], hasTryParse: true, hasBindAsync: false, isOptional: false));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -387,6 +392,33 @@ file sealed class AntiforgeryMetadata : IAntiforgeryMetadata
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsDifferentInterceptorsFromSameLocation.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsDifferentInterceptorsFromSameLocation.generated.txt
index 746ccff2f381..c5ba9a893684 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsDifferentInterceptorsFromSameLocation.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsDifferentInterceptorsFromSameLocation.generated.txt
@@ -69,7 +69,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("name", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -182,7 +183,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("age", methodInfo.GetParameters()[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -393,6 +395,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsSameInterceptorsFromDifferentFiles.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsSameInterceptorsFromDifferentFiles.generated.txt
index de4a2f087ea0..4c987b44f6b0 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsSameInterceptorsFromDifferentFiles.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsSameInterceptorsFromDifferentFiles.generated.txt
@@ -71,7 +71,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("name", methodInfo.GetParameters()[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -264,6 +265,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/VerifyAsParametersBaseline.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/VerifyAsParametersBaseline.generated.txt
index b26c613dc854..30b4541a6f49 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/VerifyAsParametersBaseline.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/VerifyAsParametersBaseline.generated.txt
@@ -72,6 +72,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("HttpContext", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParameterListWitDefaultValue)!.GetProperty("HttpContext")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParameterListWitDefaultValue).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(int) })?.GetParameters()[0]), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("Value", new PropertyAsParameterInfo(true, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParameterListWitDefaultValue)!.GetProperty("Value")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParameterListWitDefaultValue).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(int) })?.GetParameters()[1]), hasTryParse: true, hasBindAsync: false, isOptional: true));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -208,6 +210,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("HttpContext", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParameterListRecordStruct)!.GetProperty("HttpContext")!), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("Value", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParameterListRecordStruct)!.GetProperty("Value")!), hasTryParse: true, hasBindAsync: false, isOptional: false));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -337,6 +341,10 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("HttpContext", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithHttpContext)!.GetProperty("HttpContext")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithHttpContext).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(System.Security.Claims.ClaimsPrincipal), typeof(Microsoft.AspNetCore.Http.HttpRequest), typeof(Microsoft.AspNetCore.Http.HttpResponse) })?.GetParameters()[0]), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("User", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithHttpContext)!.GetProperty("User")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithHttpContext).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(System.Security.Claims.ClaimsPrincipal), typeof(Microsoft.AspNetCore.Http.HttpRequest), typeof(Microsoft.AspNetCore.Http.HttpResponse) })?.GetParameters()[1]), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("Request", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithHttpContext)!.GetProperty("Request")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithHttpContext).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(System.Security.Claims.ClaimsPrincipal), typeof(Microsoft.AspNetCore.Http.HttpRequest), typeof(Microsoft.AspNetCore.Http.HttpResponse) })?.GetParameters()[2]), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("Response", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithHttpContext)!.GetProperty("Response")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithHttpContext).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(System.Security.Claims.ClaimsPrincipal), typeof(Microsoft.AspNetCore.Http.HttpRequest), typeof(Microsoft.AspNetCore.Http.HttpResponse) })?.GetParameters()[3]), hasTryParse: false, hasBindAsync: false, isOptional: false));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -438,7 +446,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(contentTypes: GeneratedMetadataConstants.JsonContentType));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("HttpContext", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithImplicitFromBody)!.GetProperty("HttpContext")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithImplicitFromBody).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(Microsoft.AspNetCore.Http.Generators.Tests.TodoStruct) })?.GetParameters()[0]), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("Todo", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithImplicitFromBody)!.GetProperty("Todo")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithImplicitFromBody).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(Microsoft.AspNetCore.Http.Generators.Tests.TodoStruct) })?.GetParameters()[1]), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -557,6 +567,8 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("HttpContext", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithMetadataType)!.GetProperty("HttpContext")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithMetadataType).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(Microsoft.AspNetCore.Http.Generators.Tests.AddsCustomParameterMetadataAsProperty) })?.GetParameters()[0]), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("Value", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithMetadataType)!.GetProperty("Value")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithMetadataType).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(Microsoft.AspNetCore.Http.Generators.Tests.AddsCustomParameterMetadataAsProperty) })?.GetParameters()[1]), hasTryParse: false, hasBindAsync: false, isOptional: false));
var parameterInfos = methodInfo.GetParameters();
var Value_ParameterInfo = new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithMetadataType)!.GetProperty("Value")!, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParametersListWithMetadataType).GetConstructor(new[] { typeof(Microsoft.AspNetCore.Http.HttpContext), typeof(Microsoft.AspNetCore.Http.Generators.Tests.AddsCustomParameterMetadataAsProperty) })?.GetParameters()[1]);
PopulateMetadataForParameter(Value_ParameterInfo, options.EndpointBuilder);
@@ -671,7 +683,9 @@ namespace Microsoft.AspNetCore.Http.Generated
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42"));
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(contentTypes: GeneratedMetadataConstants.JsonContentType));
- options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, contentTypes: GeneratedMetadataConstants.PlaintextContentType));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("Todo", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParameterRecordStructWithJsonBodyOrService)!.GetProperty("Todo")!), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("Service", new PropertyAsParameterInfo(false, typeof(Microsoft.AspNetCore.Http.Generators.Tests.ParameterRecordStructWithJsonBodyOrService)!.GetProperty("Service")!), hasTryParse: false, hasBindAsync: false, isOptional: false));
+ options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -1059,6 +1073,33 @@ namespace Microsoft.AspNetCore.Http.Generated
public new bool IsOptional { get; }
}
+ %GENERATEDCODEATTRIBUTE%
+ file sealed class ParameterBindingMetadata: IParameterBindingMetadata
+ {
+ internal ParameterBindingMetadata(
+ string name,
+ ParameterInfo parameterInfo,
+ bool hasTryParse = false,
+ bool hasBindAsync = false,
+ bool isOptional = false)
+ {
+ Name = name;
+ ParameterInfo = parameterInfo;
+ HasTryParse = hasTryParse;
+ HasBindAsync = hasBindAsync;
+ IsOptional = isOptional;
+ }
+
+ public string Name { get; }
+
+ public bool HasTryParse { get; }
+
+ public bool HasBindAsync { get; }
+
+ public ParameterInfo ParameterInfo { get; }
+
+ public bool IsOptional { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file sealed class LogOrThrowExceptionHelper
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Metadata.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Metadata.cs
index 6be8fd336245..68f0af004651 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Metadata.cs
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Metadata.cs
@@ -33,7 +33,7 @@ public async Task MapAction_ReturnsString_Has_Metadata()
var metadata = endpoint.Metadata.OfType().Single();
Assert.Equal(200, metadata.StatusCode);
Assert.Equal("text/plain", metadata.ContentTypes.Single());
- Assert.Null(metadata.Type);
+ Assert.Equal(typeof(string), metadata.Type);
await VerifyAgainstBaselineUsingFile(compilation);
}
@@ -79,19 +79,21 @@ public async Task MapAction_ReturnsTaskOfString_Has_Metadata()
var metadata = endpoint.Metadata.OfType().Single();
Assert.Equal(200, metadata.StatusCode);
Assert.Equal("text/plain", metadata.ContentTypes.Single());
- Assert.Null(metadata.Type);
+ Assert.Equal(typeof(string), metadata.Type);
}
[Fact]
- public async Task MapAction_ReturnsTask_Has_No_Metadata()
+ public async Task MapAction_ReturnsTask_ProducesInferredMetadata()
{
var (_, compilation) = await RunGeneratorAsync("""
app.MapGet("/", Task () => Task.CompletedTask);
""");
var endpoint = GetEndpointFromCompilation(compilation);
- var metadata = endpoint.Metadata.OfType();
- Assert.Empty(metadata);
+ var metadata = endpoint.Metadata.OfType().Single();
+ Assert.Equal(200, metadata.StatusCode);
+ Assert.Equal("text/plain", metadata.ContentTypes.Single());
+ Assert.Equal(typeof(void), metadata.Type);
}
[Fact]
@@ -105,19 +107,21 @@ public async Task MapAction_ReturnsValueTaskOfString_Has_Metadata()
var metadata = endpoint.Metadata.OfType().Single();
Assert.Equal(200, metadata.StatusCode);
Assert.Equal("text/plain", metadata.ContentTypes.Single());
- Assert.Null(metadata.Type);
+ Assert.Equal(typeof(string), metadata.Type);
}
[Fact]
- public async Task MapAction_ReturnsValueTask_Has_No_Metadata()
+ public async Task MapAction_ReturnsValueTask_ProducesInferredMetadata()
{
var (_, compilation) = await RunGeneratorAsync("""
app.MapGet("/", ValueTask () => ValueTask.CompletedTask);
""");
var endpoint = GetEndpointFromCompilation(compilation);
- var metadata = endpoint.Metadata.OfType();
- Assert.Empty(metadata);
+ var metadata = endpoint.Metadata.OfType().Single();
+ Assert.Equal(200, metadata.StatusCode);
+ Assert.Equal("text/plain", metadata.ContentTypes.Single());
+ Assert.Equal(typeof(void), metadata.Type);
}
[Fact]
@@ -189,7 +193,7 @@ public async Task Create_AddPlaintextResponseType_AsMetadata()
var responseMetadata = endpoint.Metadata.OfType().Single();
Assert.Equal("text/plain", Assert.Single(responseMetadata.ContentTypes));
- Assert.Null(responseMetadata.Type);
+ Assert.Equal(typeof(string), responseMetadata.Type);
}
[Fact]
@@ -526,6 +530,8 @@ m is not Attribute2 &&
Assert.Collection(filteredMetadata,
// Inferred AcceptsMetadata from RDF for complex type
m => Assert.True(m is IAcceptsMetadata am && am.RequestType == typeof(AddsCustomParameterMetadata)),
+ // Parameter binding metadata inferred by RDF
+ m => Assert.True(m is IParameterBindingMetadata { Name: "param1" }),
// Inferred ProducesResopnseTypeMetadata from RDF for complex type
m => Assert.Equal(typeof(CountsDefaultEndpointMetadataPoco), ((IProducesResponseTypeMetadata)m).Type),
// Metadata provided by parameters implementing IEndpointParameterMetadataProvider
diff --git a/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs b/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs
index 451c408d004b..a5156c7fff05 100644
--- a/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs
+++ b/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs
@@ -487,6 +487,7 @@ public void Map_AddsMetadata_InCorrectOrder()
Assert.Collection(metadata,
m => Assert.IsAssignableFrom(m),
+ m => Assert.IsAssignableFrom(m),
m => Assert.IsAssignableFrom(m),
m =>
{
diff --git a/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.WarningSuppressions.xml b/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.WarningSuppressions.xml
new file mode 100644
index 000000000000..97a42afc46b0
--- /dev/null
+++ b/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.WarningSuppressions.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ ILLink
+ IL2026
+ member
+ M:Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata.#ctor(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity)
+
+
+
\ No newline at end of file
diff --git a/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.csproj b/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.csproj
index 376dd41c133b..16a5411f1caf 100644
--- a/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.csproj
+++ b/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.csproj
@@ -9,6 +9,12 @@ Microsoft.AspNetCore.Mvc.IActionResult
true
aspnetcore;aspnetcoremvc
false
+
+ true
+ false
+ false
diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelMetadata.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelMetadata.cs
index 1f6e8042341a..e6cd088cf93a 100644
--- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelMetadata.cs
+++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelMetadata.cs
@@ -27,8 +27,19 @@ public abstract class ModelMetadata : IEquatable, IModelMetadata
///
public static readonly int DefaultOrder = 10000;
- private static readonly ParameterBindingMethodCache ParameterBindingMethodCache
- = new(throwOnInvalidMethod: false);
+ internal const string RequiresUnreferencedCodeMessage = "Resolving this property is not compatible with trimming, as it requires dynamic access to code that is not referenced statically.";
+ internal const string RequiresDynamicCodeMessage = "Resolving this property may require dynamic code generation.";
+
+ ///
+ /// Exposes a feature switch to disable generating model metadata with reflection-heavy strategies.
+ /// This is primarily intended for use in Minimal API-based scenarios where information is derived from
+ /// IParameterBindingMetadata
+ ///
+ [FeatureSwitchDefinition("Microsoft.AspNetCore.Mvc.ApiExplorer.IsEnhancedModelMetadataSupported")]
+ [FeatureGuard(typeof(RequiresDynamicCodeAttribute))]
+ [FeatureGuard(typeof(RequiresUnreferencedCodeAttribute))]
+ private static bool IsEnhancedModelMetadataSupported { get; } =
+ AppContext.TryGetSwitch("Microsoft.AspNetCore.Mvc.ApiExplorer.IsEnhancedModelMetadataSupported", out var isEnhancedModelMetadataSupported) ? isEnhancedModelMetadataSupported : true;
private int? _hashCode;
private IReadOnlyList? _boundProperties;
@@ -46,6 +57,10 @@ protected ModelMetadata(ModelMetadataIdentity identity)
Identity = identity;
InitializeTypeInformation();
+ if (IsEnhancedModelMetadataSupported)
+ {
+ InitializeDynamicTypeInformation();
+ }
}
///
@@ -428,11 +443,29 @@ internal IReadOnlyDictionary BoundConstructorPrope
///
public abstract IReadOnlyList