diff --git a/src/Http/Http.Abstractions/src/Metadata/ApiEndpointMetadata.cs b/src/Http/Http.Abstractions/src/Metadata/ApiEndpointMetadata.cs
new file mode 100644
index 000000000000..815bf2c834c9
--- /dev/null
+++ b/src/Http/Http.Abstractions/src/Metadata/ApiEndpointMetadata.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.Http.Metadata;
+
+///
+/// Metadata that indicates the endpoint is intended for API clients.
+/// When present, authentication handlers should prefer returning status codes over browser redirects.
+///
+internal sealed class ApiEndpointMetadata : IApiEndpointMetadata
+{
+ ///
+ /// Singleton instance of .
+ ///
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+}
diff --git a/src/Http/Http.Abstractions/src/Metadata/IApiEndpointMetadata.cs b/src/Http/Http.Abstractions/src/Metadata/IApiEndpointMetadata.cs
new file mode 100644
index 000000000000..cadaafcae1a9
--- /dev/null
+++ b/src/Http/Http.Abstractions/src/Metadata/IApiEndpointMetadata.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.Http.Metadata;
+
+///
+/// Metadata that indicates the endpoint is an API intended for programmatic access rather than direct browser navigation.
+/// When present, authentication handlers should prefer returning status codes over browser redirects.
+///
+public interface IApiEndpointMetadata
+{
+}
diff --git a/src/Http/Http.Abstractions/src/Microsoft.AspNetCore.Http.Abstractions.csproj b/src/Http/Http.Abstractions/src/Microsoft.AspNetCore.Http.Abstractions.csproj
index d383efa6a20e..37e17a0f0f49 100644
--- a/src/Http/Http.Abstractions/src/Microsoft.AspNetCore.Http.Abstractions.csproj
+++ b/src/Http/Http.Abstractions/src/Microsoft.AspNetCore.Http.Abstractions.csproj
@@ -35,7 +35,6 @@ Microsoft.AspNetCore.Http.HttpResponse
-
@@ -61,5 +60,6 @@ Microsoft.AspNetCore.Http.HttpResponse
+
diff --git a/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt b/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt
index 3a2461306d54..2944a853cdf2 100644
--- a/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt
+++ b/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt
@@ -1,4 +1,5 @@
#nullable enable
+Microsoft.AspNetCore.Http.Metadata.IApiEndpointMetadata
Microsoft.AspNetCore.Http.Metadata.IDisableValidationMetadata
Microsoft.AspNetCore.Http.ProducesResponseTypeMetadata.Description.get -> string?
Microsoft.AspNetCore.Http.ProducesResponseTypeMetadata.Description.set -> void
diff --git a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/RequestDelegateGenerator.cs b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/RequestDelegateGenerator.cs
index f4e2ad0e8e33..f5e2abacaaf1 100644
--- a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/RequestDelegateGenerator.cs
+++ b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/RequestDelegateGenerator.cs
@@ -248,7 +248,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
if (hasFormBody)
{
- codeWriter.WriteLine(RequestDelegateGeneratorSources.AntiforgeryMetadataType);
+ codeWriter.WriteLine(RequestDelegateGeneratorSources.AntiforgeryMetadataClass);
+ }
+
+ if (hasJsonBody || hasResponseMetadata)
+ {
+ codeWriter.WriteLine(RequestDelegateGeneratorSources.ApiEndpointMetadataClass);
}
if (hasFormBody || hasJsonBody || hasResponseMetadata)
diff --git a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/RequestDelegateGeneratorSources.cs b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/RequestDelegateGeneratorSources.cs
index d7c7a480446c..b626db274124 100644
--- a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/RequestDelegateGeneratorSources.cs
+++ b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/RequestDelegateGeneratorSources.cs
@@ -479,19 +479,39 @@ internal ParameterBindingMetadata(
}
""";
- public static string AntiforgeryMetadataType = """
-file sealed class AntiforgeryMetadata : IAntiforgeryMetadata
-{
- public static readonly IAntiforgeryMetadata ValidationRequired = new AntiforgeryMetadata(true);
-
- public AntiforgeryMetadata(bool requiresValidation)
+ public static string AntiforgeryMetadataClass = """
+ file sealed class AntiforgeryMetadata : IAntiforgeryMetadata
{
- RequiresValidation = requiresValidation;
+ public static readonly IAntiforgeryMetadata ValidationRequired = new AntiforgeryMetadata(true);
+
+ public AntiforgeryMetadata(bool requiresValidation)
+ {
+ RequiresValidation = requiresValidation;
+ }
+
+ public bool RequiresValidation { get; }
}
+""";
- public bool RequiresValidation { get; }
-}
+ public static string ApiEndpointMetadataClass = """
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
""";
+
public static string GetGeneratedRouteBuilderExtensionsSource(string endpoints, string helperMethods, string helperTypes, ImmutableHashSet verbs) => $$"""
{{SourceHeader}}
diff --git a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/StaticRouteHandlerModel/StaticRouteHandlerModel.Emitter.cs b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/StaticRouteHandlerModel/StaticRouteHandlerModel.Emitter.cs
index 83790d44eb33..97fe2dc990ff 100644
--- a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/StaticRouteHandlerModel/StaticRouteHandlerModel.Emitter.cs
+++ b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.RequestDelegateGenerator/StaticRouteHandlerModel/StaticRouteHandlerModel.Emitter.cs
@@ -205,7 +205,7 @@ private static void EmitBuiltinResponseTypeMetadata(this Endpoint endpoint, Code
return;
}
- if (!endpoint.Response.IsAwaitable && (response.HasNoResponse || response.IsIResult))
+ if (response.HasNoResponse || response.IsIResult)
{
return;
}
@@ -215,13 +215,10 @@ private static void EmitBuiltinResponseTypeMetadata(this Endpoint endpoint, Code
{
codeWriter.WriteLine($"options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(string), contentTypes: GeneratedMetadataConstants.PlaintextContentType));");
}
- 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));""");
+ codeWriter.WriteLine("ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);");
}
}
@@ -339,13 +336,15 @@ public static void EmitJsonAcceptsMetadata(this Endpoint endpoint, CodeWriter co
codeWriter.WriteLine("if (!serviceProviderIsService.IsService(type))");
codeWriter.StartBlock();
codeWriter.WriteLine("options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));");
+ codeWriter.WriteLine("options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);");
codeWriter.WriteLine("break;");
codeWriter.EndBlock();
codeWriter.EndBlock();
}
else
{
- codeWriter.WriteLine($"options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(contentTypes: GeneratedMetadataConstants.JsonContentType));");
+ codeWriter.WriteLine("options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(contentTypes: GeneratedMetadataConstants.JsonContentType));");
+ codeWriter.WriteLine("options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);");
}
}
diff --git a/src/Http/Http.Extensions/src/RequestDelegateFactory.cs b/src/Http/Http.Extensions/src/RequestDelegateFactory.cs
index 19965ef1fc31..aaebe4179806 100644
--- a/src/Http/Http.Extensions/src/RequestDelegateFactory.cs
+++ b/src/Http/Http.Extensions/src/RequestDelegateFactory.cs
@@ -401,7 +401,14 @@ private static Expression[] CreateArgumentsAndInferMetadata(MethodInfo methodInf
InferAntiforgeryMetadata(factoryContext);
}
- PopulateBuiltInResponseTypeMetadata(methodInfo.ReturnType, factoryContext.EndpointBuilder);
+ // If this endpoint expects a JSON request body, we assume its an API endpoint not intended for browser navigation.
+ // When present, authentication handlers should prefer returning status codes over browser redirects.
+ if (factoryContext.JsonRequestBodyParameter is not null)
+ {
+ factoryContext.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
+ }
+
+ PopulateBuiltInResponseTypeMetadata(methodInfo.ReturnType, factoryContext);
// Add metadata provided by the delegate return type and parameter types next, this will be more specific than inferred metadata from above
EndpointMetadataPopulator.PopulateMetadata(methodInfo, factoryContext.EndpointBuilder, factoryContext.Parameters);
@@ -1023,37 +1030,40 @@ private static Expression CreateParamCheckingResponseWritingMethodCall(Type retu
return Expression.Block(localVariables, checkParamAndCallMethod);
}
- private static void PopulateBuiltInResponseTypeMetadata(Type returnType, EndpointBuilder builder)
+ private static void PopulateBuiltInResponseTypeMetadata(Type returnType, RequestDelegateFactoryContext factoryContext)
{
if (returnType.IsByRefLike)
{
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 (!isAwaitable && (returnType == typeof(void) || typeof(IResult).IsAssignableFrom(returnType)))
+ if (returnType == typeof(void) || typeof(IResult).IsAssignableFrom(returnType))
{
return;
}
+ var builder = factoryContext.EndpointBuilder;
+
if (returnType == typeof(string))
{
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
{
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(returnType, statusCode: 200, DefaultAcceptsAndProducesContentType));
+
+ if (factoryContext.JsonRequestBodyParameter is null)
+ {
+ // Since this endpoint responds with JSON, we assume its an API endpoint not intended for browser navigation,
+ // but we don't want to bother adding this metadata twice if we've already inferred it based on the expected JSON request body.
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
+ }
}
}
diff --git a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs
index 083da9bd7aed..7cee04fb8a0f 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs
+++ b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs
@@ -2533,7 +2533,7 @@ public void Create_AddJsonResponseType_AsMetadata()
var @delegate = () => new object();
var result = RequestDelegateFactory.Create(@delegate);
- var responseMetadata = Assert.IsAssignableFrom(Assert.Single(result.EndpointMetadata));
+ var responseMetadata = Assert.Single(result.EndpointMetadata.OfType());
Assert.Equal("application/json", Assert.Single(responseMetadata.ContentTypes));
Assert.Equal(typeof(object), responseMetadata.Type);
@@ -2545,7 +2545,7 @@ public void Create_AddPlaintextResponseType_AsMetadata()
var @delegate = () => "Hello";
var result = RequestDelegateFactory.Create(@delegate);
- var responseMetadata = Assert.IsAssignableFrom(Assert.Single(result.EndpointMetadata));
+ var responseMetadata = Assert.Single(result.EndpointMetadata.OfType());
Assert.Equal("text/plain", Assert.Single(responseMetadata.ContentTypes));
Assert.Equal(typeof(string), responseMetadata.Type);
@@ -2683,6 +2683,7 @@ public void Create_CombinesDefaultMetadata_AndMetadataFromReturnTypesImplementin
// Assert
Assert.Contains(result.EndpointMetadata, m => m is CustomEndpointMetadata { Source: MetadataSource.Caller });
+ Assert.DoesNotContain(result.EndpointMetadata, m => m is IProducesResponseTypeMetadata);
// 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 });
}
@@ -2705,9 +2706,9 @@ public void Create_CombinesDefaultMetadata_AndMetadataFromTaskWrappedReturnTypes
// Assert
Assert.Contains(result.EndpointMetadata, m => m is CustomEndpointMetadata { Source: MetadataSource.Caller });
- 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 });
+ Assert.DoesNotContain(result.EndpointMetadata, m => m is IProducesResponseTypeMetadata);
+ // 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 });
}
[Fact]
@@ -2728,9 +2729,9 @@ public void Create_CombinesDefaultMetadata_AndMetadataFromValueTaskWrappedReturn
// Assert
Assert.Contains(result.EndpointMetadata, m => m is CustomEndpointMetadata { Source: MetadataSource.Caller });
- 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 });
+ Assert.DoesNotContain(result.EndpointMetadata, m => m is IProducesResponseTypeMetadata);
+ // 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 });
}
[Fact]
@@ -2751,9 +2752,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));
+ Assert.DoesNotContain(result.EndpointMetadata, m => m is IProducesResponseTypeMetadata);
// 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: 2 });
+ Assert.Contains(result.EndpointMetadata, m => m is MetadataCountMetadata { Count: 1 });
}
[Fact]
@@ -2824,14 +2825,16 @@ public void Create_CombinesAllMetadata_InCorrectOrder()
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
+ // Inferred IApiEndpointMetadata from RDF for complex request and response type
+ m => Assert.True(m is IApiEndpointMetadata),
+ // Inferred ProducesResponseTypeMetadata from RDF for complex type
m => Assert.Equal(typeof(CountsDefaultEndpointMetadataPoco), ((IProducesResponseTypeMetadata)m).Type),
// Metadata provided by parameters implementing IEndpointParameterMetadataProvider
m => Assert.True(m is ParameterNameMetadata { Name: "param1" }),
// 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: 6 }));
+ m => Assert.True(m is MetadataCountMetadata { Count: 7 }));
}
[Fact]
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 ae38db998901..18cf2ce8010b 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/HandlesEndpointsWithAndWithoutDiagnostics.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/HandlesEndpointsWithAndWithoutDiagnostics.generated.txt
@@ -225,6 +225,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 ddfeaf604670..04b1dc6c3bbe 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
@@ -363,6 +363,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 ab79dddfdc12..6c1240e6b8f3 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
@@ -2225,6 +2225,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 28e8316f4a7e..830c81d1309b 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
@@ -412,6 +412,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 3a8e7fe8928b..bd0ceac25240 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
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -259,6 +260,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 6365d1485f43..e2c866e2c2bb 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
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -231,6 +232,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 66c4504e000b..b2fc71b9158a 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
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -231,6 +232,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 860627ce40b0..9aee726d2055 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
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -259,6 +260,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_IntArrayParam_Optional.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_IntArrayParam_Optional.generated.txt
index f09d01273f7e..01d6808eaf6e 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_IntArrayParam_Optional.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_IntArrayParam_Optional.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -259,6 +260,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_IntArrayParam_Optional_QueryNotPresent.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_IntArrayParam_Optional_QueryNotPresent.generated.txt
index f09d01273f7e..01d6808eaf6e 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_IntArrayParam_Optional_QueryNotPresent.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_IntArrayParam_Optional_QueryNotPresent.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -259,6 +260,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableIntArrayParam_Optional.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableIntArrayParam_Optional.generated.txt
index 9075d188acda..40a1b29bb120 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableIntArrayParam_Optional.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableIntArrayParam_Optional.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32?[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -259,6 +260,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableIntArrayParam_Optional_QueryNotPresent.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableIntArrayParam_Optional_QueryNotPresent.generated.txt
index 9075d188acda..40a1b29bb120 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableIntArrayParam_Optional_QueryNotPresent.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_NullableIntArrayParam_Optional_QueryNotPresent.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32?[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -259,6 +260,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 1d755d1dc5ad..9bebb6eea5ee 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
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -230,6 +231,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 e9d7ec91cc48..7931fdc136d0 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
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -230,6 +231,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam_Optional.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam_Optional.generated.txt
index 3e4918ffd63d..757eb5f81f8d 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam_Optional.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam_Optional.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.String[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -230,6 +231,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam_Optional_QueryNotPresent.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam_Optional_QueryNotPresent.generated.txt
index 3e4918ffd63d..757eb5f81f8d 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam_Optional_QueryNotPresent.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitQuery_StringArrayParam_Optional_QueryNotPresent.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.String[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -230,6 +231,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 a82fa6fb9baf..2e18c631a26a 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
@@ -439,6 +439,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 794413cb79a9..3663350edf78 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
@@ -606,6 +606,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 948327f881b7..07e79ab29820 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
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -266,6 +267,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_IntArrayParam_Optional.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_IntArrayParam_Optional.generated.txt
index 682208c08c8c..e51b39e6f806 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_IntArrayParam_Optional.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_IntArrayParam_Optional.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -266,6 +267,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_IntArrayParam_Optional_QueryNotPresent.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_IntArrayParam_Optional_QueryNotPresent.generated.txt
index 682208c08c8c..e51b39e6f806 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_IntArrayParam_Optional_QueryNotPresent.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_IntArrayParam_Optional_QueryNotPresent.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -266,6 +267,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableIntArrayParam_Optional.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableIntArrayParam_Optional.generated.txt
index 82e1993b1b45..2e4b0d343e08 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableIntArrayParam_Optional.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableIntArrayParam_Optional.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32?[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -266,6 +267,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableIntArrayParam_Optional_QueryNotPresent.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableIntArrayParam_Optional_QueryNotPresent.generated.txt
index 82e1993b1b45..2e4b0d343e08 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableIntArrayParam_Optional_QueryNotPresent.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_NullableIntArrayParam_Optional_QueryNotPresent.generated.txt
@@ -72,6 +72,7 @@ namespace Microsoft.AspNetCore.Http.Generated
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: true, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32?[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -266,6 +267,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 af6f3f0d1c17..857501669994 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
@@ -81,12 +81,14 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -327,6 +329,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 af6f3f0d1c17..857501669994 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
@@ -81,12 +81,14 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -327,6 +329,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 af6f3f0d1c17..857501669994 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
@@ -81,12 +81,14 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -327,6 +329,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 3d2c9a682319..9c1fe26e5902 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
@@ -81,12 +81,14 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -327,6 +329,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam_Optional.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam_Optional.generated.txt
index 5e6adff6d906..65ddf7109200 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam_Optional.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam_Optional.generated.txt
@@ -81,12 +81,14 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.String[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -327,6 +329,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam_Optional_QueryNotPresent.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam_Optional_QueryNotPresent.generated.txt
index 5e6adff6d906..65ddf7109200 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam_Optional_QueryNotPresent.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ImplicitQuery_StringArrayParam_Optional_QueryNotPresent.generated.txt
@@ -81,12 +81,14 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: true));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.String[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -327,6 +329,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 9a7acd7eb45f..bc9c6a59d734 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
@@ -82,6 +82,7 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
@@ -345,6 +346,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 8ac1c767314e..560f0ec1f94a 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
@@ -234,6 +234,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 139a5739a234..0c26ae021468 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
@@ -267,6 +267,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 ae38db998901..18cf2ce8010b 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
@@ -225,6 +225,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 ae38db998901..18cf2ce8010b 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
@@ -225,6 +225,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ReturnsTodo_Has_Metadata.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ReturnsTodo_Has_Metadata.generated.txt
index f1a99f9eb04b..808d55a96981 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ReturnsTodo_Has_Metadata.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ReturnsTodo_Has_Metadata.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 ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::Microsoft.AspNetCore.Http.Generators.Tests.Todo), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -218,6 +219,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 dd910316c8f7..509930131549 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
@@ -266,6 +266,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 e37a0fa0f25e..b1b71f8eecd5 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
@@ -266,6 +266,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 773c77bc8d20..b56621cb8c50 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
@@ -238,6 +238,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 839b8eaa9374..72e03e06b74e 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
@@ -81,6 +81,7 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
@@ -333,6 +334,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 0daff798796f..7409065d2ce6 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
@@ -81,6 +81,7 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
@@ -334,6 +335,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 0daff798796f..7409065d2ce6 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
@@ -81,6 +81,7 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
@@ -334,6 +335,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 0daff798796f..7409065d2ce6 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
@@ -81,6 +81,7 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
@@ -334,6 +335,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 0daff798796f..7409065d2ce6 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
@@ -81,6 +81,7 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
@@ -334,6 +335,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 8a2bc539262c..3fb5a66501a7 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
@@ -81,6 +81,7 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
@@ -334,6 +335,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 379c78383b45..f34ec56593e5 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
@@ -81,12 +81,14 @@ namespace Microsoft.AspNetCore.Http.Generated
if (!serviceProviderIsService.IsService(type))
{
options.EndpointBuilder.Metadata.Add(new AcceptsMetadata(type: type, isOptional: isOptional, contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
break;
}
}
var parameters = methodInfo.GetParameters();
options.EndpointBuilder.Metadata.Add(new ParameterBindingMetadata("p", parameters[0], hasTryParse: false, hasBindAsync: false, isOptional: false));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::System.Int32), contentTypes: GeneratedMetadataConstants.JsonContentType));
+ ApiEndpointMetadata.AddApiEndpointMetadataIfMissing(options.EndpointBuilder);
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
@@ -327,6 +329,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 79567d9d3a09..bf51a39927f5 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
@@ -414,6 +414,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 38e13d3e6d53..ffb90a91f7fc 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
@@ -428,6 +428,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 905324b900eb..8119c31870ea 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/RequestDelegateValidateGeneratedFormCode.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/RequestDelegateValidateGeneratedFormCode.generated.txt
@@ -373,17 +373,17 @@ namespace Microsoft.AspNetCore.Http.Generated
}
-file sealed class AntiforgeryMetadata : IAntiforgeryMetadata
-{
- public static readonly IAntiforgeryMetadata ValidationRequired = new AntiforgeryMetadata(true);
-
- public AntiforgeryMetadata(bool requiresValidation)
+ file sealed class AntiforgeryMetadata : IAntiforgeryMetadata
{
- RequiresValidation = requiresValidation;
- }
+ public static readonly IAntiforgeryMetadata ValidationRequired = new AntiforgeryMetadata(true);
- public bool RequiresValidation { get; }
-}
+ public AntiforgeryMetadata(bool requiresValidation)
+ {
+ RequiresValidation = requiresValidation;
+ }
+
+ public bool RequiresValidation { get; }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 5316ad22d597..fea0e359a92f 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsDifferentInterceptorsFromSameLocation.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsDifferentInterceptorsFromSameLocation.generated.txt
@@ -388,6 +388,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 aad88a30d271..cafc9280c930 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsSameInterceptorsFromDifferentFiles.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/SupportsSameInterceptorsFromDifferentFiles.generated.txt
@@ -257,6 +257,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
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 30b4541a6f49..489a8b16b73a 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/VerifyAsParametersBaseline.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/VerifyAsParametersBaseline.generated.txt
@@ -446,6 +446,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(contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
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));
@@ -567,6 +568,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(contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
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();
@@ -683,6 +685,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(contentTypes: GeneratedMetadataConstants.JsonContentType));
+ options.EndpointBuilder.Metadata.Add(ApiEndpointMetadata.Instance);
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));
@@ -966,6 +969,22 @@ namespace Microsoft.AspNetCore.Http.Generated
}
+ file sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static readonly ApiEndpointMetadata Instance = new();
+
+ private ApiEndpointMetadata()
+ {
+ }
+
+ public static void AddApiEndpointMetadataIfMissing(EndpointBuilder builder)
+ {
+ if (!builder.Metadata.Any(m => m is IApiEndpointMetadata))
+ {
+ builder.Metadata.Add(Instance);
+ }
+ }
+ }
%GENERATEDCODEATTRIBUTE%
file static class GeneratedMetadataConstants
{
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Metadata.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Metadata.cs
index 68f0af004651..1f3412e54391 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Metadata.cs
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Metadata.cs
@@ -83,17 +83,14 @@ public async Task MapAction_ReturnsTaskOfString_Has_Metadata()
}
[Fact]
- public async Task MapAction_ReturnsTask_ProducesInferredMetadata()
+ public async Task MapAction_ReturnsTask_ProducesNoInferredProducesResponseTypeMetadata()
{
var (_, compilation) = await RunGeneratorAsync("""
app.MapGet("/", Task () => Task.CompletedTask);
""");
var endpoint = GetEndpointFromCompilation(compilation);
- var metadata = endpoint.Metadata.OfType().Single();
- Assert.Equal(200, metadata.StatusCode);
- Assert.Equal("text/plain", metadata.ContentTypes.Single());
- Assert.Equal(typeof(void), metadata.Type);
+ Assert.Empty(endpoint.Metadata.OfType());
}
[Fact]
@@ -111,17 +108,14 @@ public async Task MapAction_ReturnsValueTaskOfString_Has_Metadata()
}
[Fact]
- public async Task MapAction_ReturnsValueTask_ProducesInferredMetadata()
+ public async Task MapAction_ReturnsValueTask_ProducesNoInferredProducesResponseTypeMetadata()
{
var (_, compilation) = await RunGeneratorAsync("""
app.MapGet("/", ValueTask () => ValueTask.CompletedTask);
""");
var endpoint = GetEndpointFromCompilation(compilation);
- var metadata = endpoint.Metadata.OfType().Single();
- Assert.Equal(200, metadata.StatusCode);
- Assert.Equal("text/plain", metadata.ContentTypes.Single());
- Assert.Equal(typeof(void), metadata.Type);
+ Assert.Empty(endpoint.Metadata.OfType());
}
[Fact]
@@ -512,6 +506,11 @@ public async Task InferMetadata_ThenCreate_CombinesAllMetadata_InCorrectOrder()
// Act
var endpoint = GetEndpointFromCompilation(compilation);
+ // IApiEndpointMetadata is tricky to order consistently because it depends on whether AddsCustomParameterMetadata is registered
+ // as a service at runtime. However, the order of IApiEndpointMetadata is not significant since there's no way to override it
+ // other than removing it.
+ Assert.Single(endpoint.Metadata, m => m is IApiEndpointMetadata);
+
// Assert
// NOTE: Depending on whether we are running under RDG or RDG, there are some generated types which
// don't have equivalents in the opposite. The two examples here are NullableContextAttribute which
@@ -525,7 +524,8 @@ m is not MethodInfo &&
m is not HttpMethodMetadata &&
m is not Attribute1 &&
m is not Attribute2 &&
- m is not IRouteDiagnosticsMetadata);
+ m is not IRouteDiagnosticsMetadata &&
+ m is not IApiEndpointMetadata);
Assert.Collection(filteredMetadata,
// Inferred AcceptsMetadata from RDF for complex type
diff --git a/src/Http/Http.Results/src/Accepted.cs b/src/Http/Http.Results/src/Accepted.cs
index 5dbc56987c4c..d71fe9072c7e 100644
--- a/src/Http/Http.Results/src/Accepted.cs
+++ b/src/Http/Http.Results/src/Accepted.cs
@@ -82,5 +82,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status202Accepted, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/AcceptedAtRoute.cs b/src/Http/Http.Results/src/AcceptedAtRoute.cs
index 7472559549da..900ee507d9cf 100644
--- a/src/Http/Http.Results/src/AcceptedAtRoute.cs
+++ b/src/Http/Http.Results/src/AcceptedAtRoute.cs
@@ -109,5 +109,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status202Accepted, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/AcceptedAtRouteOfT.cs b/src/Http/Http.Results/src/AcceptedAtRouteOfT.cs
index e9467dbe1e54..b8e4304a7237 100644
--- a/src/Http/Http.Results/src/AcceptedAtRouteOfT.cs
+++ b/src/Http/Http.Results/src/AcceptedAtRouteOfT.cs
@@ -123,5 +123,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status202Accepted, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/AcceptedOfT.cs b/src/Http/Http.Results/src/AcceptedOfT.cs
index 6777d3549d58..346070714b43 100644
--- a/src/Http/Http.Results/src/AcceptedOfT.cs
+++ b/src/Http/Http.Results/src/AcceptedOfT.cs
@@ -101,5 +101,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status202Accepted, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/BadRequest.cs b/src/Http/Http.Results/src/BadRequest.cs
index 9eef74aa41c2..0356afedc2c7 100644
--- a/src/Http/Http.Results/src/BadRequest.cs
+++ b/src/Http/Http.Results/src/BadRequest.cs
@@ -52,5 +52,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status400BadRequest, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/BadRequestOfT.cs b/src/Http/Http.Results/src/BadRequestOfT.cs
index 4b932786eb3b..b8fa51423d7e 100644
--- a/src/Http/Http.Results/src/BadRequestOfT.cs
+++ b/src/Http/Http.Results/src/BadRequestOfT.cs
@@ -66,5 +66,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status400BadRequest, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/Conflict.cs b/src/Http/Http.Results/src/Conflict.cs
index da162ed5d207..f0067ba4aea1 100644
--- a/src/Http/Http.Results/src/Conflict.cs
+++ b/src/Http/Http.Results/src/Conflict.cs
@@ -52,5 +52,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status409Conflict, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/ConflictOfT.cs b/src/Http/Http.Results/src/ConflictOfT.cs
index bbfb3c6a503e..dda54d9dd5cc 100644
--- a/src/Http/Http.Results/src/ConflictOfT.cs
+++ b/src/Http/Http.Results/src/ConflictOfT.cs
@@ -66,5 +66,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status409Conflict, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/Created.cs b/src/Http/Http.Results/src/Created.cs
index 7766d91a6f46..1959556280c9 100644
--- a/src/Http/Http.Results/src/Created.cs
+++ b/src/Http/Http.Results/src/Created.cs
@@ -82,5 +82,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status201Created, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/CreatedAtRoute.cs b/src/Http/Http.Results/src/CreatedAtRoute.cs
index 2fb70fa23b16..2ff79596ba36 100644
--- a/src/Http/Http.Results/src/CreatedAtRoute.cs
+++ b/src/Http/Http.Results/src/CreatedAtRoute.cs
@@ -109,5 +109,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status201Created, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/CreatedAtRouteOfT.cs b/src/Http/Http.Results/src/CreatedAtRouteOfT.cs
index d13d6154413b..a2868afdc0a1 100644
--- a/src/Http/Http.Results/src/CreatedAtRouteOfT.cs
+++ b/src/Http/Http.Results/src/CreatedAtRouteOfT.cs
@@ -126,5 +126,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status201Created, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/CreatedOfT.cs b/src/Http/Http.Results/src/CreatedOfT.cs
index 58d0638b218d..a12e52b9f69f 100644
--- a/src/Http/Http.Results/src/CreatedOfT.cs
+++ b/src/Http/Http.Results/src/CreatedOfT.cs
@@ -100,5 +100,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status201Created, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/InternalServerErrorOfT.cs b/src/Http/Http.Results/src/InternalServerErrorOfT.cs
index 36ec9fed9512..c726debf67c0 100644
--- a/src/Http/Http.Results/src/InternalServerErrorOfT.cs
+++ b/src/Http/Http.Results/src/InternalServerErrorOfT.cs
@@ -66,5 +66,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status500InternalServerError, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/JsonHttpResultOfT.cs b/src/Http/Http.Results/src/JsonHttpResultOfT.cs
index 4841e675ecfd..fea230609a20 100644
--- a/src/Http/Http.Results/src/JsonHttpResultOfT.cs
+++ b/src/Http/Http.Results/src/JsonHttpResultOfT.cs
@@ -2,8 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -13,7 +16,7 @@ namespace Microsoft.AspNetCore.Http.HttpResults;
///
/// An action result which formats the given object as JSON.
///
-public sealed partial class JsonHttpResult : IResult, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult, IContentTypeHttpResult
+public sealed partial class JsonHttpResult : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IValueHttpResult, IValueHttpResult, IContentTypeHttpResult
{
///
/// Initializes a new instance of the class with the values.
@@ -117,7 +120,7 @@ public Task ExecuteAsync(HttpContext httpContext)
typedJsonTypeInfo,
contentType: ContentType);
}
-
+
return httpContext.Response.WriteAsJsonAsync(
Value,
JsonTypeInfo,
@@ -131,4 +134,9 @@ public Task ExecuteAsync(HttpContext httpContext)
ContentType,
JsonSerializerOptions);
}
+
+ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, EndpointBuilder builder)
+ {
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
+ }
}
diff --git a/src/Http/Http.Results/src/NoContent.cs b/src/Http/Http.Results/src/NoContent.cs
index 987a06fc4eee..35ffb3c56701 100644
--- a/src/Http/Http.Results/src/NoContent.cs
+++ b/src/Http/Http.Results/src/NoContent.cs
@@ -52,5 +52,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status204NoContent, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/NotFoundOfT.cs b/src/Http/Http.Results/src/NotFoundOfT.cs
index ad9c3a1032eb..d37a4ee9707c 100644
--- a/src/Http/Http.Results/src/NotFoundOfT.cs
+++ b/src/Http/Http.Results/src/NotFoundOfT.cs
@@ -65,5 +65,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status404NotFound, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/Ok.cs b/src/Http/Http.Results/src/Ok.cs
index 0db060d4e6d4..837a0fa7513c 100644
--- a/src/Http/Http.Results/src/Ok.cs
+++ b/src/Http/Http.Results/src/Ok.cs
@@ -51,5 +51,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status200OK, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/OkOfT.cs b/src/Http/Http.Results/src/OkOfT.cs
index 108674fdc2ac..7f19598effe9 100644
--- a/src/Http/Http.Results/src/OkOfT.cs
+++ b/src/Http/Http.Results/src/OkOfT.cs
@@ -65,5 +65,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status200OK, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/ProblemHttpResult.cs b/src/Http/Http.Results/src/ProblemHttpResult.cs
index 4fe63c4277cc..8ac29336f053 100644
--- a/src/Http/Http.Results/src/ProblemHttpResult.cs
+++ b/src/Http/Http.Results/src/ProblemHttpResult.cs
@@ -4,6 +4,9 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using System.Reflection;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http.Metadata;
namespace Microsoft.AspNetCore.Http.HttpResults;
@@ -11,7 +14,7 @@ namespace Microsoft.AspNetCore.Http.HttpResults;
/// An that on execution will write Problem Details
/// HTTP API responses based on
///
-public sealed class ProblemHttpResult : IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult, IValueHttpResult
+public sealed class ProblemHttpResult : IResult, IEndpointMetadataProvider, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult, IValueHttpResult
{
///
/// Creates a new instance with
@@ -69,4 +72,13 @@ await HttpResultsHelper.WriteResultAsJsonAsync(
ContentType);
}
}
+
+ ///
+ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, EndpointBuilder builder)
+ {
+ ArgumentNullException.ThrowIfNull(method);
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
+ }
}
diff --git a/src/Http/Http.Results/src/ServerSentEventsResult.cs b/src/Http/Http.Results/src/ServerSentEventsResult.cs
index 448b2076daa6..a7951acd1554 100644
--- a/src/Http/Http.Results/src/ServerSentEventsResult.cs
+++ b/src/Http/Http.Results/src/ServerSentEventsResult.cs
@@ -105,5 +105,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status200OK, typeof(SseItem), contentTypes: ["text/event-stream"]));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/UnprocessableEntity.cs b/src/Http/Http.Results/src/UnprocessableEntity.cs
index eef96dc9f513..49d3982720b8 100644
--- a/src/Http/Http.Results/src/UnprocessableEntity.cs
+++ b/src/Http/Http.Results/src/UnprocessableEntity.cs
@@ -52,5 +52,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(new ProducesResponseTypeMetadata(StatusCodes.Status422UnprocessableEntity, typeof(void)));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/UnprocessableEntityOfT.cs b/src/Http/Http.Results/src/UnprocessableEntityOfT.cs
index 475a0bc3ad2c..2d1ee494a271 100644
--- a/src/Http/Http.Results/src/UnprocessableEntityOfT.cs
+++ b/src/Http/Http.Results/src/UnprocessableEntityOfT.cs
@@ -66,5 +66,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(TValue), StatusCodes.Status422UnprocessableEntity, ContentTypeConstants.ApplicationJsonContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/src/ValidationProblem.cs b/src/Http/Http.Results/src/ValidationProblem.cs
index ba738cfbcf3e..c4a539c9cd5f 100644
--- a/src/Http/Http.Results/src/ValidationProblem.cs
+++ b/src/Http/Http.Results/src/ValidationProblem.cs
@@ -77,5 +77,6 @@ static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, Endpoi
ArgumentNullException.ThrowIfNull(builder);
builder.Metadata.Add(ProducesResponseTypeMetadata.CreateUnvalidated(typeof(HttpValidationProblemDetails), StatusCodes.Status400BadRequest, ContentTypeConstants.ProblemDetailsContentTypes));
+ builder.Metadata.Add(ApiEndpointMetadata.Instance);
}
}
diff --git a/src/Http/Http.Results/test/AcceptedAtRouteOfTResultTests.cs b/src/Http/Http.Results/test/AcceptedAtRouteOfTResultTests.cs
index 47b1569390d4..1d53452fa65e 100644
--- a/src/Http/Http.Results/test/AcceptedAtRouteOfTResultTests.cs
+++ b/src/Http/Http.Results/test/AcceptedAtRouteOfTResultTests.cs
@@ -134,6 +134,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
Assert.Equal(StatusCodes.Status202Accepted, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(Todo), producesResponseTypeMetadata.Type);
Assert.Single(producesResponseTypeMetadata.ContentTypes, "application/json");
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/AcceptedAtRouteResultTests.cs b/src/Http/Http.Results/test/AcceptedAtRouteResultTests.cs
index 8f29f5a51344..15a93310e80c 100644
--- a/src/Http/Http.Results/test/AcceptedAtRouteResultTests.cs
+++ b/src/Http/Http.Results/test/AcceptedAtRouteResultTests.cs
@@ -87,6 +87,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
var producesResponseTypeMetadata = builder.Metadata.OfType().Last();
Assert.Equal(StatusCodes.Status202Accepted, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(void), producesResponseTypeMetadata.Type);
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/AcceptedOfTResultTests.cs b/src/Http/Http.Results/test/AcceptedOfTResultTests.cs
index 853a57d4704f..2ee6e03193d4 100644
--- a/src/Http/Http.Results/test/AcceptedOfTResultTests.cs
+++ b/src/Http/Http.Results/test/AcceptedOfTResultTests.cs
@@ -75,6 +75,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
Assert.Equal(StatusCodes.Status202Accepted, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(Todo), producesResponseTypeMetadata.Type);
Assert.Single(producesResponseTypeMetadata.ContentTypes, "application/json");
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/AcceptedResultTests.cs b/src/Http/Http.Results/test/AcceptedResultTests.cs
index 7511b05fa249..171b45112174 100644
--- a/src/Http/Http.Results/test/AcceptedResultTests.cs
+++ b/src/Http/Http.Results/test/AcceptedResultTests.cs
@@ -44,6 +44,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
var producesResponseTypeMetadata = builder.Metadata.OfType().Last();
Assert.Equal(StatusCodes.Status202Accepted, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(void), producesResponseTypeMetadata.Type);
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/BadRequestOfTResultTests.cs b/src/Http/Http.Results/test/BadRequestOfTResultTests.cs
index 58e1e452e399..c930db6ea80a 100644
--- a/src/Http/Http.Results/test/BadRequestOfTResultTests.cs
+++ b/src/Http/Http.Results/test/BadRequestOfTResultTests.cs
@@ -118,6 +118,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
Assert.Equal(StatusCodes.Status400BadRequest, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(Todo), producesResponseTypeMetadata.Type);
Assert.Single(producesResponseTypeMetadata.ContentTypes, "application/json");
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/BadRequestResultTests.cs b/src/Http/Http.Results/test/BadRequestResultTests.cs
index e8f3a444de05..cca2a4d139ee 100644
--- a/src/Http/Http.Results/test/BadRequestResultTests.cs
+++ b/src/Http/Http.Results/test/BadRequestResultTests.cs
@@ -57,6 +57,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
var producesResponseTypeMetadata = builder.Metadata.OfType().Last();
Assert.Equal(StatusCodes.Status400BadRequest, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(void), producesResponseTypeMetadata.Type);
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/ConflictOfTResultTests.cs b/src/Http/Http.Results/test/ConflictOfTResultTests.cs
index 5e757e3b191c..be4e43d441df 100644
--- a/src/Http/Http.Results/test/ConflictOfTResultTests.cs
+++ b/src/Http/Http.Results/test/ConflictOfTResultTests.cs
@@ -96,6 +96,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
Assert.Equal(StatusCodes.Status409Conflict, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(Todo), producesResponseTypeMetadata.Type);
Assert.Single(producesResponseTypeMetadata.ContentTypes, "application/json");
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/ConflictResultTests.cs b/src/Http/Http.Results/test/ConflictResultTests.cs
index 88f64740aaea..2f639948eac6 100644
--- a/src/Http/Http.Results/test/ConflictResultTests.cs
+++ b/src/Http/Http.Results/test/ConflictResultTests.cs
@@ -58,6 +58,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
var producesResponseTypeMetadata = builder.Metadata.OfType().Last();
Assert.Equal(StatusCodes.Status409Conflict, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(void), producesResponseTypeMetadata.Type);
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/CreatedAtRouteOfTResultTests.cs b/src/Http/Http.Results/test/CreatedAtRouteOfTResultTests.cs
index dec5f3ceafbd..a55f7dd6ef9c 100644
--- a/src/Http/Http.Results/test/CreatedAtRouteOfTResultTests.cs
+++ b/src/Http/Http.Results/test/CreatedAtRouteOfTResultTests.cs
@@ -104,6 +104,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
Assert.Equal(StatusCodes.Status201Created, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(Todo), producesResponseTypeMetadata.Type);
Assert.Single(producesResponseTypeMetadata.ContentTypes, "application/json");
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/CreatedAtRouteResultTests.cs b/src/Http/Http.Results/test/CreatedAtRouteResultTests.cs
index e91822afc79a..5a36fdcce055 100644
--- a/src/Http/Http.Results/test/CreatedAtRouteResultTests.cs
+++ b/src/Http/Http.Results/test/CreatedAtRouteResultTests.cs
@@ -85,6 +85,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
var producesResponseTypeMetadata = builder.Metadata.OfType().Last();
Assert.Equal(StatusCodes.Status201Created, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(void), producesResponseTypeMetadata.Type);
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/CreatedOfTResultTests.cs b/src/Http/Http.Results/test/CreatedOfTResultTests.cs
index 9e5f0637058c..b4b5747745a1 100644
--- a/src/Http/Http.Results/test/CreatedOfTResultTests.cs
+++ b/src/Http/Http.Results/test/CreatedOfTResultTests.cs
@@ -110,6 +110,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
Assert.Equal(StatusCodes.Status201Created, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(Todo), producesResponseTypeMetadata.Type);
Assert.Single(producesResponseTypeMetadata.ContentTypes, "application/json");
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/CreatedResultTests.cs b/src/Http/Http.Results/test/CreatedResultTests.cs
index 21b678d39301..af1c8a1179b8 100644
--- a/src/Http/Http.Results/test/CreatedResultTests.cs
+++ b/src/Http/Http.Results/test/CreatedResultTests.cs
@@ -75,6 +75,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
var producesResponseTypeMetadata = builder.Metadata.OfType().Last();
Assert.Equal(StatusCodes.Status201Created, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(void), producesResponseTypeMetadata.Type);
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/InternalServerErrorOfTResultTests.cs b/src/Http/Http.Results/test/InternalServerErrorOfTResultTests.cs
index d063b4e66a11..1ee5bd751053 100644
--- a/src/Http/Http.Results/test/InternalServerErrorOfTResultTests.cs
+++ b/src/Http/Http.Results/test/InternalServerErrorOfTResultTests.cs
@@ -118,6 +118,8 @@ public void PopulateMetadata_AddsResponseTypeMetadata()
Assert.Equal(StatusCodes.Status500InternalServerError, producesResponseTypeMetadata.StatusCode);
Assert.Equal(typeof(Todo), producesResponseTypeMetadata.Type);
Assert.Single(producesResponseTypeMetadata.ContentTypes, "application/json");
+
+ Assert.Contains(builder.Metadata, m => m is IApiEndpointMetadata);
}
[Fact]
diff --git a/src/Http/Http.Results/test/JsonResultTests.cs b/src/Http/Http.Results/test/JsonResultTests.cs
index 1c2d6d7fb225..52d76c0a03c9 100644
--- a/src/Http/Http.Results/test/JsonResultTests.cs
+++ b/src/Http/Http.Results/test/JsonResultTests.cs
@@ -1,11 +1,16 @@
// 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;
using System.Text;
using System.Text.Json;
using System.Text.Unicode;
+using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http.Json;
+using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@@ -310,6 +315,24 @@ public void JsonResult_Implements_IValueHttpResultOfT_Correctly()
Assert.Equal(value, result.Value);
}
+ [Fact]
+ public void PopulateMetadata_AddsNonBrowserEndpointMetadata()
+ {
+ // Arrange
+ JsonHttpResult MyApi() { throw new NotImplementedException(); }
+ var metadata = new List
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
-public class ApiControllerAttribute : ControllerAttribute, IApiBehaviorMetadata
+public class ApiControllerAttribute : ControllerAttribute, IApiBehaviorMetadata, IApiEndpointMetadata
{
}
diff --git a/src/Mvc/Mvc.Core/test/ApplicationModels/DefaultApplicationModelProviderTest.cs b/src/Mvc/Mvc.Core/test/ApplicationModels/DefaultApplicationModelProviderTest.cs
index 19aea8a971b2..c8c6368fe7e8 100644
--- a/src/Mvc/Mvc.Core/test/ApplicationModels/DefaultApplicationModelProviderTest.cs
+++ b/src/Mvc/Mvc.Core/test/ApplicationModels/DefaultApplicationModelProviderTest.cs
@@ -3,6 +3,7 @@
using System.Reflection;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
@@ -1277,8 +1278,9 @@ public void AddReturnTypeMetadata_ExtractsMetadataFromReturnType()
// Assert
Assert.NotNull(selector.EndpointMetadata);
- Assert.Single(selector.EndpointMetadata);
- Assert.IsType(selector.EndpointMetadata.Single());
+ Assert.Equal(2, selector.EndpointMetadata.Count);
+ Assert.Single(selector.EndpointMetadata.OfType());
+ Assert.Single(selector.EndpointMetadata.OfType());
Assert.Equal(200, ((ProducesResponseTypeMetadata)selector.EndpointMetadata[0]).StatusCode);
}
diff --git a/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs b/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs
index be47982a28dd..994d999aaf52 100644
--- a/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs
+++ b/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Authentication.Cookies;
@@ -41,7 +42,7 @@ public class CookieAuthenticationEvents
///
public Func, Task> OnRedirectToLogin { get; set; } = context =>
{
- if (IsAjaxRequest(context.Request))
+ if (IsAjaxRequest(context.Request) || IsApiEndpoint(context.HttpContext))
{
context.Response.Headers.Location = context.RedirectUri;
context.Response.StatusCode = 401;
@@ -58,7 +59,7 @@ public class CookieAuthenticationEvents
///
public Func, Task> OnRedirectToAccessDenied { get; set; } = context =>
{
- if (IsAjaxRequest(context.Request))
+ if (IsAjaxRequest(context.Request) || IsApiEndpoint(context.HttpContext))
{
context.Response.Headers.Location = context.RedirectUri;
context.Response.StatusCode = 403;
@@ -108,6 +109,12 @@ private static bool IsAjaxRequest(HttpRequest request)
string.Equals(request.Headers.XRequestedWith, "XMLHttpRequest", StringComparison.Ordinal);
}
+ private static bool IsApiEndpoint(HttpContext context)
+ {
+ var endpoint = context.GetEndpoint();
+ return endpoint?.Metadata.GetMetadata() is not null;
+ }
+
///
/// Invoked to validate the principal.
///
diff --git a/src/Security/Authentication/test/CookieTests.cs b/src/Security/Authentication/test/CookieTests.cs
index cb65ba5a6bae..3dc0d638b8cf 100644
--- a/src/Security/Authentication/test/CookieTests.cs
+++ b/src/Security/Authentication/test/CookieTests.cs
@@ -11,6 +11,7 @@
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.AspNetCore.TestHost;
using Microsoft.AspNetCore.InternalTesting;
using Microsoft.Extensions.DependencyInjection;
@@ -96,6 +97,30 @@ public async Task AjaxChallengeRedirectTurnsInto200WithLocationHeader()
Assert.StartsWith("http://example.com/Account/Login", responded.Single());
}
+ [Fact]
+ public async Task ApiEndpointChallengeReturns401WithLocationHeader()
+ {
+ using var host = await CreateHost(s => { });
+ using var server = host.GetTestServer();
+ var transaction = await SendAsync(server, "http://example.com/api/challenge");
+ Assert.Equal(HttpStatusCode.Unauthorized, transaction.Response.StatusCode);
+ var responded = transaction.Response.Headers.GetValues("Location");
+ Assert.Single(responded);
+ Assert.StartsWith("http://example.com/Account/Login", responded.Single());
+ }
+
+ [Fact]
+ public async Task ApiEndpointForbidReturns403WithLocationHeader()
+ {
+ using var host = await CreateHost(s => { });
+ using var server = host.GetTestServer();
+ var transaction = await SendAsync(server, "http://example.com/api/forbid");
+ Assert.Equal(HttpStatusCode.Forbidden, transaction.Response.StatusCode);
+ var responded = transaction.Response.Headers.GetValues("Location");
+ Assert.Single(responded);
+ Assert.StartsWith("http://example.com/Account/AccessDenied", responded.Single());
+ }
+
[Fact]
public async Task ProtectedCustomRequestShouldRedirectToCustomRedirectUri()
{
@@ -1879,8 +1904,28 @@ private static async Task CreateHostWithServices(Action
+ {
+ var apiRouteGroup = endpoints.MapGroup("/api").WithMetadata(new TestApiEndpointMetadata());
+ // Add endpoints with IApiEndpointMetadata
+ apiRouteGroup.MapGet("/challenge", async context =>
+ {
+ await context.ChallengeAsync(CookieAuthenticationDefaults.AuthenticationScheme);
+ });
+
+ apiRouteGroup.MapGet("/forbid", async context =>
+ {
+ await context.ForbidAsync(CookieAuthenticationDefaults.AuthenticationScheme);
+ });
+ });
})
- .ConfigureServices(configureServices))
+ .ConfigureServices(services =>
+ {
+ services.AddRoutingCore();
+ configureServices(services);
+ }))
.Build();
await host.StartAsync();
@@ -1949,4 +1994,8 @@ private class Transaction
public string ResponseText { get; set; }
public XElement ResponseElement { get; set; }
}
+
+ private class TestApiEndpointMetadata : IApiEndpointMetadata
+ {
+ }
}
diff --git a/src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs b/src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs
index 8ed01395df6c..f1aad8649e82 100644
--- a/src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs
+++ b/src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs
@@ -5,6 +5,7 @@
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.AspNetCore.Http.Connections.Internal;
+using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.AspNetCore.Http.Timeouts;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
@@ -125,6 +126,9 @@ public static ConnectionEndpointRouteBuilder MapConnections(this IEndpointRouteB
{
e.Metadata.Add(data);
}
+
+ // Add IApiEndpointMetadata to indicate this is a non-browser endpoint (SignalR)
+ e.Metadata.Add(ApiEndpointMetadata.Instance);
});
return new ConnectionEndpointRouteBuilder(compositeConventionBuilder);
@@ -155,4 +159,9 @@ public void Finally(Action finalConvention)
}
}
}
+
+ private sealed class ApiEndpointMetadata : IApiEndpointMetadata
+ {
+ public static ApiEndpointMetadata Instance { get; } = new();
+ }
}