Skip to content

Commit be5a2ac

Browse files
authored
Fixing failing tests and address feedback
1 parent c981930 commit be5a2ac

File tree

5 files changed

+34
-23
lines changed

5 files changed

+34
-23
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#nullable enable
22
Microsoft.Extensions.DependencyInjection.RouteHandlerJsonServiceExtensions
33
static Microsoft.Extensions.DependencyInjection.RouteHandlerJsonServiceExtensions.ConfigureRouteHandlerJsonOptions(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<Microsoft.AspNetCore.Http.Json.JsonOptions!>! configureOptions) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
4-
Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions.RouteHandlerFilters.get -> System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.IRouteHandlerFilter!>?
4+
Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions.RouteHandlerFilters.get -> System.Collections.Generic.IReadOnlyList<Microsoft.AspNetCore.Http.IRouteHandlerFilter!>?
55
Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions.RouteHandlerFilters.init -> void

src/Http/Http.Extensions/src/RequestDelegateFactory.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public static partial class RequestDelegateFactory
7979
private static readonly BinaryExpression TempSourceStringNullExpr = Expression.Equal(TempSourceStringExpr, Expression.Constant(null));
8080
private static readonly UnaryExpression TempSourceStringIsNotNullOrEmptyExpr = Expression.Not(Expression.Call(StringIsNullOrEmptyMethod, TempSourceStringExpr));
8181

82-
private static readonly ConstructorInfo RouteHandlerFilterContextConstructor = typeof(RouteHandlerFilterContext).GetConstructors().Single();
82+
private static readonly ConstructorInfo RouteHandlerFilterContextConstructor = typeof(RouteHandlerFilterContext).GetConstructor(new[] { typeof(HttpContext), typeof(object[]) })!;
8383
private static readonly ParameterExpression FilterContextExpr = Expression.Parameter(typeof(RouteHandlerFilterContext), "context");
8484
private static readonly MemberExpression FilterContextParametersExpr = Expression.Property(FilterContextExpr, typeof(RouteHandlerFilterContext).GetProperty(nameof(RouteHandlerFilterContext.Parameters))!);
8585
private static readonly MemberExpression FilterContextHttpContextExpr = Expression.Property(FilterContextExpr, typeof(RouteHandlerFilterContext).GetProperty(nameof(RouteHandlerFilterContext.HttpContext))!);
@@ -224,6 +224,7 @@ private static FactoryContext CreateFactoryContext(RequestDelegateFactoryOptions
224224

225225
private static Func<RouteHandlerFilterContext, ValueTask<object?>> CreateFilterPipeline(MethodInfo methodInfo, Expression? target, FactoryContext factoryContext)
226226
{
227+
Debug.Assert(factoryContext.Filters is not null);
227228
// httpContext.Response.StatusCode == 400
228229
// ? Task.CompletedTask
229230
// : handler((string)context.Parameters[0], (int)context.Parameters[1])
@@ -240,7 +241,7 @@ target is null
240241
)),
241242
FilterContextExpr).Compile();
242243

243-
for (int i = factoryContext.Filters!.Count - 1; i >= 0; i--)
244+
for (var i = factoryContext.Filters.Count - 1; i >= 0; i--)
244245
{
245246
var currentFilter = factoryContext.Filters![i];
246247
var nextFilter = filteredInvocation;

src/Http/Http.Extensions/src/RequestDelegateFactoryOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,5 @@ public sealed class RequestDelegateFactoryOptions
3535
/// <summary>
3636
/// The list of filters that must run in the pipeline for a given route handler.
3737
/// </summary>
38-
public IEnumerable<IRouteHandlerFilter>? RouteHandlerFilters { get; init; }
38+
public IReadOnlyList<IRouteHandlerFilter>? RouteHandlerFilters { get; init; }
3939
}

src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -507,18 +507,6 @@ private static RouteHandlerBuilder Map(
507507
builder.DisplayName = $"{builder.DisplayName} => {endpointName}";
508508
}
509509

510-
// Add delegate attributes as metadata
511-
var attributes = handler.Method.GetCustomAttributes();
512-
513-
// This can be null if the delegate is a dynamic method or compiled from an expression tree
514-
if (attributes is not null)
515-
{
516-
foreach (var attribute in attributes)
517-
{
518-
builder.Metadata.Add(attribute);
519-
}
520-
}
521-
522510
var dataSource = endpoints.DataSources.OfType<ModelEndpointDataSource>().FirstOrDefault();
523511
if (dataSource is null)
524512
{
@@ -538,11 +526,24 @@ private static RouteHandlerBuilder Map(
538526
RouteHandlerFilters = routeHandlerBuilder.RouteHandlerFilters
539527
};
540528
var filteredRequestDelegateResult = RequestDelegateFactory.Create(handler, options);
541-
// Add add request delegate metadata
529+
// Add request delegate metadata
542530
foreach (var metadata in filteredRequestDelegateResult.EndpointMetadata)
543531
{
544532
endpointBuilder.Metadata.Add(metadata);
545533
}
534+
535+
// We add attributes on the handler after those automatically generated by the
536+
// RDF since they have a higher specificity.
537+
var attributes = handler.Method.GetCustomAttributes();
538+
539+
// This can be null if the delegate is a dynamic method or compiled from an expression tree
540+
if (attributes is not null)
541+
{
542+
foreach (var attribute in attributes)
543+
{
544+
endpointBuilder.Metadata.Add(attribute);
545+
}
546+
}
546547
endpointBuilder.RequestDelegate = filteredRequestDelegateResult.RequestDelegate;
547548
});
548549

src/Http/Routing/test/UnitTests/Builder/RouteHandlerEndpointRouteBuilderExtensionsTest.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,9 @@ public async Task MapGetWithoutRouteParameter_BuildsEndpointWithQuerySpecificBin
208208
public void MapGet_ThrowsWithImplicitFromBody()
209209
{
210210
var builder = new DefaultEndpointRouteBuilder(new ApplicationBuilder(new EmptyServiceProvider()));
211-
var ex = Assert.Throws<InvalidOperationException>(() => builder.MapGet("/", (Todo todo) => { }));
211+
_ = builder.MapGet("/", (Todo todo) => { });
212+
var dataSource = GetBuilderEndpointDataSource(builder);
213+
var ex = Assert.Throws<InvalidOperationException>(() => dataSource.Endpoints);
212214
Assert.Contains("Body was inferred but the method does not allow inferred body parameters.", ex.Message);
213215
Assert.Contains("Did you mean to register the \"Body (Inferred)\" parameter(s) as a Service or apply the [FromServices] or [FromBody] attribute?", ex.Message);
214216
}
@@ -217,7 +219,9 @@ public void MapGet_ThrowsWithImplicitFromBody()
217219
public void MapDelete_ThrowsWithImplicitFromBody()
218220
{
219221
var builder = new DefaultEndpointRouteBuilder(new ApplicationBuilder(new EmptyServiceProvider()));
220-
var ex = Assert.Throws<InvalidOperationException>(() => builder.MapDelete("/", (Todo todo) => { }));
222+
_ = builder.MapDelete("/", (Todo todo) => { });
223+
var dataSource = GetBuilderEndpointDataSource(builder);
224+
var ex = Assert.Throws<InvalidOperationException>(() => dataSource.Endpoints);
221225
Assert.Contains("Body was inferred but the method does not allow inferred body parameters.", ex.Message);
222226
Assert.Contains("Did you mean to register the \"Body (Inferred)\" parameter(s) as a Service or apply the [FromServices] or [FromBody] attribute?", ex.Message);
223227
}
@@ -243,7 +247,9 @@ public static object[][] NonImplicitFromBodyMethods
243247
public void MapVerb_ThrowsWithImplicitFromBody(string method)
244248
{
245249
var builder = new DefaultEndpointRouteBuilder(new ApplicationBuilder(new EmptyServiceProvider()));
246-
var ex = Assert.Throws<InvalidOperationException>(() => builder.MapMethods("/", new[] { method }, (Todo todo) => { }));
250+
_ = builder.MapMethods("/", new[] { method }, (Todo todo) => { });
251+
var dataSource = GetBuilderEndpointDataSource(builder);
252+
var ex = Assert.Throws<InvalidOperationException>(() => dataSource.Endpoints);
247253
Assert.Contains("Body was inferred but the method does not allow inferred body parameters.", ex.Message);
248254
Assert.Contains("Did you mean to register the \"Body (Inferred)\" parameter(s) as a Service or apply the [FromServices] or [FromBody] attribute?", ex.Message);
249255
}
@@ -581,7 +587,9 @@ public async Task MapVerbWithRouteParameterDoesNotFallbackToQuery(Func<IEndpoint
581587
public void MapGetWithRouteParameter_ThrowsIfRouteParameterDoesNotExist()
582588
{
583589
var builder = new DefaultEndpointRouteBuilder(new ApplicationBuilder(new EmptyServiceProvider()));
584-
var ex = Assert.Throws<InvalidOperationException>(() => builder.MapGet("/", ([FromRoute] int id) => { }));
590+
_ = builder.MapGet("/", ([FromRoute] int id) => { });
591+
var dataSource = GetBuilderEndpointDataSource(builder);
592+
var ex = Assert.Throws<InvalidOperationException>(() => dataSource.Endpoints);
585593
Assert.Equal("'id' is not a route parameter.", ex.Message);
586594
}
587595

@@ -637,7 +645,9 @@ public async Task MapGetWithNamedFromRouteParameter_FailsForParameterName()
637645
public void MapGetWithNamedFromRouteParameter_ThrowsForMismatchedPattern()
638646
{
639647
var builder = new DefaultEndpointRouteBuilder(new ApplicationBuilder(new EmptyServiceProvider()));
640-
var ex = Assert.Throws<InvalidOperationException>(() => builder.MapGet("/{id}", ([FromRoute(Name = "value")] int id, HttpContext httpContext) => { }));
648+
_ = builder.MapGet("/{id}", ([FromRoute(Name = "value")] int id, HttpContext httpContext) => { });
649+
var dataSource = GetBuilderEndpointDataSource(builder);
650+
var ex = Assert.Throws<InvalidOperationException>(() => dataSource.Endpoints);
641651
Assert.Equal("'value' is not a route parameter.", ex.Message);
642652
}
643653

@@ -677,7 +687,6 @@ public void MapPost_BuildsEndpointWithCorrectEndpointMetadata()
677687
Assert.False(endpointMetadata!.IsOptional);
678688
Assert.Equal(typeof(Todo), endpointMetadata.RequestType);
679689
Assert.Equal(new[] { "application/xml" }, endpointMetadata.ContentTypes);
680-
681690
}
682691

683692
[Fact]

0 commit comments

Comments
 (0)