From 1680b9f4fcd1cc4fcfd79470ac7ff75ea24e04c3 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 22 Aug 2018 17:15:57 +1200 Subject: [PATCH] Change endpoint invoker to RequestDelegate, Endpoint/EndpointMetadataCollection namespaces, split out IRouteValuesFeature (#712) --- .../Benchmarks/StartupUsingEndpointRouting.cs | 6 +- .../EndpointMetadataCollectionBenchmark.cs | 1 + .../EndpointRoutingBenchmarkBase.cs | 23 +-- ...LinkGenerationGithubBenchmark.generated.cs | 4 +- .../Matching/MatcherAzureBenchmark.cs | 1 + .../MatcherAzureBenchmark.generated.cs | 2 +- ...indCandidateSetAzureBenchmark.generated.cs | 2 +- ...ndCandidateSetGithubBenchmark.generated.cs | 2 +- ...herFindCandidateSetSingleEntryBenchmark.cs | 2 +- ...indCandidateSetSmallEntryCountBenchmark.cs | 3 +- .../Matching/MatcherGithubBenchmark.cs | 1 + .../MatcherGithubBenchmark.generated.cs | 2 +- .../Matching/MatcherSingleEntryBenchmark.cs | 3 +- .../Matching/TrivialMatcher.cs | 9 +- .../Matching/TrivialMatcherBuilder.cs | 4 +- benchmarks/Swaggatherer/Template.cs | 4 +- .../UseEndpointRoutingStartup.cs | 14 +- .../Endpoint.cs | 14 +- .../EndpointMetadataCollection.cs | 2 +- .../IEndpointFeature.cs | 19 +-- .../IRouteValuesFeature.cs | 16 ++ .../CompositeEndpointDataSource.cs | 18 +- .../DataSourceDependentCache.cs | 1 + .../DataTokensMetadata.cs | 1 + .../DefaultEndpointDataSource.cs | 1 + .../DefaultLinkGenerationTemplate.cs | 4 +- .../DefaultLinkGenerator.cs | 17 +- .../EndpointDataSource.cs | 1 + .../EndpointFeature.cs | 28 ++-- .../EndpointMiddleware.cs | 5 +- .../EndpointRoutingMiddleware.cs | 20 ++- .../IDataTokenMetadata.cs | 1 + .../IEndpointFinderOfT.cs | 1 + .../Internal/DfaGraphWriter.cs | 3 +- .../Matching/Candidate.cs | 6 +- .../Matching/CandidateSet.cs | 3 +- .../Matching/CandidateState.cs | 14 +- .../Matching/DataSourceDependentMatcher.cs | 8 +- .../Matching/DefaultEndpointSelector.cs | 10 +- .../Matching/DfaMatcher.cs | 3 +- .../Matching/DfaMatcherBuilder.cs | 22 +-- .../Matching/DfaNode.cs | 4 +- .../Matching/EndpointMetadataComparer.cs | 1 + .../Matching/EndpointSelector.cs | 8 +- .../Matching/HttpMethodMatcherPolicy.cs | 4 +- .../Matching/IEndpointComparerPolicy.cs | 1 + .../Matching/INodeBuilderPolicy.cs | 1 + .../Matching/Matcher.cs | 5 +- .../Matching/MatcherBuilder.cs | 2 +- .../Matching/PolicyNodeEdge.cs | 1 + ...ntComparer.cs => RouteEndpointComparer.cs} | 30 ++-- .../MatcherEndpoint.cs => RouteEndpoint.cs} | 29 +--- .../RouteValuesBasedEndpointFinder.cs | 7 +- .../EndpointMetadataCollectionTests.cs | 1 + .../EndpointRoutingBuilderExtensionsTest.cs | 1 + .../CompositeEndpointDataSourceTest.cs | 7 +- .../DefaultEndpointDataSourceTests.cs | 10 +- .../DefaultLinkGeneratorTest.cs | 158 +++++++++--------- .../EndpointFactory.cs | 8 +- .../EndpointFeatureTest.cs | 9 +- .../EndpointRoutingMiddlewareTest.cs | 34 ++-- .../Matching/BarebonesMatcher.cs | 13 +- .../Matching/BarebonesMatcherBuilder.cs | 4 +- .../BarebonesMatcherConformanceTest.cs | 2 +- .../Matching/CandidateSetTest.cs | 11 +- .../DataSourceDependentMatcherTest.cs | 21 +-- .../Matching/DefaultEndpointSelectorTest.cs | 41 ++--- .../Matching/DfaMatcherBuilderTest.cs | 7 +- .../Matching/DfaMatcherConformanceTest.cs | 4 +- .../Matching/DfaMatcherTest.cs | 36 ++-- .../Matching/EndpointMetadataComparerTest.cs | 22 +-- .../FullFeaturedMatcherConformanceTest.cs | 34 ++-- .../HttpMethodMatcherPolicyIntegrationTest.cs | 44 ++--- .../Matching/HttpMethodMatcherPolicyTest.cs | 7 +- .../Matching/MatcherAssert.cs | 41 +++-- .../MatcherConformanceTest.SingleEndpoint.cs | 34 ++-- .../Matching/MatcherConformanceTest.cs | 14 +- ...erTest.cs => RouteEndpointComparerTest.cs} | 15 +- .../Matching/RouteMatcher.cs | 5 +- .../Matching/RouteMatcherBuilder.cs | 13 +- .../Matching/RouteMatcherConformanceTest.cs | 2 +- .../Matching/TreeRouterMatcher.cs | 5 +- .../Matching/TreeRouterMatcherBuilder.cs | 15 +- .../TreeRouterMatcherConformanceTest.cs | 2 +- .../RouteValueBasedEndpointFinderTest.cs | 27 +-- .../TestConstants.cs | 13 ++ .../TestObjects/DynamicEndpointDataSource.cs | 1 + .../TestObjects/TestEndpoint.cs | 13 -- .../TestObjects/TestMatcher.cs | 7 +- 89 files changed, 574 insertions(+), 501 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Routing.Abstractions/IRouteValuesFeature.cs rename src/Microsoft.AspNetCore.Routing/Matching/{MatcherEndpointComparer.cs => RouteEndpointComparer.cs} (70%) rename src/Microsoft.AspNetCore.Routing/{Matching/MatcherEndpoint.cs => RouteEndpoint.cs} (66%) rename test/Microsoft.AspNetCore.Routing.Tests/Matching/{MatcherEndpointComparerTest.cs => RouteEndpointComparerTest.cs} (93%) create mode 100644 test/Microsoft.AspNetCore.Routing.Tests/TestConstants.cs delete mode 100644 test/Microsoft.AspNetCore.Routing.Tests/TestObjects/TestEndpoint.cs diff --git a/benchmarkapps/Benchmarks/StartupUsingEndpointRouting.cs b/benchmarkapps/Benchmarks/StartupUsingEndpointRouting.cs index 2c5fa5a7d9..2814badc32 100644 --- a/benchmarkapps/Benchmarks/StartupUsingEndpointRouting.cs +++ b/benchmarkapps/Benchmarks/StartupUsingEndpointRouting.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Text; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -21,8 +21,8 @@ namespace Benchmarks var endpointDataSource = new DefaultEndpointDataSource(new[] { - new MatcherEndpoint( - invoker: (next) => (httpContext) => + new RouteEndpoint( + requestDelegate: (httpContext) => { var response = httpContext.Response; var payloadLength = _helloWorldPayload.Length; diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/EndpointMetadataCollectionBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/EndpointMetadataCollectionBenchmark.cs index 14c1498462..3e5492b8a2 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/EndpointMetadataCollectionBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/EndpointMetadataCollectionBenchmark.cs @@ -3,6 +3,7 @@ using System; using BenchmarkDotNet.Attributes; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing { diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/EndpointRoutingBenchmarkBase.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/EndpointRoutingBenchmarkBase.cs index 57e79d7109..ece73b75a4 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/EndpointRoutingBenchmarkBase.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/EndpointRoutingBenchmarkBase.cs @@ -5,7 +5,9 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Text; +using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Template; @@ -18,10 +20,10 @@ namespace Microsoft.AspNetCore.Routing { public abstract class EndpointRoutingBenchmarkBase { - private protected MatcherEndpoint[] Endpoints; + private protected RouteEndpoint[] Endpoints; private protected HttpContext[] Requests; - private protected void SetupEndpoints(params MatcherEndpoint[] endpoints) + private protected void SetupEndpoints(params RouteEndpoint[] endpoints) { Endpoints = endpoints; } @@ -76,8 +78,8 @@ namespace Microsoft.AspNetCore.Routing var message = new StringBuilder(); message.AppendLine($"Validation failed for request {Array.IndexOf(Requests, httpContext)}"); message.AppendLine($"{httpContext.Request.Method} {httpContext.Request.Path}"); - message.AppendLine($"expected: '{((MatcherEndpoint)expected)?.DisplayName ?? "null"}'"); - message.AppendLine($"actual: '{((MatcherEndpoint)actual)?.DisplayName ?? "null"}'"); + message.AppendLine($"expected: '{((RouteEndpoint)expected)?.DisplayName ?? "null"}'"); + message.AppendLine($"actual: '{((RouteEndpoint)actual)?.DisplayName ?? "null"}'"); throw new InvalidOperationException(message.ToString()); } } @@ -95,7 +97,7 @@ namespace Microsoft.AspNetCore.Routing } } - protected MatcherEndpoint CreateEndpoint( + protected RouteEndpoint CreateEndpoint( string template, object defaults = null, object constraints = null, @@ -108,8 +110,8 @@ namespace Microsoft.AspNetCore.Routing var endpointMetadata = new List(metadata ?? Array.Empty()); endpointMetadata.Add(new RouteValuesAddressMetadata(routeName, new RouteValueDictionary(requiredValues))); - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + (context) => Task.CompletedTask, RoutePatternFactory.Parse(template, defaults, constraints), order, new EndpointMetadataCollection(endpointMetadata), @@ -119,14 +121,15 @@ namespace Microsoft.AspNetCore.Routing protected (HttpContext httpContext, RouteValueDictionary ambientValues) CreateCurrentRequestContext( object ambientValues = null) { - var feature = new EndpointFeature { Values = new RouteValueDictionary(ambientValues) }; + var feature = new EndpointFeature { RouteValues = new RouteValueDictionary(ambientValues) }; var context = new DefaultHttpContext(); context.Features.Set(feature); + context.Features.Set(feature); - return (context, feature.Values); + return (context, feature.RouteValues); } - protected void CreateOutboundRouteEntry(TreeRouteBuilder treeRouteBuilder, MatcherEndpoint endpoint) + protected void CreateOutboundRouteEntry(TreeRouteBuilder treeRouteBuilder, RouteEndpoint endpoint) { var routeValuesAddressMetadata = endpoint.Metadata.GetMetadata(); var requiredValues = routeValuesAddressMetadata?.RequiredValues ?? new RouteValueDictionary(); diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/LinkGeneration/LinkGenerationGithubBenchmark.generated.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/LinkGeneration/LinkGenerationGithubBenchmark.generated.cs index 14e3ecb9d7..2da180b1d2 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/LinkGeneration/LinkGenerationGithubBenchmark.generated.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/LinkGeneration/LinkGenerationGithubBenchmark.generated.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Routing.LinkGeneration private void SetupEndpoints() { - Endpoints = new MatcherEndpoint[243]; + Endpoints = new RouteEndpoint[243]; Endpoints[0] = CreateEndpoint("/emojis", "Controller1", "Action1", "GET"); Endpoints[1] = CreateEndpoint("/events", "Controller2", "Action1", "GET"); Endpoints[2] = CreateEndpoint("/feeds", "Controller3", "Action1", "GET"); @@ -1485,7 +1485,7 @@ namespace Microsoft.AspNetCore.Routing.LinkGeneration return builder.Build(); } - private MatcherEndpoint CreateEndpoint(string template, string controllerName, string actionName, string httpMethod) + private RouteEndpoint CreateEndpoint(string template, string controllerName, string actionName, string httpMethod) { var requiredValues = new { diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherAzureBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherAzureBenchmark.cs index cf3a41c31f..b68255e3cd 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherAzureBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherAzureBenchmark.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherAzureBenchmark.generated.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherAzureBenchmark.generated.cs index f486eb23e1..ebb347ea51 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherAzureBenchmark.generated.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherAzureBenchmark.generated.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Routing.Matching private void SetupEndpoints() { - Endpoints = new MatcherEndpoint[5160]; + Endpoints = new RouteEndpoint[5160]; Endpoints[0] = CreateEndpoint("/account", "GET"); Endpoints[1] = CreateEndpoint("/analyze", "POST"); Endpoints[2] = CreateEndpoint("/apis", "GET"); diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetAzureBenchmark.generated.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetAzureBenchmark.generated.cs index bd633b706c..55672f7726 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetAzureBenchmark.generated.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetAzureBenchmark.generated.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Routing.Matching private void SetupEndpoints() { - Endpoints = new MatcherEndpoint[3517]; + Endpoints = new RouteEndpoint[3517]; Endpoints[0] = CreateEndpoint("/account"); Endpoints[1] = CreateEndpoint("/analyze"); Endpoints[2] = CreateEndpoint("/apis"); diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetGithubBenchmark.generated.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetGithubBenchmark.generated.cs index ee94d2c67f..01fca2ee00 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetGithubBenchmark.generated.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetGithubBenchmark.generated.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Routing.Matching private void SetupEndpoints() { - Endpoints = new MatcherEndpoint[155]; + Endpoints = new RouteEndpoint[155]; Endpoints[0] = CreateEndpoint("/emojis"); Endpoints[1] = CreateEndpoint("/events"); Endpoints[2] = CreateEndpoint("/feeds"); diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSingleEntryBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSingleEntryBenchmark.cs index cf08ed656b..b0d3b2bcd2 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSingleEntryBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSingleEntryBenchmark.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Routing.Matching [GlobalSetup] public void Setup() { - Endpoints = new MatcherEndpoint[1]; + Endpoints = new RouteEndpoint[1]; Endpoints[0] = CreateEndpoint("/plaintext"); Requests = new HttpContext[1]; diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSmallEntryCountBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSmallEntryCountBenchmark.cs index 4bcb08517b..993dabc419 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSmallEntryCountBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSmallEntryCountBenchmark.cs @@ -4,6 +4,7 @@ using System; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -32,7 +33,7 @@ namespace Microsoft.AspNetCore.Routing.Matching private void SetupEndpoints() { - Endpoints = new MatcherEndpoint[10]; + Endpoints = new RouteEndpoint[10]; Endpoints[0] = CreateEndpoint("/another-really-cool-entry"); Endpoints[1] = CreateEndpoint("/Some-Entry"); Endpoints[2] = CreateEndpoint("/a/path/with/more/segments"); diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherGithubBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherGithubBenchmark.cs index 723bcbd549..0859fd7a72 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherGithubBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherGithubBenchmark.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherGithubBenchmark.generated.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherGithubBenchmark.generated.cs index b6bc1ba4ff..01b2edd58f 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherGithubBenchmark.generated.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherGithubBenchmark.generated.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Routing.Matching private void SetupEndpoints() { - Endpoints = new MatcherEndpoint[243]; + Endpoints = new RouteEndpoint[243]; Endpoints[0] = CreateEndpoint("/emojis", "GET"); Endpoints[1] = CreateEndpoint("/events", "GET"); Endpoints[2] = CreateEndpoint("/feeds", "GET"); diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherSingleEntryBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherSingleEntryBenchmark.cs index f38883658a..1c15e43862 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherSingleEntryBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherSingleEntryBenchmark.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -22,7 +23,7 @@ namespace Microsoft.AspNetCore.Routing.Matching [GlobalSetup] public void Setup() { - Endpoints = new MatcherEndpoint[1]; + Endpoints = new RouteEndpoint[1]; Endpoints[0] = CreateEndpoint("/plaintext"); Requests = new HttpContext[1]; diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/TrivialMatcher.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/TrivialMatcher.cs index d05ed2639d..ffe2428fe3 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/TrivialMatcher.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/TrivialMatcher.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -12,17 +13,17 @@ namespace Microsoft.AspNetCore.Routing.Matching // to establish a lower bound for perf comparisons. internal sealed class TrivialMatcher : Matcher { - private readonly MatcherEndpoint _endpoint; + private readonly RouteEndpoint _endpoint; private readonly Candidate[] _candidates; - public TrivialMatcher(MatcherEndpoint endpoint) + public TrivialMatcher(RouteEndpoint endpoint) { _endpoint = endpoint; _candidates = new Candidate[] { new Candidate(endpoint), }; } - public sealed override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public sealed override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { if (httpContext == null) { @@ -38,7 +39,7 @@ namespace Microsoft.AspNetCore.Routing.Matching if (string.Equals(_endpoint.RoutePattern.RawText, path, StringComparison.OrdinalIgnoreCase)) { feature.Endpoint = _endpoint; - feature.Values = new RouteValueDictionary(); + feature.RouteValues = new RouteValueDictionary(); } return Task.CompletedTask; diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/TrivialMatcherBuilder.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/TrivialMatcherBuilder.cs index ffa3def965..01ce2871ac 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/TrivialMatcherBuilder.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/TrivialMatcherBuilder.cs @@ -8,9 +8,9 @@ namespace Microsoft.AspNetCore.Routing.Matching { internal class TrivialMatcherBuilder : MatcherBuilder { - private readonly List _endpoints = new List(); + private readonly List _endpoints = new List(); - public override void AddEndpoint(MatcherEndpoint endpoint) + public override void AddEndpoint(RouteEndpoint endpoint) { _endpoints.Add(endpoint); } diff --git a/benchmarks/Swaggatherer/Template.cs b/benchmarks/Swaggatherer/Template.cs index 13704b22b1..c5c0c7b42e 100644 --- a/benchmarks/Swaggatherer/Template.cs +++ b/benchmarks/Swaggatherer/Template.cs @@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.Routing private void SetupEndpoints() {{ - Endpoints = new MatcherEndpoint[{3}]; + Endpoints = new RouteEndpoint[{3}]; {0} }} @@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Routing return builder.Build(); }} - private MatcherEndpoint CreateEndpoint(string template, string controllerName, string actionName, string httpMethod) + private RouteEndpoint CreateEndpoint(string template, string controllerName, string actionName, string httpMethod) {{ var requiredValues = new {{ diff --git a/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs b/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs index f3606d5a9f..49262142dd 100644 --- a/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs +++ b/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs @@ -32,7 +32,7 @@ namespace RoutingSample.Web var endpointDataSource = new DefaultEndpointDataSource(new[] { - new MatcherEndpoint((next) => (httpContext) => + new RouteEndpoint((httpContext) => { var response = httpContext.Response; var payloadLength = _homePayload.Length; @@ -45,7 +45,7 @@ namespace RoutingSample.Web 0, EndpointMetadataCollection.Empty, "Home"), - new MatcherEndpoint((next) => (httpContext) => + new RouteEndpoint((httpContext) => { var response = httpContext.Response; var payloadLength = _helloWorldPayload.Length; @@ -58,7 +58,7 @@ namespace RoutingSample.Web 0, EndpointMetadataCollection.Empty, "Plaintext"), - new MatcherEndpoint((next) => (httpContext) => + new RouteEndpoint((httpContext) => { var response = httpContext.Response; response.StatusCode = 200; @@ -69,7 +69,7 @@ namespace RoutingSample.Web 0, EndpointMetadataCollection.Empty, "withconstraints"), - new MatcherEndpoint((next) => (httpContext) => + new RouteEndpoint((httpContext) => { var response = httpContext.Response; response.StatusCode = 200; @@ -80,7 +80,7 @@ namespace RoutingSample.Web 0, EndpointMetadataCollection.Empty, "withoptionalconstraints"), - new MatcherEndpoint((next) => (httpContext) => + new RouteEndpoint((httpContext) => { using (var writer = new StreamWriter(httpContext.Response.Body, Encoding.UTF8, 1024, leaveOpen: true)) { @@ -95,7 +95,7 @@ namespace RoutingSample.Web 0, new EndpointMetadataCollection(new HttpMethodMetadata(new[]{ "GET", })), "DFA Graph"), - new MatcherEndpoint((next) => (httpContext) => + new RouteEndpoint((httpContext) => { var linkGenerator = httpContext.RequestServices.GetRequiredService(); @@ -112,7 +112,7 @@ namespace RoutingSample.Web name: "WithSingleAsteriskCatchAll", requiredValues: new RouteValueDictionary())), "WithSingleAsteriskCatchAll"), - new MatcherEndpoint((next) => (httpContext) => + new RouteEndpoint((httpContext) => { var linkGenerator = httpContext.RequestServices.GetRequiredService(); diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/Endpoint.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/Endpoint.cs index ef98f75d8a..16202b45f5 100644 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/Endpoint.cs +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/Endpoint.cs @@ -1,27 +1,30 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Routing +namespace Microsoft.AspNetCore.Http { /// /// Respresents a logical endpoint in an application. /// - public abstract class Endpoint + public class Endpoint { /// /// Creates a new instance of . /// + /// The delegate used to process requests for the endpoint. /// /// The endpoint . May be null. /// /// /// The informational display name of the endpoint. May be null. /// - protected Endpoint( + public Endpoint( + RequestDelegate requestDelegate, EndpointMetadataCollection metadata, string displayName) { // All are allowed to be null + RequestDelegate = requestDelegate; Metadata = metadata ?? EndpointMetadataCollection.Empty; DisplayName = displayName; } @@ -36,6 +39,11 @@ namespace Microsoft.AspNetCore.Routing /// public EndpointMetadataCollection Metadata { get; } + /// + /// Gets the delegate used to process requests for the endpoint. + /// + public RequestDelegate RequestDelegate { get; } + public override string ToString() => DisplayName ?? base.ToString(); } } diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/EndpointMetadataCollection.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/EndpointMetadataCollection.cs index 4ca653a8fa..a792fff295 100644 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/EndpointMetadataCollection.cs +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/EndpointMetadataCollection.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; -namespace Microsoft.AspNetCore.Routing +namespace Microsoft.AspNetCore.Http { /// /// A collection of arbitrary metadata associated with an endpoint. diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/IEndpointFeature.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/IEndpointFeature.cs index c4b9ac95c2..ff0762bb20 100644 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/IEndpointFeature.cs +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/IEndpointFeature.cs @@ -1,10 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; -using Microsoft.AspNetCore.Http; - -namespace Microsoft.AspNetCore.Routing +namespace Microsoft.AspNetCore.Http.Features { /// /// A feature interface for endpoint routing. Use @@ -13,21 +10,9 @@ namespace Microsoft.AspNetCore.Routing public interface IEndpointFeature { /// - /// Gets or sets the selected for the current + /// Gets or sets the selected for the current /// request. /// Endpoint Endpoint { get; set; } - - /// - /// Gets or sets a delegate that can be used to invoke the current - /// . - /// - Func Invoker { get; set; } - - /// - /// Gets or sets the associated with the currrent - /// request. - /// - RouteValueDictionary Values { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/IRouteValuesFeature.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/IRouteValuesFeature.cs new file mode 100644 index 0000000000..3ab74b6bc7 --- /dev/null +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/IRouteValuesFeature.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Routing; + +namespace Microsoft.AspNetCore.Http.Features +{ + public interface IRouteValuesFeature + { + /// + /// Gets or sets the associated with the currrent + /// request. + /// + RouteValueDictionary RouteValues { get; set; } + } +} diff --git a/src/Microsoft.AspNetCore.Routing/CompositeEndpointDataSource.cs b/src/Microsoft.AspNetCore.Routing/CompositeEndpointDataSource.cs index b247291db4..991a324afb 100644 --- a/src/Microsoft.AspNetCore.Routing/CompositeEndpointDataSource.cs +++ b/src/Microsoft.AspNetCore.Routing/CompositeEndpointDataSource.cs @@ -7,7 +7,7 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; -using Microsoft.AspNetCore.Routing.Matching; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Routing @@ -132,15 +132,15 @@ namespace Microsoft.AspNetCore.Routing var sb = new StringBuilder(); foreach (var endpoint in _endpoints) { - if (endpoint is MatcherEndpoint matcherEndpoint) + if (endpoint is RouteEndpoint routeEndpoint) { - var template = matcherEndpoint.RoutePattern.RawText; + var template = routeEndpoint.RoutePattern.RawText; template = string.IsNullOrEmpty(template) ? "\"\"" : template; sb.Append(template); sb.Append(", Defaults: new { "); - sb.Append(string.Join(", ", FormatValues(matcherEndpoint.RoutePattern.Defaults))); + sb.Append(string.Join(", ", FormatValues(routeEndpoint.RoutePattern.Defaults))); sb.Append(" }"); - var routeValuesAddressMetadata = matcherEndpoint.Metadata.GetMetadata(); + var routeValuesAddressMetadata = routeEndpoint.Metadata.GetMetadata(); sb.Append(", Route Name: "); sb.Append(routeValuesAddressMetadata?.Name); if (routeValuesAddressMetadata?.RequiredValues != null) @@ -150,21 +150,21 @@ namespace Microsoft.AspNetCore.Routing sb.Append(" }"); } sb.Append(", Order: "); - sb.Append(matcherEndpoint.Order); + sb.Append(routeEndpoint.Order); - var httpMethodMetadata = matcherEndpoint.Metadata.GetMetadata(); + var httpMethodMetadata = routeEndpoint.Metadata.GetMetadata(); if (httpMethodMetadata != null) { sb.Append(", Http Methods: "); sb.Append(string.Join(", ", httpMethodMetadata.HttpMethods)); } sb.Append(", Display Name: "); - sb.Append(matcherEndpoint.DisplayName); + sb.Append(routeEndpoint.DisplayName); sb.AppendLine(); } else { - sb.Append("Non-MatcherEndpoint. DisplayName:"); + sb.Append("Non-RouteEndpoint. DisplayName:"); sb.AppendLine(endpoint.DisplayName); } } diff --git a/src/Microsoft.AspNetCore.Routing/DataSourceDependentCache.cs b/src/Microsoft.AspNetCore.Routing/DataSourceDependentCache.cs index 8df45ef090..4daf256327 100644 --- a/src/Microsoft.AspNetCore.Routing/DataSourceDependentCache.cs +++ b/src/Microsoft.AspNetCore.Routing/DataSourceDependentCache.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Threading; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing { diff --git a/src/Microsoft.AspNetCore.Routing/DataTokensMetadata.cs b/src/Microsoft.AspNetCore.Routing/DataTokensMetadata.cs index 99a07f038d..831075af40 100644 --- a/src/Microsoft.AspNetCore.Routing/DataTokensMetadata.cs +++ b/src/Microsoft.AspNetCore.Routing/DataTokensMetadata.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing { diff --git a/src/Microsoft.AspNetCore.Routing/DefaultEndpointDataSource.cs b/src/Microsoft.AspNetCore.Routing/DefaultEndpointDataSource.cs index 7ec3f4c6e6..94728feb8c 100644 --- a/src/Microsoft.AspNetCore.Routing/DefaultEndpointDataSource.cs +++ b/src/Microsoft.AspNetCore.Routing/DefaultEndpointDataSource.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Primitives; diff --git a/src/Microsoft.AspNetCore.Routing/DefaultLinkGenerationTemplate.cs b/src/Microsoft.AspNetCore.Routing/DefaultLinkGenerationTemplate.cs index 2b432db71f..01d4c54267 100644 --- a/src/Microsoft.AspNetCore.Routing/DefaultLinkGenerationTemplate.cs +++ b/src/Microsoft.AspNetCore.Routing/DefaultLinkGenerationTemplate.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Routing { public DefaultLinkGenerationTemplate( DefaultLinkGenerator linkGenerator, - IEnumerable endpoints, + IEnumerable endpoints, HttpContext httpContext, RouteValueDictionary explicitValues, RouteValueDictionary ambientValues) @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Routing internal DefaultLinkGenerator LinkGenerator { get; } - internal IEnumerable Endpoints { get; } + internal IEnumerable Endpoints { get; } internal HttpContext HttpContext { get; } diff --git a/src/Microsoft.AspNetCore.Routing/DefaultLinkGenerator.cs b/src/Microsoft.AspNetCore.Routing/DefaultLinkGenerator.cs index fe38826aa7..b60f25eb25 100644 --- a/src/Microsoft.AspNetCore.Routing/DefaultLinkGenerator.cs +++ b/src/Microsoft.AspNetCore.Routing/DefaultLinkGenerator.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Internal; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Template; @@ -97,7 +98,7 @@ namespace Microsoft.AspNetCore.Routing internal string MakeLink( HttpContext httpContext, - MatcherEndpoint endpoint, + RouteEndpoint endpoint, RouteValueDictionary ambientValues, RouteValueDictionary explicitValues, LinkOptions options) @@ -232,7 +233,7 @@ namespace Microsoft.AspNetCore.Routing private bool MatchesConstraints( HttpContext httpContext, - MatcherEndpoint endpoint, + RouteEndpoint endpoint, RouteValueDictionary routeValues) { if (routeValues == null) @@ -303,16 +304,16 @@ namespace Microsoft.AspNetCore.Routing { if (httpContext != null) { - var feature = httpContext.Features.Get(); + var feature = httpContext.Features.Get(); if (feature != null) { - return feature.Values; + return feature.RouteValues; } } return new RouteValueDictionary(); } - private IEnumerable FindEndpoints(TAddress address) + private IEnumerable FindEndpoints(TAddress address) { var finder = _serviceProvider.GetRequiredService>(); var endpoints = finder.FindEndpoints(address); @@ -321,13 +322,13 @@ namespace Microsoft.AspNetCore.Routing return null; } - var matcherEndpoints = endpoints.OfType(); - if (!matcherEndpoints.Any()) + var routeEndpoints = endpoints.OfType(); + if (!routeEndpoints.Any()) { return null; } - return matcherEndpoints; + return routeEndpoints; } } } diff --git a/src/Microsoft.AspNetCore.Routing/EndpointDataSource.cs b/src/Microsoft.AspNetCore.Routing/EndpointDataSource.cs index 6ae887d0a0..6176ba08e0 100644 --- a/src/Microsoft.AspNetCore.Routing/EndpointDataSource.cs +++ b/src/Microsoft.AspNetCore.Routing/EndpointDataSource.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Routing diff --git a/src/Microsoft.AspNetCore.Routing/EndpointFeature.cs b/src/Microsoft.AspNetCore.Routing/EndpointFeature.cs index c87db04900..582f96cb7c 100644 --- a/src/Microsoft.AspNetCore.Routing/EndpointFeature.cs +++ b/src/Microsoft.AspNetCore.Routing/EndpointFeature.cs @@ -3,39 +3,31 @@ using System; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing { - /// - /// A default implementation of and . - /// - public sealed class EndpointFeature : IEndpointFeature, IRoutingFeature + public sealed class EndpointFeature : IEndpointFeature, IRouteValuesFeature, IRoutingFeature { private RouteData _routeData; - private RouteValueDictionary _values; + private RouteValueDictionary _routeValues; /// - /// Gets or sets the selected for the current + /// Gets or sets the selected for the current /// request. /// public Endpoint Endpoint { get; set; } - /// - /// Gets or sets a delegate that can be used to invoke the current - /// . - /// - public Func Invoker { get; set; } - /// /// Gets or sets the associated with the currrent /// request. /// - public RouteValueDictionary Values + public RouteValueDictionary RouteValues { - get => _values; + get => _routeValues; set { - _values = value; + _routeValues = value; // RouteData will be created next get with new Values _routeData = null; @@ -46,7 +38,7 @@ namespace Microsoft.AspNetCore.Routing /// Gets or sets the for the current request. /// /// - /// The setter is not implemented. Use to set the route values. + /// The setter is not implemented. Use to set the route values. /// RouteData IRoutingFeature.RouteData { @@ -54,7 +46,7 @@ namespace Microsoft.AspNetCore.Routing { if (_routeData == null) { - _routeData = _values == null ? new RouteData() : new RouteData(_values); + _routeData = _routeValues == null ? new RouteData() : new RouteData(_routeValues); // Note: DataTokens won't update if someone else overwrites the Endpoint // after route values has been set. This seems find since endpoints are a new @@ -75,4 +67,4 @@ namespace Microsoft.AspNetCore.Routing set => throw new NotSupportedException(); } } -} +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing/EndpointMiddleware.cs b/src/Microsoft.AspNetCore.Routing/EndpointMiddleware.cs index 8ef2bcdb3d..46a2c36a25 100644 --- a/src/Microsoft.AspNetCore.Routing/EndpointMiddleware.cs +++ b/src/Microsoft.AspNetCore.Routing/EndpointMiddleware.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Routing @@ -40,13 +41,13 @@ namespace Microsoft.AspNetCore.Routing throw new InvalidOperationException(message); } - if (feature.Invoker != null) + if (feature.Endpoint?.RequestDelegate != null) { Log.ExecutingEndpoint(_logger, feature.Endpoint); try { - await feature.Invoker(_next)(httpContext); + await feature.Endpoint.RequestDelegate(httpContext); } finally { diff --git a/src/Microsoft.AspNetCore.Routing/EndpointRoutingMiddleware.cs b/src/Microsoft.AspNetCore.Routing/EndpointRoutingMiddleware.cs index e38175d165..c4c09d5de7 100644 --- a/src/Microsoft.AspNetCore.Routing/EndpointRoutingMiddleware.cs +++ b/src/Microsoft.AspNetCore.Routing/EndpointRoutingMiddleware.cs @@ -5,6 +5,7 @@ using System; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -54,11 +55,10 @@ namespace Microsoft.AspNetCore.Routing public async Task Invoke(HttpContext httpContext) { + // For back-compat EndpointRouteValuesFeature implements IEndpointFeature, IRouteValuesFeature and IRoutingFeature var feature = new EndpointFeature(); - httpContext.Features.Set(feature); - // Back compat support for users of IRoutingFeature - httpContext.Features.Set(feature); + SetEndpointFeature(httpContext, feature); // There's an inherent race condition between waiting for init and accessing the matcher // this is OK because once `_matcher` is initialized, it will not be set to null again. @@ -77,6 +77,18 @@ namespace Microsoft.AspNetCore.Routing await _next(httpContext); } + private static void SetEndpointFeature(HttpContext httpContext, EndpointFeature feature) + { + // An IRouteValuesFeature might have already been set + // Copy its RouteValues collection if present + var currentRouteValuesFeature = httpContext.Features.Get(); + feature.RouteValues = currentRouteValuesFeature?.RouteValues; + + httpContext.Features.Set(feature); + httpContext.Features.Set(feature); + httpContext.Features.Set(feature); + } + // Initialization is async to avoid blocking threads while reflection and things // of that nature take place. // @@ -127,4 +139,4 @@ namespace Microsoft.AspNetCore.Routing } } } -} +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing/IDataTokenMetadata.cs b/src/Microsoft.AspNetCore.Routing/IDataTokenMetadata.cs index 9cd6455d6c..0fb28ac244 100644 --- a/src/Microsoft.AspNetCore.Routing/IDataTokenMetadata.cs +++ b/src/Microsoft.AspNetCore.Routing/IDataTokenMetadata.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing { diff --git a/src/Microsoft.AspNetCore.Routing/IEndpointFinderOfT.cs b/src/Microsoft.AspNetCore.Routing/IEndpointFinderOfT.cs index 618220a6e9..b40453d678 100644 --- a/src/Microsoft.AspNetCore.Routing/IEndpointFinderOfT.cs +++ b/src/Microsoft.AspNetCore.Routing/IEndpointFinderOfT.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing { diff --git a/src/Microsoft.AspNetCore.Routing/Internal/DfaGraphWriter.cs b/src/Microsoft.AspNetCore.Routing/Internal/DfaGraphWriter.cs index 2d036ac76b..eb2d2f10ec 100644 --- a/src/Microsoft.AspNetCore.Routing/Internal/DfaGraphWriter.cs +++ b/src/Microsoft.AspNetCore.Routing/Internal/DfaGraphWriter.cs @@ -38,8 +38,7 @@ namespace Microsoft.AspNetCore.Routing.Internal var endpoints = dataSource.Endpoints; for (var i = 0; i < endpoints.Count; i++) { - var endpoint = endpoints[i] as MatcherEndpoint; - if (endpoint != null && endpoint.Metadata.GetMetadata() == null) + if (endpoints[i] is RouteEndpoint endpoint && endpoint.Metadata.GetMetadata() == null) { builder.AddEndpoint(endpoint); } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/Candidate.cs b/src/Microsoft.AspNetCore.Routing/Matching/Candidate.cs index 27f9b138cf..47564d511c 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/Candidate.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/Candidate.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Routing.Matching { internal readonly struct Candidate { - public readonly MatcherEndpoint Endpoint; + public readonly RouteEndpoint Endpoint; // Used to optimize out operations that modify route values. public readonly CandidateFlags Flags; @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public readonly int Score; // Used in tests. - public Candidate(MatcherEndpoint endpoint) + public Candidate(RouteEndpoint endpoint) { Endpoint = endpoint; @@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Routing.Matching } public Candidate( - MatcherEndpoint endpoint, + RouteEndpoint endpoint, int score, KeyValuePair[] slots, (string parameterName, int segmentIndex, int slotIndex)[] captures, diff --git a/src/Microsoft.AspNetCore.Routing/Matching/CandidateSet.cs b/src/Microsoft.AspNetCore.Routing/Matching/CandidateSet.cs index be134bf6ce..58cb607e41 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/CandidateSet.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/CandidateSet.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing.Matching { @@ -35,7 +36,7 @@ namespace Microsoft.AspNetCore.Routing.Matching /// /// The list of endpoints, sorted in descending priority order. /// The list of endpoint scores. . - public CandidateSet(MatcherEndpoint[] endpoints, int[] scores) + public CandidateSet(RouteEndpoint[] endpoints, int[] scores) { Count = endpoints.Length; diff --git a/src/Microsoft.AspNetCore.Routing/Matching/CandidateState.cs b/src/Microsoft.AspNetCore.Routing/Matching/CandidateState.cs index cf27c04c78..04913a532d 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/CandidateState.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/CandidateState.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Routing.Matching /// public struct CandidateState { - internal CandidateState(MatcherEndpoint endpoint, int score) + internal CandidateState(RouteEndpoint endpoint, int score) { Endpoint = endpoint; Score = score; @@ -18,12 +18,12 @@ namespace Microsoft.AspNetCore.Routing.Matching } /// - /// Gets the . + /// Gets the . /// - public MatcherEndpoint Endpoint { get; } + public RouteEndpoint Endpoint { get; } /// - /// Gets the score of the within the current + /// Gets the score of the within the current /// . /// /// @@ -40,15 +40,15 @@ namespace Microsoft.AspNetCore.Routing.Matching public int Score { get; } /// - /// Gets or sets a value which indicates where the is considered + /// Gets or sets a value which indicates where the is considered /// a valid candiate for the current request. Set this value to false to exclude an - /// from consideration. + /// from consideration. /// public bool IsValidCandidate { get; set; } /// /// Gets or sets the associated with the - /// and the current request. + /// and the current request. /// public RouteValueDictionary Values { get; set; } } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/DataSourceDependentMatcher.cs b/src/Microsoft.AspNetCore.Routing/Matching/DataSourceDependentMatcher.cs index 9dced3dc3d..85a1214402 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/DataSourceDependentMatcher.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/DataSourceDependentMatcher.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Routing.Matching // Used in tests internal Matcher CurrentMatcher => _cache.Value; - public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { return CurrentMatcher.MatchAsync(httpContext, feature); } @@ -36,11 +37,10 @@ namespace Microsoft.AspNetCore.Routing.Matching var builder = _matcherBuilderFactory(); for (var i = 0; i < endpoints.Count; i++) { - // By design we only look at MatcherEndpoint here. It's possible to + // By design we only look at RouteEndpoint here. It's possible to // register other endpoint types, which are non-routable, and it's // ok that we won't route to them. - var endpoint = endpoints[i] as MatcherEndpoint; - if (endpoint != null && endpoint.Metadata.GetMetadata() == null) + if (endpoints[i] is RouteEndpoint endpoint && endpoint.Metadata.GetMetadata() == null) { builder.AddEndpoint(endpoint); } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/DefaultEndpointSelector.cs b/src/Microsoft.AspNetCore.Routing/Matching/DefaultEndpointSelector.cs index 59418b10c1..56779c75e0 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/DefaultEndpointSelector.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/DefaultEndpointSelector.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -25,7 +26,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public override Task SelectAsync( HttpContext httpContext, - IEndpointFeature feature, + EndpointFeature feature, CandidateSet candidateSet) { for (var i = 0; i < _selectorPolicies.Length; i++) @@ -33,7 +34,7 @@ namespace Microsoft.AspNetCore.Routing.Matching _selectorPolicies[i].Apply(httpContext, candidateSet); } - MatcherEndpoint endpoint = null; + RouteEndpoint endpoint = null; RouteValueDictionary values = null; int? foundScore = null; for (var i = 0; i < candidateSet.Count; i++) @@ -73,8 +74,7 @@ namespace Microsoft.AspNetCore.Routing.Matching if (endpoint != null) { feature.Endpoint = endpoint; - feature.Invoker = endpoint.Invoker; - feature.Values = values; + feature.RouteValues = values; } return Task.CompletedTask; @@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Routing.Matching { // If we get here it's the result of an ambiguity - we're OK with this // being a littler slower and more allocatey. - var matches = new List(); + var matches = new List(); for (var i = 0; i < candidates.Count; i++) { ref var state = ref candidates[i]; diff --git a/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcher.cs b/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcher.cs index ce8d6b4c1e..54209ab0e4 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcher.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcher.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Patterns; namespace Microsoft.AspNetCore.Routing.Matching @@ -22,7 +23,7 @@ namespace Microsoft.AspNetCore.Routing.Matching _maxSegmentCount = maxSegmentCount; } - public sealed override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public sealed override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { if (httpContext == null) { diff --git a/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcherBuilder.cs b/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcherBuilder.cs index c58d2547ff..10b05a60a0 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcherBuilder.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcherBuilder.cs @@ -10,13 +10,13 @@ namespace Microsoft.AspNetCore.Routing.Matching { internal class DfaMatcherBuilder : MatcherBuilder { - private readonly List _endpoints = new List(); + private readonly List _endpoints = new List(); private readonly ParameterPolicyFactory _parameterPolicyFactory; private readonly EndpointSelector _selector; private readonly MatcherPolicy[] _policies; private readonly INodeBuilderPolicy[] _nodeBuilders; - private readonly MatcherEndpointComparer _comparer; + private readonly RouteEndpointComparer _comparer; public DfaMatcherBuilder( ParameterPolicyFactory parameterPolicyFactory, @@ -29,10 +29,10 @@ namespace Microsoft.AspNetCore.Routing.Matching // Taking care to use _policies, which has been sorted. _nodeBuilders = _policies.OfType().ToArray(); - _comparer = new MatcherEndpointComparer(_policies.OfType().ToArray()); + _comparer = new RouteEndpointComparer(_policies.OfType().ToArray()); } - public override void AddEndpoint(MatcherEndpoint endpoint) + public override void AddEndpoint(RouteEndpoint endpoint) { _endpoints.Add(endpoint); } @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Routing.Matching // Since we're doing a BFS we will process each 'level' of the tree in stages // this list will hold the set of items we need to process at the current // stage. - var work = new List<(MatcherEndpoint endpoint, List parents)>(); + var work = new List<(RouteEndpoint endpoint, List parents)>(); var root = new DfaNode() { PathDepth = 0, Label = "/" }; @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Routing.Matching for (var depth = 0; depth <= maxDepth; depth++) { // As we process items, collect the next set of items. - var nextWork = new List<(MatcherEndpoint endpoint, List parents)>(); + var nextWork = new List<(RouteEndpoint endpoint, List parents)>(); for (var i = 0; i < work.Count; i++) { @@ -192,7 +192,7 @@ namespace Microsoft.AspNetCore.Routing.Matching return root; } - private RoutePatternPathSegment GetCurrentSegment(MatcherEndpoint endpoint, int depth) + private RoutePatternPathSegment GetCurrentSegment(RouteEndpoint endpoint, int depth) { if (depth < endpoint.RoutePattern.PathSegments.Count) { @@ -337,7 +337,7 @@ namespace Microsoft.AspNetCore.Routing.Matching // Builds an array of candidates for a node, assigns a 'score' for each // endpoint. - internal Candidate[] CreateCandidates(IReadOnlyList endpoints) + internal Candidate[] CreateCandidates(IReadOnlyList endpoints) { if (endpoints.Count == 0) { @@ -367,7 +367,7 @@ namespace Microsoft.AspNetCore.Routing.Matching } // internal for tests - internal Candidate CreateCandidate(MatcherEndpoint endpoint, int score) + internal Candidate CreateCandidate(RouteEndpoint endpoint, int score) { var assignments = new Dictionary(StringComparer.OrdinalIgnoreCase); var slots = new List>(); @@ -481,7 +481,7 @@ namespace Microsoft.AspNetCore.Routing.Matching return groups.ToArray(); } - private static bool HasAdditionalRequiredSegments(MatcherEndpoint endpoint, int depth) + private static bool HasAdditionalRequiredSegments(RouteEndpoint endpoint, int depth) { for (var i = depth; i < endpoint.RoutePattern.PathSegments.Count; i++) { @@ -550,7 +550,7 @@ namespace Microsoft.AspNetCore.Routing.Matching }; // TODO: https://github.com/aspnet/Routing/issues/648 - next.Matches.AddRange(edge.Endpoints.Cast().ToArray()); + next.Matches.AddRange(edge.Endpoints.Cast().ToArray()); nextWork.Add(next); parent.PolicyEdges.Add(edge.State, next); diff --git a/src/Microsoft.AspNetCore.Routing/Matching/DfaNode.cs b/src/Microsoft.AspNetCore.Routing/Matching/DfaNode.cs index ae939a13eb..36cd4e9bcd 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/DfaNode.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/DfaNode.cs @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public DfaNode() { Literals = new Dictionary(StringComparer.OrdinalIgnoreCase); - Matches = new List(); + Matches = new List(); PolicyEdges = new Dictionary(); } @@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Routing.Matching // Just for diagnostics and debugging public string Label { get; set; } - public List Matches { get; } + public List Matches { get; } public Dictionary Literals { get; } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/EndpointMetadataComparer.cs b/src/Microsoft.AspNetCore.Routing/Matching/EndpointMetadataComparer.cs index b2a7b9ec00..721d1816dd 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/EndpointMetadataComparer.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/EndpointMetadataComparer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing.Matching { diff --git a/src/Microsoft.AspNetCore.Routing/Matching/EndpointSelector.cs b/src/Microsoft.AspNetCore.Routing/Matching/EndpointSelector.cs index 436c3df6f5..d1f08ab207 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/EndpointSelector.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/EndpointSelector.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -21,13 +22,12 @@ namespace Microsoft.AspNetCore.Routing.Matching /// The . /// A that completes asynchronously once endpoint selection is complete. /// - /// An should assign the , - /// , and properties - /// once an endpoint is selected. + /// An should assign the + /// and properties once an endpoint is selected. /// public abstract Task SelectAsync( HttpContext httpContext, - IEndpointFeature feature, + EndpointFeature feature, CandidateSet candidates); } } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/HttpMethodMatcherPolicy.cs b/src/Microsoft.AspNetCore.Routing/Matching/HttpMethodMatcherPolicy.cs index 4a08df719b..64601108e7 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/HttpMethodMatcherPolicy.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/HttpMethodMatcherPolicy.cs @@ -250,8 +250,8 @@ namespace Microsoft.AspNetCore.Routing.Matching private Endpoint CreateRejectionEndpoint(IEnumerable httpMethods) { var allow = string.Join(", ", httpMethods); - return new MatcherEndpoint( - (next) => (context) => + return new RouteEndpoint( + (context) => { context.Response.StatusCode = 405; context.Response.Headers.Add("Allow", allow); diff --git a/src/Microsoft.AspNetCore.Routing/Matching/IEndpointComparerPolicy.cs b/src/Microsoft.AspNetCore.Routing/Matching/IEndpointComparerPolicy.cs index a1010c181c..a62cc8162d 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/IEndpointComparerPolicy.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/IEndpointComparerPolicy.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing.Matching { diff --git a/src/Microsoft.AspNetCore.Routing/Matching/INodeBuilderPolicy.cs b/src/Microsoft.AspNetCore.Routing/Matching/INodeBuilderPolicy.cs index 3c32b20aec..8be6cb75c9 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/INodeBuilderPolicy.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/INodeBuilderPolicy.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing.Matching { diff --git a/src/Microsoft.AspNetCore.Routing/Matching/Matcher.cs b/src/Microsoft.AspNetCore.Routing/Matching/Matcher.cs index 4a0928d1c6..0d84df9dd4 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/Matcher.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/Matcher.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -18,8 +19,8 @@ namespace Microsoft.AspNetCore.Routing.Matching /// The associated with the current request. /// /// The associated with the current request. The - /// will be mutated to contain the result of the operation. + /// will be mutated to contain the result of the operation. /// A which represents the asynchronous completion of the operation. - public abstract Task MatchAsync(HttpContext httpContext, IEndpointFeature feature); + public abstract Task MatchAsync(HttpContext httpContext, EndpointFeature feature); } } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/MatcherBuilder.cs b/src/Microsoft.AspNetCore.Routing/Matching/MatcherBuilder.cs index 84c22c59eb..c8368d0456 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/MatcherBuilder.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/MatcherBuilder.cs @@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Routing.Matching { internal abstract class MatcherBuilder { - public abstract void AddEndpoint(MatcherEndpoint endpoint); + public abstract void AddEndpoint(RouteEndpoint endpoint); public abstract Matcher Build(); } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/PolicyNodeEdge.cs b/src/Microsoft.AspNetCore.Routing/Matching/PolicyNodeEdge.cs index 2607b33d7e..419c390e05 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/PolicyNodeEdge.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/PolicyNodeEdge.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing.Matching { diff --git a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointComparer.cs b/src/Microsoft.AspNetCore.Routing/Matching/RouteEndpointComparer.cs similarity index 70% rename from src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointComparer.cs rename to src/Microsoft.AspNetCore.Routing/Matching/RouteEndpointComparer.cs index a03e81076d..95c897c373 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointComparer.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/RouteEndpointComparer.cs @@ -6,7 +6,7 @@ using System.Diagnostics; namespace Microsoft.AspNetCore.Routing.Matching { - // Use to sort and group MatcherEndpoints. + // Use to sort and group RouteEndpoints. // // NOTE: // When ordering endpoints, we compare the route templates as an absolute last resort. @@ -20,14 +20,14 @@ namespace Microsoft.AspNetCore.Routing.Matching // IComparer implementation considers the template string as a tiebreaker. // IEqualityComparer implementation does not. // This is cool and good. - internal class MatcherEndpointComparer : IComparer, IEqualityComparer + internal class RouteEndpointComparer : IComparer, IEqualityComparer { - private readonly IComparer[] _comparers; + private readonly IComparer[] _comparers; - public MatcherEndpointComparer(IEndpointComparerPolicy[] policies) + public RouteEndpointComparer(IEndpointComparerPolicy[] policies) { // Order, Precedence, (others)... - _comparers = new IComparer[2 + policies.Length]; + _comparers = new IComparer[2 + policies.Length]; _comparers[0] = OrderComparer.Instance; _comparers[1] = PrecedenceComparer.Instance; for (var i = 0; i < policies.Length; i++) @@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Routing.Matching } } - public int Compare(MatcherEndpoint x, MatcherEndpoint y) + public int Compare(RouteEndpoint x, RouteEndpoint y) { // We don't expose this publicly, and we should never call it on // a null endpoint. @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Routing.Matching return compare == 0 ? x.RoutePattern.RawText.CompareTo(y.RoutePattern.RawText) : compare; } - public bool Equals(MatcherEndpoint x, MatcherEndpoint y) + public bool Equals(RouteEndpoint x, RouteEndpoint y) { // We don't expose this publicly, and we should never call it on // a null endpoint. @@ -59,14 +59,14 @@ namespace Microsoft.AspNetCore.Routing.Matching return CompareCore(x, y) == 0; } - public int GetHashCode(MatcherEndpoint obj) + public int GetHashCode(RouteEndpoint obj) { // This should not be possible to call publicly. Debug.Fail("We don't expect this to be called."); throw new System.NotImplementedException(); } - private int CompareCore(MatcherEndpoint x, MatcherEndpoint y) + private int CompareCore(RouteEndpoint x, RouteEndpoint y) { for (var i = 0; i < _comparers.Length; i++) { @@ -80,21 +80,21 @@ namespace Microsoft.AspNetCore.Routing.Matching return 0; } - private class OrderComparer : IComparer + private class OrderComparer : IComparer { - public static readonly IComparer Instance = new OrderComparer(); + public static readonly IComparer Instance = new OrderComparer(); - public int Compare(MatcherEndpoint x, MatcherEndpoint y) + public int Compare(RouteEndpoint x, RouteEndpoint y) { return x.Order.CompareTo(y.Order); } } - private class PrecedenceComparer : IComparer + private class PrecedenceComparer : IComparer { - public static readonly IComparer Instance = new PrecedenceComparer(); + public static readonly IComparer Instance = new PrecedenceComparer(); - public int Compare(MatcherEndpoint x, MatcherEndpoint y) + public int Compare(RouteEndpoint x, RouteEndpoint y) { return x.RoutePattern.InboundPrecedence.CompareTo(y.RoutePattern.InboundPrecedence); } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpoint.cs b/src/Microsoft.AspNetCore.Routing/RouteEndpoint.cs similarity index 66% rename from src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpoint.cs rename to src/Microsoft.AspNetCore.Routing/RouteEndpoint.cs index ff5067cb81..a6750a2ef6 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpoint.cs +++ b/src/Microsoft.AspNetCore.Routing/RouteEndpoint.cs @@ -7,39 +7,34 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Patterns; -namespace Microsoft.AspNetCore.Routing.Matching +namespace Microsoft.AspNetCore.Routing { /// /// Represents an that can be used in URL matching or URL generation. /// - public sealed class MatcherEndpoint : Endpoint + public sealed class RouteEndpoint : Endpoint { - internal static readonly Func EmptyInvoker = (next) => - { - return (context) => Task.CompletedTask; - }; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The delegate to invoke to create a . + /// The delegate used to process requests for the endpoint. /// The to use in URL matching. /// The order assigned to the endpoint. /// /// The or metadata associated with the endpoint. /// /// The informational display name of the endpoint. - public MatcherEndpoint( - Func invoker, + public RouteEndpoint( + RequestDelegate requestDelegate, RoutePattern routePattern, int order, EndpointMetadataCollection metadata, string displayName) - : base(metadata, displayName) + : base(requestDelegate, metadata, displayName) { - if (invoker == null) + if (requestDelegate == null) { - throw new ArgumentNullException(nameof(invoker)); + throw new ArgumentNullException(nameof(requestDelegate)); } if (routePattern == null) @@ -47,16 +42,10 @@ namespace Microsoft.AspNetCore.Routing.Matching throw new ArgumentNullException(nameof(routePattern)); } - Invoker = invoker; RoutePattern = routePattern; Order = order; } - /// - /// Gets the invoker. The invoker is a delegate used to create a . - /// - public Func Invoker { get; } - /// /// Gets the order value of endpoint. /// diff --git a/src/Microsoft.AspNetCore.Routing/RouteValuesBasedEndpointFinder.cs b/src/Microsoft.AspNetCore.Routing/RouteValuesBasedEndpointFinder.cs index 2821c73aaf..a55e1b7274 100644 --- a/src/Microsoft.AspNetCore.Routing/RouteValuesBasedEndpointFinder.cs +++ b/src/Microsoft.AspNetCore.Routing/RouteValuesBasedEndpointFinder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Internal; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Template; @@ -56,7 +57,7 @@ namespace Microsoft.AspNetCore.Routing return matchResults .Select(matchResult => matchResult.Match) - .Select(match => (MatcherEndpoint)match.Entry.Data); + .Select(match => (RouteEndpoint)match.Entry.Data); } private void HandleChange() @@ -103,7 +104,7 @@ namespace Microsoft.AspNetCore.Routing var namedOutboundMatchResults = new Dictionary>( StringComparer.OrdinalIgnoreCase); - var endpoints = _endpointDataSource.Endpoints.OfType(); + var endpoints = _endpointDataSource.Endpoints.OfType(); foreach (var endpoint in endpoints) { // Do not consider an endpoint for link generation if the following marker metadata is on it @@ -135,7 +136,7 @@ namespace Microsoft.AspNetCore.Routing return (allOutboundMatches, namedOutboundMatchResults); } - private OutboundRouteEntry CreateOutboundRouteEntry(MatcherEndpoint endpoint) + private OutboundRouteEntry CreateOutboundRouteEntry(RouteEndpoint endpoint) { var routeValuesAddressMetadata = endpoint.Metadata.GetMetadata(); var entry = new OutboundRouteEntry() diff --git a/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/EndpointMetadataCollectionTests.cs b/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/EndpointMetadataCollectionTests.cs index 12c75020a4..9f37f3ebec 100644 --- a/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/EndpointMetadataCollectionTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/EndpointMetadataCollectionTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Text; +using Microsoft.AspNetCore.Http; using Xunit; namespace Microsoft.AspNetCore.Routing diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingBuilderExtensionsTest.cs index dd85fb11f6..028b8a6c60 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingBuilderExtensionsTest.cs @@ -5,6 +5,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder.Internal; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Microsoft.AspNetCore.Routing.Tests/CompositeEndpointDataSourceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/CompositeEndpointDataSourceTest.cs index a01ee921de..cd98416c4a 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/CompositeEndpointDataSourceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/CompositeEndpointDataSourceTest.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.TestObjects; @@ -146,14 +147,14 @@ namespace Microsoft.AspNetCore.Routing Assert.False(token.HasChanged); } - private MatcherEndpoint CreateEndpoint( + private RouteEndpoint CreateEndpoint( string template, object defaults = null, int order = 0, string routeName = null) { - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template, defaults, parameterPolicies: null), order, EndpointMetadataCollection.Empty, diff --git a/test/Microsoft.AspNetCore.Routing.Tests/DefaultEndpointDataSourceTests.cs b/test/Microsoft.AspNetCore.Routing.Tests/DefaultEndpointDataSourceTests.cs index 6e46dea578..09278332df 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/DefaultEndpointDataSourceTests.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/DefaultEndpointDataSourceTests.cs @@ -1,10 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNetCore.Routing.TestObjects; using System; using System.Collections.Generic; using System.Text; +using Microsoft.AspNetCore.Http; using Xunit; namespace Microsoft.AspNetCore.Routing @@ -16,8 +16,8 @@ namespace Microsoft.AspNetCore.Routing { // Arrange & Act var dataSource = new DefaultEndpointDataSource( - new TestEndpoint(EndpointMetadataCollection.Empty, "1"), - new TestEndpoint(EndpointMetadataCollection.Empty, "2") + new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "1"), + new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "2") ); // Assert @@ -32,8 +32,8 @@ namespace Microsoft.AspNetCore.Routing // Arrange & Act var dataSource = new DefaultEndpointDataSource(new List { - new TestEndpoint(EndpointMetadataCollection.Empty, "1"), - new TestEndpoint(EndpointMetadataCollection.Empty, "2") + new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "1"), + new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "2") }); // Assert diff --git a/test/Microsoft.AspNetCore.Routing.Tests/DefaultLinkGeneratorTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/DefaultLinkGeneratorTest.cs index 33f1807d64..2d82c439ee 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/DefaultLinkGeneratorTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/DefaultLinkGeneratorTest.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Constraints; using Microsoft.AspNetCore.Routing.Internal; using Microsoft.AspNetCore.Routing.Matching; @@ -25,7 +26,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_Success() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}"); var linkGenerator = CreateLinkGenerator(endpoint); // Act @@ -40,7 +41,7 @@ namespace Microsoft.AspNetCore.Routing { // Arrange var expectedMessage = "Could not find a matching endpoint to generate a link."; - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(endpoint); // Act & Assert @@ -53,7 +54,7 @@ namespace Microsoft.AspNetCore.Routing public void TryGetLink_Fail() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(endpoint); // Act @@ -70,9 +71,9 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_MultipleEndpoints_Success() { // Arrange - var endpoint1 = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{id?}"); - var endpoint2 = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); - var endpoint3 = EndpointFactory.CreateMatcherEndpoint("{controller}"); + var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}"); + var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); + var endpoint3 = EndpointFactory.CreateRouteEndpoint("{controller}"); var linkGenerator = CreateLinkGenerator(endpoint1, endpoint2, endpoint3); // Act @@ -86,9 +87,9 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_MultipleEndpoints_Success2() { // Arrange - var endpoint1 = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{id}"); - var endpoint2 = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); - var endpoint3 = EndpointFactory.CreateMatcherEndpoint("{controller}"); + var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}"); + var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); + var endpoint3 = EndpointFactory.CreateRouteEndpoint("{controller}"); var linkGenerator = CreateLinkGenerator(endpoint1, endpoint2, endpoint3); // Act @@ -102,7 +103,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_EncodesIntermediate_DefaultValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{p1}/{p2=a b}/{p3=foo}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{p1}/{p2=a b}/{p3=foo}"); var linkGenerator = CreateLinkGenerator(endpoint); // Act @@ -118,7 +119,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_EncodesValue_OfSingleAsteriskCatchAllParameter(string routeValue, string expected) { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{*path}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{*path}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home", action = "Index" }); @@ -142,7 +143,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_DoesNotEncodeSlashes_OfDoubleAsteriskCatchAllParameter(string routeValue, string expected) { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{**path}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{**path}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home", action = "Index" }); @@ -157,7 +158,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_EncodesContentOtherThanSlashes_OfDoubleAsteriskCatchAllParameter() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{**path}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{**path}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home", action = "Index" }); @@ -172,7 +173,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_EncodesValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home", action = "Index" }); @@ -187,7 +188,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_ForListOfStrings() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(endpoint); var context = CreateHttpContext(ambientValues: new { controller = "Home", action = "Index" }); @@ -202,7 +203,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_ForListOfInts() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home", action = "Index" }); @@ -217,7 +218,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_ForList_Empty() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home", action = "Index" }); @@ -232,7 +233,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_ForList_StringWorkaround() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home", action = "Index" }); @@ -249,7 +250,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_Success_AmbientValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home" }); @@ -264,7 +265,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_GeneratesLowercaseUrl_SetOnRouteOptions() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator(new[] { endpoint }, new RouteOptions() { LowercaseUrls = true }); var httpContext = CreateHttpContext(ambientValues: new { controller = "Home" }); @@ -279,7 +280,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_GeneratesLowercaseQueryString_SetOnRouteOptions() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { LowercaseUrls = true, LowercaseQueryStrings = true }); @@ -298,7 +299,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_GeneratesLowercaseQueryString_OnlyIfLowercaseUrlIsTrue_SetOnRouteOptions() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { LowercaseUrls = false, LowercaseQueryStrings = true }); @@ -317,7 +318,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_AppendsTrailingSlash_SetOnRouteOptions() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { AppendTrailingSlash = true }); @@ -334,7 +335,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_GeneratesLowercaseQueryStringAndTrailingSlash_SetOnRouteOptions() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { LowercaseUrls = true, LowercaseQueryStrings = true, AppendTrailingSlash = true }); @@ -353,7 +354,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_LowercaseUrlSetToTrue_OnRouteOptions_OverridenByCallsiteValue() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { LowercaseUrls = true }); @@ -376,7 +377,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_LowercaseUrlSetToFalse_OnRouteOptions_OverridenByCallsiteValue() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { LowercaseUrls = false }); @@ -399,7 +400,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_LowercaseUrlQueryStringsSetToTrue_OnRouteOptions_OverridenByCallsiteValue() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { LowercaseUrls = true, LowercaseQueryStrings = true }); @@ -423,7 +424,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_LowercaseUrlQueryStringsSetToFalse_OnRouteOptions_OverridenByCallsiteValue() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { LowercaseUrls = false, LowercaseQueryStrings = false }); @@ -447,7 +448,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_AppendTrailingSlashSetToFalse_OnRouteOptions_OverridenByCallsiteValue() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); var linkGenerator = CreateLinkGenerator( new[] { endpoint }, new RouteOptions() { AppendTrailingSlash = false }); @@ -470,7 +471,7 @@ namespace Microsoft.AspNetCore.Routing public void RouteGenerationRejectsConstraints() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "{p1}/{p2}", defaults: new { p2 = "catchall" }, constraints: new { p2 = "\\d{4}" }); @@ -491,7 +492,7 @@ namespace Microsoft.AspNetCore.Routing public void RouteGenerationAcceptsConstraints() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "{p1}/{p2}", defaults: new { p2 = "catchall" }, constraints: new { p2 = new RegexRouteConstraint("\\d{4}"), }); @@ -513,7 +514,7 @@ namespace Microsoft.AspNetCore.Routing public void RouteWithCatchAllRejectsConstraints() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "{p1}/{*p2}", defaults: new { p2 = "catchall" }, constraints: new { p2 = new RegexRouteConstraint("\\d{4}") }); @@ -534,7 +535,7 @@ namespace Microsoft.AspNetCore.Routing public void RouteWithCatchAllAcceptsConstraints() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "{p1}/{*p2}", defaults: new { p2 = "catchall" }, constraints: new { p2 = new RegexRouteConstraint("\\d{4}") }); @@ -567,7 +568,7 @@ namespace Microsoft.AspNetCore.Routing It.IsAny())) .Returns(true) .Verifiable(); - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "{p1}/{p2}", defaults: new { p2 = "catchall" }, constraints: new { p2 = target.Object }); @@ -593,7 +594,7 @@ namespace Microsoft.AspNetCore.Routing { // Arrange var constraint = new CapturingConstraint(); - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "slug/Home/Store", defaults: new { controller = "Home", action = "Store" }, constraints: new { c = constraint }); @@ -622,7 +623,7 @@ namespace Microsoft.AspNetCore.Routing { // Arrange var constraint = new CapturingConstraint(); - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "slug/Home/Store", defaults: new { controller = "Home", action = "Store", otherthing = "17" }, constraints: new { c = constraint }); @@ -645,7 +646,7 @@ namespace Microsoft.AspNetCore.Routing { // Arrange var constraint = new CapturingConstraint(); - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "slug/{controller}/{action}", defaults: new { action = "Index" }, constraints: new { c = constraint, }); @@ -669,7 +670,7 @@ namespace Microsoft.AspNetCore.Routing { // Arrange var constraint = new CapturingConstraint(); - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "slug/Home/Store", defaults: new { controller = "Home", action = "Store", otherthing = "17", thirdthing = "13" }, constraints: new { c = constraint, }); @@ -694,7 +695,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_InlineConstraints_Success() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "Home/Index/{id:int}", defaults: new { controller = "Home", action = "Index" }, constraints: new { }); @@ -714,7 +715,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_InlineConstraints_NonMatchingvalue() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "Home/Index/{id}", defaults: new { controller = "Home", action = "Index" }, constraints: new { id = "int" }); @@ -735,7 +736,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_InlineConstraints_OptionalParameter_ValuePresent() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "Home/Index/{id:int?}", defaults: new { controller = "Home", action = "Index" }, constraints: new { }); @@ -753,7 +754,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_InlineConstraints_OptionalParameter_ValueNotPresent() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "Home/Index/{id?}", defaults: new { controller = "Home", action = "Index" }, constraints: new { id = "int" }); @@ -771,7 +772,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_InlineConstraints_OptionalParameter_ValuePresent_ConstraintFails() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "Home/Index/{id?}", defaults: new { controller = "Home", action = "Index" }, constraints: new { id = "int" }); @@ -792,7 +793,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_InlineConstraints_MultipleInlineConstraints() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "Home/Index/{id:int:range(1,20)}", defaults: new { controller = "Home", action = "Index" }, constraints: new { }); @@ -812,7 +813,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_InlineConstraints_CompositeInlineConstraint_Fails() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "Home/Index/{id:int:range(1,20)}", defaults: new { controller = "Home", action = "Index" }, constraints: new { }); @@ -834,7 +835,7 @@ namespace Microsoft.AspNetCore.Routing { // Arrange var constraint = new MaxLengthRouteConstraint(20); - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "Home/Index/{name}", defaults: new { controller = "Home", action = "Index" }, constraints: new { name = constraint }); @@ -854,7 +855,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_OptionalParameter_ParameterPresentInValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{name?}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{name?}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { }); @@ -871,7 +872,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_OptionalParameter_ParameterNotPresentInValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{name?}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{name?}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { }); @@ -888,7 +889,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_OptionalParameter_ParameterPresentInValuesAndDefaults() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "{controller}/{action}/{name}", defaults: new { name = "default-products" }); var linkGenerator = CreateLinkGenerator(endpoint); @@ -907,7 +908,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_OptionalParameter_ParameterNotPresentInValues_PresentInDefaults() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "{controller}/{action}/{name}", defaults: new { name = "products" }); var linkGenerator = CreateLinkGenerator(endpoint); @@ -926,7 +927,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_ParameterNotPresentInTemplate_PresentInValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{name}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{name}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { }); @@ -943,7 +944,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_OptionalParameter_FollowedByDotAfterSlash_ParameterPresent() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( template: "{controller}/{action}/.{name?}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { }); @@ -961,7 +962,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_OptionalParameter_FollowedByDotAfterSlash_ParameterNotPresent() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/.{name?}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/.{name?}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { }); @@ -976,7 +977,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_OptionalParameter_InSimpleSegment() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("{controller}/{action}/{name?}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{name?}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { }); @@ -991,7 +992,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_TwoOptionalParameters_OneValueFromAmbientValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("a/{b=15}/{c?}/{d?}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("a/{b=15}/{c?}/{d?}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { c = "17" }); @@ -1006,7 +1007,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_OptionalParameterAfterDefault_OneValueFromAmbientValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("a/{b=15}/{c?}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("a/{b=15}/{c?}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { c = "17" }); @@ -1021,7 +1022,7 @@ namespace Microsoft.AspNetCore.Routing public void GetLink_TwoOptionalParametersAfterDefault_LastValueFromAmbientValues() { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint("a/{b=15}/{c?}/{d?}"); + var endpoint = EndpointFactory.CreateRouteEndpoint("a/{b=15}/{c?}/{d?}"); var linkGenerator = CreateLinkGenerator(endpoint); var httpContext = CreateHttpContext(ambientValues: new { d = "17" }); @@ -1114,7 +1115,7 @@ namespace Microsoft.AspNetCore.Routing object defaults) { // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "Products/Edit/{id}", requiredValues: requiredValues, defaults: defaults); @@ -1138,7 +1139,7 @@ namespace Microsoft.AspNetCore.Routing // Verifying that discarding works in general usage case i.e when keys are not like controller, action etc. // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "Products/Edit/{id}", requiredValues: new { c = "Products", a = "Edit" }, defaults: new { c = "Products", a = "Edit" }); @@ -1162,7 +1163,7 @@ namespace Microsoft.AspNetCore.Routing // Verifying that discarding works in general usage case i.e when keys are not like controller, action etc. // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "Products/Edit/{id}", requiredValues: new { c = "Products", a = "Edit" }, defaults: new { c = "Products", a = "Edit" }); @@ -1268,7 +1269,7 @@ namespace Microsoft.AspNetCore.Routing // Linking to a different action on the same controller // Arrange - var endpoint = EndpointFactory.CreateMatcherEndpoint( + var endpoint = EndpointFactory.CreateRouteEndpoint( "Products/Edit/{id}", requiredValues: requiredValues, defaults: defaults); @@ -1293,11 +1294,11 @@ namespace Microsoft.AspNetCore.Routing var services = GetBasicServices(); services.TryAddEnumerable( ServiceDescriptor.Singleton, EndpointFinderByName>()); - var endpoint1 = EndpointFactory.CreateMatcherEndpoint( + var endpoint1 = EndpointFactory.CreateRouteEndpoint( "Products/Details/{id}", requiredValues: new { controller = "Products", action = "Details" }, defaults: new { controller = "Products", action = "Details" }); - var endpoint2 = EndpointFactory.CreateMatcherEndpoint( + var endpoint2 = EndpointFactory.CreateRouteEndpoint( "Customers/Details/{id}", requiredValues: new { controller = "Customers", action = "Details" }, defaults: new { controller = "Customers", action = "Details" }, @@ -1324,11 +1325,11 @@ namespace Microsoft.AspNetCore.Routing var services = GetBasicServices(); services.TryAddEnumerable( ServiceDescriptor.Singleton, EndpointFinderByName>()); - var endpoint1 = EndpointFactory.CreateMatcherEndpoint( + var endpoint1 = EndpointFactory.CreateRouteEndpoint( "Products/Details/{id}", requiredValues: new { controller = "Products", action = "Details" }, defaults: new { controller = "Products", action = "Details" }); - var endpoint2 = EndpointFactory.CreateMatcherEndpoint( + var endpoint2 = EndpointFactory.CreateRouteEndpoint( "Customers/Details/{id}", requiredValues: new { controller = "Customers", action = "Details" }, defaults: new { controller = "Customers", action = "Details" }, @@ -1356,7 +1357,7 @@ namespace Microsoft.AspNetCore.Routing public void GetTemplate_ByRouteValues_ReturnsTemplate() { // Arrange - var endpoint1 = EndpointFactory.CreateMatcherEndpoint( + var endpoint1 = EndpointFactory.CreateRouteEndpoint( "Product/Edit/{id}", requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }, defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }); @@ -1379,7 +1380,7 @@ namespace Microsoft.AspNetCore.Routing public void GetTemplate_ByRouteName_ReturnsTemplate() { // Arrange - var endpoint1 = EndpointFactory.CreateMatcherEndpoint( + var endpoint1 = EndpointFactory.CreateRouteEndpoint( "Product/Edit/{id}", defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }, metadata: new RouteValuesAddressMetadata( @@ -1403,13 +1404,13 @@ namespace Microsoft.AspNetCore.Routing public void GetTemplate_ByRouteName_ReturnsTemplate_WithMultipleEndpoints() { // Arrange - var endpoint1 = EndpointFactory.CreateMatcherEndpoint( + var endpoint1 = EndpointFactory.CreateRouteEndpoint( "Product/Edit/{id}", defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }, metadata: new RouteValuesAddressMetadata( "default", new RouteValueDictionary(new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }))); - var endpoint2 = EndpointFactory.CreateMatcherEndpoint( + var endpoint2 = EndpointFactory.CreateRouteEndpoint( "Product/Details/{id}", defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }, metadata: new RouteValuesAddressMetadata( @@ -1436,11 +1437,11 @@ namespace Microsoft.AspNetCore.Routing var services = GetBasicServices(); services.TryAddEnumerable( ServiceDescriptor.Singleton, EndpointFinderByName>()); - var endpoint1 = EndpointFactory.CreateMatcherEndpoint( + var endpoint1 = EndpointFactory.CreateRouteEndpoint( "Product/Edit/{id}", requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }, defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }); - var endpoint2 = EndpointFactory.CreateMatcherEndpoint( + var endpoint2 = EndpointFactory.CreateRouteEndpoint( "Customers/Details/{id}", requiredValues: new { controller = "Customers", action = "Details" }, defaults: new { controller = "Customers", action = "Details" }, @@ -1466,11 +1467,11 @@ namespace Microsoft.AspNetCore.Routing var services = GetBasicServices(); services.TryAddEnumerable( ServiceDescriptor.Singleton, EndpointFinderByName>()); - var endpoint1 = EndpointFactory.CreateMatcherEndpoint( + var endpoint1 = EndpointFactory.CreateRouteEndpoint( "Product/Edit/{id}", requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }, defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }); - var endpoint2 = EndpointFactory.CreateMatcherEndpoint( + var endpoint2 = EndpointFactory.CreateRouteEndpoint( "Customers/Details/{id}", requiredValues: new { controller = "Customers", action = "Details" }, defaults: new { controller = "Customers", action = "Details" }, @@ -1500,7 +1501,7 @@ namespace Microsoft.AspNetCore.Routing public void MakeUrl_GeneratesLink_WithExtraRouteValues() { // Arrange - var endpoint1 = EndpointFactory.CreateMatcherEndpoint( + var endpoint1 = EndpointFactory.CreateRouteEndpoint( "Product/Edit/{id}", requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }, defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null }); @@ -1564,10 +1565,13 @@ namespace Microsoft.AspNetCore.Routing private HttpContext CreateHttpContext(object ambientValues) { var httpContext = new DefaultHttpContext(); - httpContext.Features.Set(new EndpointFeature + + var feature = new EndpointFeature { - Values = new RouteValueDictionary(ambientValues) - }); + RouteValues = new RouteValueDictionary(ambientValues) + }; + httpContext.Features.Set(feature); + httpContext.Features.Set(feature); return httpContext; } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/EndpointFactory.cs b/test/Microsoft.AspNetCore.Routing.Tests/EndpointFactory.cs index 6ff5f8b909..3ae4b79517 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/EndpointFactory.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/EndpointFactory.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNetCore.Routing.Matching; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Patterns; using System; using System.Collections.Generic; @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Routing { internal static class EndpointFactory { - public static MatcherEndpoint CreateMatcherEndpoint( + public static RouteEndpoint CreateRouteEndpoint( string template, object defaults = null, object constraints = null, @@ -25,8 +25,8 @@ namespace Microsoft.AspNetCore.Routing d.Add(new RouteValuesAddressMetadata(null, new RouteValueDictionary(requiredValues))); } - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template, defaults, constraints), order, new EndpointMetadataCollection(d), diff --git a/test/Microsoft.AspNetCore.Routing.Tests/EndpointFeatureTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/EndpointFeatureTest.cs index 5ffd868630..fb27335677 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/EndpointFeatureTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/EndpointFeatureTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Patterns; using Xunit; @@ -18,8 +19,8 @@ namespace Microsoft.AspNetCore.Routing var feature = new EndpointFeature() { - Endpoint = new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + Endpoint = new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse("/"), 0, new EndpointMetadataCollection(new DataTokensMetadata(expected)), @@ -40,8 +41,8 @@ namespace Microsoft.AspNetCore.Routing // Arrange var feature = new EndpointFeature() { - Endpoint = new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + Endpoint = new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse("/"), 0, new EndpointMetadataCollection(), diff --git a/test/Microsoft.AspNetCore.Routing.Tests/EndpointRoutingMiddlewareTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/EndpointRoutingMiddlewareTest.cs index 186eb9f0e3..1e2f1bbca3 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/EndpointRoutingMiddlewareTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/EndpointRoutingMiddlewareTest.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.TestObjects; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -19,8 +20,7 @@ namespace Microsoft.AspNetCore.Routing public async Task Invoke_OnCall_SetsEndpointFeature() { // Arrange - var httpContext = new DefaultHttpContext(); - httpContext.RequestServices = new TestServiceProvider(); + var httpContext = CreateHttpContext(); var middleware = CreateMiddleware(); @@ -43,8 +43,7 @@ namespace Microsoft.AspNetCore.Routing TestSink.EnableWithTypeName); var loggerFactory = new TestLoggerFactory(sink, enabled: true); - var httpContext = new DefaultHttpContext(); - httpContext.RequestServices = new TestServiceProvider(); + var httpContext = CreateHttpContext(); var logger = new Logger(loggerFactory); var middleware = CreateMiddleware(logger); @@ -62,8 +61,7 @@ namespace Microsoft.AspNetCore.Routing public async Task Invoke_BackCompatGetRouteValue_ValueUsedFromEndpointFeature() { // Arrange - var httpContext = new DefaultHttpContext(); - httpContext.RequestServices = new TestServiceProvider(); + var httpContext = CreateHttpContext(); var middleware = CreateMiddleware(); @@ -71,7 +69,7 @@ namespace Microsoft.AspNetCore.Routing await middleware.Invoke(httpContext); var routeData = httpContext.GetRouteData(); var routeValue = httpContext.GetRouteValue("controller"); - var endpointFeature = httpContext.Features.Get(); + var routeValuesFeature = httpContext.Features.Get(); // Assert Assert.NotNull(routeData); @@ -79,15 +77,14 @@ namespace Microsoft.AspNetCore.Routing // changing route data value is reflected in endpoint feature values routeData.Values["testKey"] = "testValue"; - Assert.Equal("testValue", endpointFeature.Values["testKey"]); + Assert.Equal("testValue", routeValuesFeature.RouteValues["testKey"]); } [Fact] public async Task Invoke_BackCompatGetDataTokens_ValueUsedFromEndpointMetadata() { // Arrange - var httpContext = new DefaultHttpContext(); - httpContext.RequestServices = new TestServiceProvider(); + var httpContext = CreateHttpContext(); var middleware = CreateMiddleware(); @@ -95,7 +92,7 @@ namespace Microsoft.AspNetCore.Routing await middleware.Invoke(httpContext); var routeData = httpContext.GetRouteData(); var routeValue = httpContext.GetRouteValue("controller"); - var endpointFeature = httpContext.Features.Get(); + var routeValuesFeature = httpContext.Features.Get(); // Assert Assert.NotNull(routeData); @@ -103,7 +100,20 @@ namespace Microsoft.AspNetCore.Routing // changing route data value is reflected in endpoint feature values routeData.Values["testKey"] = "testValue"; - Assert.Equal("testValue", endpointFeature.Values["testKey"]); + Assert.Equal("testValue", routeValuesFeature.RouteValues["testKey"]); + } + + private HttpContext CreateHttpContext() + { + var feature = new EndpointFeature(); + + var httpContext = new DefaultHttpContext(); + httpContext.Features.Set(feature); + httpContext.Features.Set(feature); + + httpContext.RequestServices = new TestServiceProvider(); + + return httpContext; } private EndpointRoutingMiddleware CreateMiddleware(Logger logger = null) diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcher.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcher.cs index df2d7b2a76..9b96df1ed8 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcher.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcher.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -19,7 +20,7 @@ namespace Microsoft.AspNetCore.Routing.Matching Matchers = matchers; } - public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { if (httpContext == null) { @@ -37,7 +38,7 @@ namespace Microsoft.AspNetCore.Routing.Matching if (Matchers[i].TryMatch(path)) { feature.Endpoint = Matchers[i].Endpoint; - feature.Values = new RouteValueDictionary(); + feature.RouteValues = new RouteValueDictionary(); } } @@ -46,12 +47,12 @@ namespace Microsoft.AspNetCore.Routing.Matching public sealed class InnerMatcher : Matcher { - public readonly MatcherEndpoint Endpoint; + public readonly RouteEndpoint Endpoint; private readonly string[] _segments; private readonly Candidate[] _candidates; - public InnerMatcher(string[] segments, MatcherEndpoint endpoint) + public InnerMatcher(string[] segments, RouteEndpoint endpoint) { _segments = segments; Endpoint = endpoint; @@ -120,12 +121,12 @@ namespace Microsoft.AspNetCore.Routing.Matching return Array.Empty(); } - public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { if (TryMatch(httpContext.Request.Path.Value)) { feature.Endpoint = Endpoint; - feature.Values = new RouteValueDictionary(); + feature.RouteValues = new RouteValueDictionary(); } return Task.CompletedTask; diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcherBuilder.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcherBuilder.cs index 0cde404142..d55d0dcdf0 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcherBuilder.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcherBuilder.cs @@ -11,9 +11,9 @@ namespace Microsoft.AspNetCore.Routing.Matching { internal class BarebonesMatcherBuilder : MatcherBuilder { - private List _endpoints = new List(); + private List _endpoints = new List(); - public override void AddEndpoint(MatcherEndpoint endpoint) + public override void AddEndpoint(RouteEndpoint endpoint) { _endpoints.Add(endpoint); } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcherConformanceTest.cs index c3f2b28968..bedc07a206 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/BarebonesMatcherConformanceTest.cs @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Routing.Matching return Task.CompletedTask; } - internal override Matcher CreateMatcher(params MatcherEndpoint[] endpoints) + internal override Matcher CreateMatcher(params RouteEndpoint[] endpoints) { var builder = new BarebonesMatcherBuilder(); for (int i = 0; i < endpoints.Length; i++) diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/CandidateSetTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/CandidateSetTest.cs index 1c5d751af5..b0f3eacd91 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/CandidateSetTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/CandidateSetTest.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Patterns; using Moq; using Xunit; @@ -24,7 +25,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public void Create_CreatesCandidateSet(int count) { // Arrange - var endpoints = new MatcherEndpoint[count]; + var endpoints = new RouteEndpoint[count]; for (var i = 0; i < endpoints.Length; i++) { endpoints[i] = CreateEndpoint($"/{i}"); @@ -60,7 +61,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public void Create_CreatesCandidateSet_TestConstructor(int count) { // Arrange - var endpoints = new MatcherEndpoint[count]; + var endpoints = new RouteEndpoint[count]; for (var i = 0; i < endpoints.Length; i++) { endpoints[i] = CreateEndpoint($"/{i}"); @@ -80,10 +81,10 @@ namespace Microsoft.AspNetCore.Routing.Matching } } - private MatcherEndpoint CreateEndpoint(string template) + private RouteEndpoint CreateEndpoint(string template) { - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template), 0, EndpointMetadataCollection.Empty, diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DataSourceDependentMatcherTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DataSourceDependentMatcherTest.cs index 74b87b56fc..fc72765748 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DataSourceDependentMatcherTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DataSourceDependentMatcherTest.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.TestObjects; using Xunit; @@ -34,8 +35,8 @@ namespace Microsoft.AspNetCore.Routing.Matching var dataSource = new DynamicEndpointDataSource(); var matcher = new DataSourceDependentMatcher(dataSource, TestMatcherBuilder.Create); - var endpoint = new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + var endpoint = new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse("a/b/c"), 0, EndpointMetadataCollection.Empty, @@ -52,11 +53,11 @@ namespace Microsoft.AspNetCore.Routing.Matching } [Fact] - public void Matcher_Ignores_NonMatcherEndpoint() + public void Matcher_Ignores_NonRouteEndpoint() { // Arrange var dataSource = new DynamicEndpointDataSource(); - var endpoint = new TestEndpoint(EndpointMetadataCollection.Empty, "test"); + var endpoint = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "test"); dataSource.AddEndpoint(endpoint); // Act @@ -72,8 +73,8 @@ namespace Microsoft.AspNetCore.Routing.Matching { // Arrange var dataSource = new DynamicEndpointDataSource(); - var endpoint = new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + var endpoint = new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse("/"), 0, new EndpointMetadataCollection(new SuppressMatchingMetadata()), @@ -116,9 +117,9 @@ namespace Microsoft.AspNetCore.Routing.Matching { public static Func Create = () => new TestMatcherBuilder(); - private List Endpoints { get; } = new List(); + private List Endpoints { get; } = new List(); - public override void AddEndpoint(MatcherEndpoint endpoint) + public override void AddEndpoint(RouteEndpoint endpoint) { Endpoints.Add(endpoint); } @@ -131,9 +132,9 @@ namespace Microsoft.AspNetCore.Routing.Matching private class TestMatcher : Matcher { - public IReadOnlyList Endpoints { get; set; } + public IReadOnlyList Endpoints { get; set; } - public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { throw new NotImplementedException(); } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DefaultEndpointSelectorTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DefaultEndpointSelectorTest.cs index 5ec095bc4e..c6ef7cd4f3 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DefaultEndpointSelectorTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DefaultEndpointSelectorTest.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Patterns; using Moq; using Xunit; @@ -15,7 +16,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public async Task SelectAsync_NoCandidates_DoesNothing() { // Arrange - var endpoints = new MatcherEndpoint[] { }; + var endpoints = new RouteEndpoint[] { }; var scores = new int[] { }; var candidateSet = CreateCandidateSet(endpoints, scores); @@ -33,7 +34,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public async Task SelectAsync_NoValidCandidates_DoesNothing() { // Arrange - var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test"), }; + var endpoints = new RouteEndpoint[] { CreateEndpoint("/test"), }; var scores = new int[] { 0, }; var candidateSet = CreateCandidateSet(endpoints, scores); @@ -48,14 +49,13 @@ namespace Microsoft.AspNetCore.Routing.Matching // Assert Assert.Null(feature.Endpoint); - Assert.Null(feature.Values); } [Fact] public async Task SelectAsync_SingleCandidate_ChoosesCandidate() { // Arrange - var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test"), }; + var endpoints = new RouteEndpoint[] { CreateEndpoint("/test"), }; var scores = new int[] { 0, }; var candidateSet = CreateCandidateSet(endpoints, scores); @@ -70,18 +70,16 @@ namespace Microsoft.AspNetCore.Routing.Matching // Assert Assert.Same(endpoints[0], feature.Endpoint); - Assert.Same(endpoints[0].Invoker, feature.Invoker); - Assert.NotNull(feature.Values); } [Fact] public async Task SelectAsync_SingleValidCandidate_ChoosesCandidate() { // Arrange - var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), }; + var endpoints = new RouteEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), }; var scores = new int[] { 0, 0 }; var candidateSet = CreateCandidateSet(endpoints, scores); - + candidateSet[0].IsValidCandidate = false; candidateSet[1].IsValidCandidate = true; @@ -99,7 +97,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public async Task SelectAsync_SingleValidCandidateInGroup_ChoosesCandidate() { // Arrange - var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), }; + var endpoints = new RouteEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), }; var scores = new int[] { 0, 0, 1 }; var candidateSet = CreateCandidateSet(endpoints, scores); @@ -121,7 +119,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public async Task SelectAsync_ManyGroupsLastCandidate_ChoosesCandidate() { // Arrange - var endpoints = new MatcherEndpoint[] + var endpoints = new RouteEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), @@ -152,7 +150,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public async Task SelectAsync_MultipleValidCandidatesInGroup_ReportsAmbiguity() { // Arrange - var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), }; + var endpoints = new RouteEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), }; var scores = new int[] { 0, 1, 1 }; var candidateSet = CreateCandidateSet(endpoints, scores); @@ -179,7 +177,7 @@ test: /test3", ex.Message); public async Task SelectAsync_RunsEndpointSelectorPolicies() { // Arrange - var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), }; + var endpoints = new RouteEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), }; var scores = new int[] { 0, 0, 1 }; var candidateSet = CreateCandidateSet(endpoints, scores); @@ -206,22 +204,27 @@ test: /test3", ex.Message); Assert.Same(endpoints[2], feature.Endpoint); } - private static (HttpContext httpContext, IEndpointFeature feature) CreateContext() + private static (HttpContext httpContext, EndpointFeature feature) CreateContext() { - return (new DefaultHttpContext(), new EndpointFeature()); + var feature = new EndpointFeature(); + var httpContext = new DefaultHttpContext(); + httpContext.Features.Set(feature); + httpContext.Features.Set(feature); + + return (httpContext, feature); } - private static MatcherEndpoint CreateEndpoint(string template) + private static RouteEndpoint CreateEndpoint(string template) { - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template), 0, EndpointMetadataCollection.Empty, $"test: {template}"); } - private static CandidateSet CreateCandidateSet(MatcherEndpoint[] endpoints, int[] scores) + private static CandidateSet CreateCandidateSet(RouteEndpoint[] endpoints, int[] scores) { return new CandidateSet(endpoints, scores); } @@ -231,4 +234,4 @@ test: /test3", ex.Message); return new DefaultEndpointSelector(policies); } } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherBuilderTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherBuilderTest.cs index f9581a067b..430a2d92d9 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherBuilderTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Constraints; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.Extensions.Options; @@ -876,14 +877,14 @@ namespace Microsoft.AspNetCore.Routing.Matching policies); } - private MatcherEndpoint CreateEndpoint( + private RouteEndpoint CreateEndpoint( string template, object defaults = null, object constraints = null, params object[] metadata) { - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints)), 0, new EndpointMetadataCollection(metadata), diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherConformanceTest.cs index 2aa04fb882..5d44e62ab0 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherConformanceTest.cs @@ -20,10 +20,10 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, keys, values); } - internal override Matcher CreateMatcher(params MatcherEndpoint[] endpoints) + internal override Matcher CreateMatcher(params RouteEndpoint[] endpoints) { var services = new ServiceCollection() .AddLogging() diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherTest.cs index 1fcd86f89c..43046764db 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/DfaMatcherTest.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.Extensions.DependencyInjection; using Moq; @@ -15,10 +16,10 @@ namespace Microsoft.AspNetCore.Routing.Matching // so we're reusing the services here. public class DfaMatcherTest { - private MatcherEndpoint CreateEndpoint(string template, int order, object defaults = null, EndpointMetadataCollection metadata = null) + private RouteEndpoint CreateEndpoint(string template, int order, object defaults = null, EndpointMetadataCollection metadata = null) { - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template, defaults, parameterPolicies: null), order, metadata ?? EndpointMetadataCollection.Empty, @@ -54,11 +55,9 @@ namespace Microsoft.AspNetCore.Routing.Matching var matcher = CreateDfaMatcher(endpointDataSource); - var httpContext = new DefaultHttpContext(); + var (httpContext, endpointFeature) = CreateHttpContext(); httpContext.Request.Path = "/1"; - var endpointFeature = new EndpointFeature(); - // Act await matcher.MatchAsync(httpContext, endpointFeature); @@ -77,11 +76,9 @@ namespace Microsoft.AspNetCore.Routing.Matching var matcher = CreateDfaMatcher(endpointDataSource); - var httpContext = new DefaultHttpContext(); + var (httpContext, endpointFeature) = CreateHttpContext(); httpContext.Request.Path = "/One"; - var endpointFeature = new EndpointFeature(); - // Act await matcher.MatchAsync(httpContext, endpointFeature); @@ -104,11 +101,9 @@ namespace Microsoft.AspNetCore.Routing.Matching var matcher = CreateDfaMatcher(endpointDataSource); - var httpContext = new DefaultHttpContext(); + var (httpContext, endpointFeature) = CreateHttpContext(); httpContext.Request.Path = "/Teams"; - var endpointFeature = new EndpointFeature(); - // Act await matcher.MatchAsync(httpContext, endpointFeature); @@ -125,7 +120,7 @@ namespace Microsoft.AspNetCore.Routing.Matching var endpointSelector = new Mock(); endpointSelector - .Setup(s => s.SelectAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Setup(s => s.SelectAsync(It.IsAny(), It.IsAny(), It.IsAny())) .Callback((c, f, cs) => { Assert.Equal(2, cs.Count); @@ -152,16 +147,25 @@ namespace Microsoft.AspNetCore.Routing.Matching var matcher = CreateDfaMatcher(endpointDataSource, endpointSelector.Object); - var httpContext = new DefaultHttpContext(); + var (httpContext, endpointFeature) = CreateHttpContext(); httpContext.Request.Path = "/Teams"; - var endpointFeature = new EndpointFeature(); - // Act await matcher.MatchAsync(httpContext, endpointFeature); // Assert Assert.Equal(endpoint2, endpointFeature.Endpoint); } + + private (HttpContext httpContext, EndpointFeature feature) CreateHttpContext() + { + var feature = new EndpointFeature(); + + var httpContext = new DefaultHttpContext(); + httpContext.Features.Set(feature); + httpContext.Features.Set(feature); + + return (httpContext, feature); + } } } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/EndpointMetadataComparerTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/EndpointMetadataComparerTest.cs index f36ce81cba..918262e469 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/EndpointMetadataComparerTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/EndpointMetadataComparerTest.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using Microsoft.AspNetCore.Routing.TestObjects; +using Microsoft.AspNetCore.Http; using Xunit; namespace Microsoft.AspNetCore.Routing.Matching @@ -13,8 +13,8 @@ namespace Microsoft.AspNetCore.Routing.Matching public void Compare_EndpointWithMetadata_MoreSpecific() { // Arrange - var endpoint1 = new TestEndpoint(new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test1"); - var endpoint2 = new TestEndpoint(new EndpointMetadataCollection(new object[] { }), "test2"); + var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test1"); + var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { }), "test2"); // Act var result = EndpointMetadataComparer.Default.Compare(endpoint1, endpoint2); @@ -27,8 +27,8 @@ namespace Microsoft.AspNetCore.Routing.Matching public void Compare_EndpointWithMetadata_ReverseOrder_MoreSpecific() { // Arrange - var endpoint1 = new TestEndpoint(new EndpointMetadataCollection(new object[] { }), "test1"); - var endpoint2 = new TestEndpoint(new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test2"); + var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { }), "test1"); + var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test2"); // Act var result = EndpointMetadataComparer.Default.Compare(endpoint1, endpoint2); @@ -41,8 +41,8 @@ namespace Microsoft.AspNetCore.Routing.Matching public void Compare_BothEndpointsWithMetadata_Equal() { // Arrange - var endpoint1 = new TestEndpoint(new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test1"); - var endpoint2 = new TestEndpoint(new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test2"); + var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test1"); + var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test2"); // Act var result = EndpointMetadataComparer.Default.Compare(endpoint1, endpoint2); @@ -55,8 +55,8 @@ namespace Microsoft.AspNetCore.Routing.Matching public void Compare_BothEndpointsWithoutMetadata_Equal() { // Arrange - var endpoint1 = new TestEndpoint(new EndpointMetadataCollection(new object[] { }), "test1"); - var endpoint2 = new TestEndpoint(new EndpointMetadataCollection(new object[] { }), "test2"); + var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { }), "test1"); + var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { }), "test2"); // Act var result = EndpointMetadataComparer.Default.Compare(endpoint1, endpoint2); @@ -69,8 +69,8 @@ namespace Microsoft.AspNetCore.Routing.Matching public void Sort_EndpointWithMetadata_FirstInList() { // Arrange - var endpoint1 = new TestEndpoint(new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test1"); - var endpoint2 = new TestEndpoint(new EndpointMetadataCollection(new object[] { }), "test2"); + var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { new TestMetadata(), }), "test1"); + var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, new EndpointMetadataCollection(new object[] { }), "test2"); var list = new List() { endpoint2, endpoint1, }; diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/FullFeaturedMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/FullFeaturedMatcherConformanceTest.cs index 4048c7827e..b831720e67 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/FullFeaturedMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/FullFeaturedMatcherConformanceTest.cs @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, keys, values); } [Fact] @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, new { b = "17", c = "18", }); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, new { b = "17", c = "18", }); } [Fact] @@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, new { b = "17", c = "18", d = "19" }); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, new { b = "17", c = "18", d = "19" }); } [Theory] @@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } [Theory] @@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, keys, values); } [Theory] @@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } [Theory] @@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, keys, values); } // Historically catchall segments don't match an empty segment, but only if it's @@ -188,7 +188,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); // Need to access these to prevent a warning from the xUnit analyzer. // Some of these tests will match (and process the values) and some will not. @@ -223,7 +223,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, keys, values); } [Theory] @@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } [Theory] @@ -272,7 +272,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, keys, values); } [Theory] @@ -298,7 +298,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } // Most of are copied from old routing tests that date back to the VS 2010 era. Enjoy! @@ -323,7 +323,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, keys, values); } [Theory] @@ -353,7 +353,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, expected, ignoreValues: true); + MatcherAssert.AssertMatch(feature, httpContext, expected, ignoreValues: true); } [Theory] @@ -387,7 +387,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, expected, ignoreValues: true); + MatcherAssert.AssertMatch(feature, httpContext, expected, ignoreValues: true); } [Theory] @@ -440,7 +440,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, expected, ignoreValues: true); + MatcherAssert.AssertMatch(feature, httpContext, expected, ignoreValues: true); } } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/HttpMethodMatcherPolicyIntegrationTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/HttpMethodMatcherPolicyIntegrationTest.cs index 5d5c0eccd8..6d271b5c83 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/HttpMethodMatcherPolicyIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/HttpMethodMatcherPolicyIntegrationTest.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.Extensions.DependencyInjection; using Xunit; @@ -28,7 +29,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] @@ -44,7 +45,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] @@ -60,7 +61,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } @@ -94,7 +95,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] @@ -110,7 +111,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] @@ -126,7 +127,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] @@ -142,7 +143,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] // This matches because the endpoint accepts OPTIONS @@ -158,7 +159,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] @@ -174,7 +175,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] // When all of the candidates handles specific verbs, use a 405 endpoint @@ -197,7 +198,7 @@ namespace Microsoft.AspNetCore.Routing.Matching Assert.Same(HttpMethodMatcherPolicy.Http405EndpointDisplayName, feature.Endpoint.DisplayName); // Invoke the endpoint - await feature.Invoker((c) => Task.CompletedTask)(httpContext); + await feature.Endpoint.RequestDelegate(httpContext); Assert.Equal(405, httpContext.Response.StatusCode); Assert.Equal("DELETE, GET, PUT", httpContext.Response.Headers["Allow"]); } @@ -216,7 +217,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } [Fact] // When one of the candidates handles all verbs, dont use a 405 endpoint @@ -233,7 +234,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } [Fact] @@ -250,7 +251,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint1); + MatcherAssert.AssertMatch(feature, httpContext, endpoint1); } [Fact] @@ -267,7 +268,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint1); + MatcherAssert.AssertMatch(feature, httpContext, endpoint1); } [Fact] // The non-http-method-specific endpoint is part of the same candidate set @@ -284,10 +285,10 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint2, ignoreValues: true); + MatcherAssert.AssertMatch(feature, httpContext, endpoint2, ignoreValues: true); } - private static Matcher CreateMatcher(params MatcherEndpoint[] endpoints) + private static Matcher CreateMatcher(params RouteEndpoint[] endpoints) { var services = new ServiceCollection() .AddOptions() @@ -304,7 +305,7 @@ namespace Microsoft.AspNetCore.Routing.Matching return builder.Build(); } - internal static (HttpContext httpContext, IEndpointFeature feature) CreateContext( + internal static (HttpContext httpContext, EndpointFeature feature) CreateContext( string path, string httpMethod, bool corsPreflight = false) @@ -321,10 +322,11 @@ namespace Microsoft.AspNetCore.Routing.Matching var feature = new EndpointFeature(); httpContext.Features.Set(feature); + httpContext.Features.Set(feature); return (httpContext, feature); } - internal static MatcherEndpoint CreateEndpoint( + internal static RouteEndpoint CreateEndpoint( string template, object defaults = null, object constraints = null, @@ -339,15 +341,15 @@ namespace Microsoft.AspNetCore.Routing.Matching } var displayName = "endpoint: " + template + " " + string.Join(", ", httpMethods ?? new[] { "(any)" }); - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template, defaults, constraints), order, new EndpointMetadataCollection(metadata), displayName); } - internal (Matcher matcher, MatcherEndpoint endpoint) CreateMatcher(string template) + internal (Matcher matcher, RouteEndpoint endpoint) CreateMatcher(string template) { var endpoint = CreateEndpoint(template); return (CreateMatcher(endpoint), endpoint); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/HttpMethodMatcherPolicyTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/HttpMethodMatcherPolicyTest.cs index e8c7121597..070147fee1 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/HttpMethodMatcherPolicyTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/HttpMethodMatcherPolicyTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Patterns; using Xunit; using static Microsoft.AspNetCore.Routing.Matching.HttpMethodMatcherPolicy; @@ -276,7 +277,7 @@ namespace Microsoft.AspNetCore.Routing.Matching }); } - private static MatcherEndpoint CreateEndpoint(string template, HttpMethodMetadata httpMethodMetadata) + private static RouteEndpoint CreateEndpoint(string template, HttpMethodMetadata httpMethodMetadata) { var metadata = new List(); if (httpMethodMetadata != null) @@ -284,8 +285,8 @@ namespace Microsoft.AspNetCore.Routing.Matching metadata.Add(httpMethodMetadata); } - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template), 0, new EndpointMetadataCollection(metadata), diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherAssert.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherAssert.cs index 5917ab4619..e760c71739 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherAssert.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherAssert.cs @@ -4,28 +4,30 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Xunit.Sdk; namespace Microsoft.AspNetCore.Routing.Matching { internal static class MatcherAssert { - public static void AssertMatch(IEndpointFeature feature, Endpoint expected) + public static void AssertMatch(EndpointFeature feature, HttpContext context, Endpoint expected) { - AssertMatch(feature, expected, new RouteValueDictionary()); + AssertMatch(feature, context, expected, new RouteValueDictionary()); } - public static void AssertMatch(IEndpointFeature feature, Endpoint expected, bool ignoreValues) + public static void AssertMatch(EndpointFeature feature, HttpContext context, Endpoint expected, bool ignoreValues) { - AssertMatch(feature, expected, new RouteValueDictionary(), ignoreValues); + AssertMatch(feature, context, expected, new RouteValueDictionary(), ignoreValues); } - public static void AssertMatch(IEndpointFeature feature, Endpoint expected, object values) + public static void AssertMatch(EndpointFeature feature, HttpContext context, Endpoint expected, object values) { - AssertMatch(feature, expected, new RouteValueDictionary(values)); + AssertMatch(feature, context, expected, new RouteValueDictionary(values)); } - public static void AssertMatch(IEndpointFeature feature, Endpoint expected, string[] keys, string[] values) + public static void AssertMatch(EndpointFeature feature, HttpContext context, Endpoint expected, string[] keys, string[] values) { keys = keys ?? Array.Empty(); values = values ?? Array.Empty(); @@ -36,11 +38,12 @@ namespace Microsoft.AspNetCore.Routing.Matching } var zipped = keys.Zip(values, (k, v) => new KeyValuePair(k, v)); - AssertMatch(feature, expected, new RouteValueDictionary(zipped)); + AssertMatch(feature, context, expected, new RouteValueDictionary(zipped)); } public static void AssertMatch( - IEndpointFeature feature, + EndpointFeature feature, + HttpContext context, Endpoint expected, RouteValueDictionary values, bool ignoreValues = false) @@ -50,39 +53,41 @@ namespace Microsoft.AspNetCore.Routing.Matching throw new XunitException($"Was expected to match '{expected.DisplayName}' but did not match."); } - if (feature.Values == null) + var actualValues = context.Features.Get().RouteValues; + + if (actualValues == null) { - throw new XunitException("Values is null."); + throw new XunitException("RouteValues is null."); } if (!object.ReferenceEquals(expected, feature.Endpoint)) { throw new XunitException( $"Was expected to match '{expected.DisplayName}' but matched " + - $"'{feature.Endpoint.DisplayName}' with values: {FormatRouteValues(feature.Values)}."); + $"'{feature.Endpoint.DisplayName}' with values: {FormatRouteValues(actualValues)}."); } if (!ignoreValues) { // Note: this comparison is intended for unit testing, and is stricter than necessary to make tests // more precise. Route value comparisons in product code are more flexible than a simple .Equals. - if (values.Count != feature.Values.Count || - !values.OrderBy(kvp => kvp.Key).SequenceEqual(feature.Values.OrderBy(kvp => kvp.Key))) + if (values.Count != actualValues.Count || + !values.OrderBy(kvp => kvp.Key).SequenceEqual(actualValues.OrderBy(kvp => kvp.Key))) { throw new XunitException( $"Was expected to match '{expected.DisplayName}' with values {FormatRouteValues(values)} but matched " + - $"values: {FormatRouteValues(feature.Values)}."); + $"values: {FormatRouteValues(actualValues)}."); } } } - public static void AssertNotMatch(IEndpointFeature feature) + public static void AssertNotMatch(EndpointFeature feature, HttpContext context) { if (feature.Endpoint != null) { throw new XunitException( $"Was expected not to match '{feature.Endpoint.DisplayName}' " + - $"but matched with values: {FormatRouteValues(feature.Values)}."); + $"but matched with values: {FormatRouteValues(context.Features.Get().RouteValues)}."); } } @@ -91,4 +96,4 @@ namespace Microsoft.AspNetCore.Routing.Matching return "{" + string.Join(", ", values.Select(kvp => $"{kvp.Key} = '{kvp.Value}'")) + "}"; } } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.SingleEndpoint.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.SingleEndpoint.cs index 580494b49c..17b569e261 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.SingleEndpoint.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.SingleEndpoint.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Fact] @@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Theory] @@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } // Some matchers will optimize for the ASCII case @@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } // Matchers should operate on the decoded representation - a matcher that calls @@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } [Theory] @@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } [Theory] @@ -136,7 +136,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } // Matchers do their own 'splitting' of the path into segments, so including @@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, httpContext, endpoint); } // Matchers do their own 'splitting' of the path into segments, so including @@ -190,7 +190,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } [Fact] @@ -205,7 +205,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, values); } [Fact] @@ -220,7 +220,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, values); } [Fact] @@ -235,7 +235,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, values); } [Fact] @@ -255,7 +255,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, values); } [Theory] @@ -273,7 +273,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } [Theory] @@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, httpContext, endpoint, keys, values); } [Theory] @@ -323,7 +323,7 @@ namespace Microsoft.AspNetCore.Routing.Matching await matcher.MatchAsync(httpContext, feature); // Assert - MatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature, httpContext); } } } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.cs index 9dbc881548..45673bb525 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.Extensions.DependencyInjection; @@ -11,9 +12,9 @@ namespace Microsoft.AspNetCore.Routing.Matching { public abstract partial class MatcherConformanceTest { - internal abstract Matcher CreateMatcher(params MatcherEndpoint[] endpoints); + internal abstract Matcher CreateMatcher(params RouteEndpoint[] endpoints); - internal static (HttpContext httpContext, IEndpointFeature feature) CreateContext(string path) + internal static (HttpContext httpContext, EndpointFeature feature) CreateContext(string path) { var httpContext = new DefaultHttpContext(); httpContext.Request.Method = "TEST"; @@ -22,6 +23,7 @@ namespace Microsoft.AspNetCore.Routing.Matching var feature = new EndpointFeature(); httpContext.Features.Set(feature); + httpContext.Features.Set(feature); return (httpContext, feature); } @@ -34,21 +36,21 @@ namespace Microsoft.AspNetCore.Routing.Matching return services.BuildServiceProvider(); } - internal static MatcherEndpoint CreateEndpoint( + internal static RouteEndpoint CreateEndpoint( string template, object defaults = null, object constraints = null, int? order = null) { - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template, defaults, constraints), order ?? 0, EndpointMetadataCollection.Empty, "endpoint: " + template); } - internal (Matcher matcher, MatcherEndpoint endpoint) CreateMatcher(string template) + internal (Matcher matcher, RouteEndpoint endpoint) CreateMatcher(string template) { var endpoint = CreateEndpoint(template); return (CreateMatcher(endpoint), endpoint); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointComparerTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteEndpointComparerTest.cs similarity index 93% rename from test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointComparerTest.cs rename to test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteEndpointComparerTest.cs index 96539d8304..92d6e22e68 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointComparerTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteEndpointComparerTest.cs @@ -2,12 +2,13 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Patterns; using Xunit; namespace Microsoft.AspNetCore.Routing.Matching { - public class MatcherEndpointComparerTest + public class RouteEndpointComparerTest { [Fact] public void Compare_PrefersOrder_IfDifferent() @@ -198,7 +199,7 @@ namespace Microsoft.AspNetCore.Routing.Matching var endpoint7 = CreateEndpoint("/bar{baz}", order: 0, new TestMetadata1(), new TestMetadata2()); // Endpoints listed in reverse of the desired order. - var list = new List() { endpoint7, endpoint6, endpoint5, endpoint4, endpoint3, endpoint2, endpoint1, }; + var list = new List() { endpoint7, endpoint6, endpoint5, endpoint4, endpoint3, endpoint2, endpoint1, }; var comparer = CreateComparer(new TestMetadata1Policy(), new TestMetadata2Policy()); @@ -217,19 +218,19 @@ namespace Microsoft.AspNetCore.Routing.Matching e => Assert.Same(endpoint7, e)); } - private static MatcherEndpoint CreateEndpoint(string template, int order, params object[] metadata) + private static RouteEndpoint CreateEndpoint(string template, int order, params object[] metadata) { - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template), order, new EndpointMetadataCollection(metadata), "test: " + template); } - private static MatcherEndpointComparer CreateComparer(params IEndpointComparerPolicy[] policies) + private static RouteEndpointComparer CreateComparer(params IEndpointComparerPolicy[] policies) { - return new MatcherEndpointComparer(policies); + return new RouteEndpointComparer(policies); } private class TestMetadata1 diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcher.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcher.cs index e7f3cb7711..88395c2eff 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcher.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcher.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; namespace Microsoft.AspNetCore.Routing.Matching { @@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Routing.Matching _inner = inner; } - public async override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public async override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { if (httpContext == null) { @@ -34,7 +35,7 @@ namespace Microsoft.AspNetCore.Routing.Matching if (context.Handler != null) { - feature.Values = context.RouteData.Values; + feature.RouteValues = context.RouteData.Values; await context.Handler(httpContext); } } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcherBuilder.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcherBuilder.cs index 57394517bf..ba8d46a920 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcherBuilder.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcherBuilder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.Extensions.Options; @@ -13,15 +14,15 @@ namespace Microsoft.AspNetCore.Routing.Matching internal class RouteMatcherBuilder : MatcherBuilder { private readonly IInlineConstraintResolver _constraintResolver; - private readonly List _endpoints; + private readonly List _endpoints; public RouteMatcherBuilder() { _constraintResolver = new DefaultInlineConstraintResolver(Options.Create(new RouteOptions())); - _endpoints = new List(); + _endpoints = new List(); } - public override void AddEndpoint(MatcherEndpoint endpoint) + public override void AddEndpoint(RouteEndpoint endpoint) { _endpoints.Add(endpoint); } @@ -73,10 +74,10 @@ namespace Microsoft.AspNetCore.Routing.Matching private class SelectorRouter : IRouter { private readonly EndpointSelector _selector; - private readonly MatcherEndpoint[] _candidates; + private readonly RouteEndpoint[] _candidates; private readonly int[] _scores; - public SelectorRouter(EndpointSelector selector, MatcherEndpoint[] candidates) + public SelectorRouter(EndpointSelector selector, RouteEndpoint[] candidates) { _selector = selector; _candidates = candidates; @@ -91,7 +92,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public async Task RouteAsync(RouteContext context) { - var feature = context.HttpContext.Features.Get(); + var feature = (EndpointFeature)context.HttpContext.Features.Get(); // This is needed due to a quirk of our tests - they reuse the endpoint feature // across requests. diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcherConformanceTest.cs index 8c3233e4cf..5daf2cae95 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/RouteMatcherConformanceTest.cs @@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Routing.Matching { public class RouteMatcherConformanceTest : FullFeaturedMatcherConformanceTest { - internal override Matcher CreateMatcher(params MatcherEndpoint[] endpoints) + internal override Matcher CreateMatcher(params RouteEndpoint[] endpoints) { var builder = new RouteMatcherBuilder(); for (int i = 0; i < endpoints.Length; i++) diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcher.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcher.cs index 7e27f454c1..3c8c10daa0 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcher.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcher.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Tree; namespace Microsoft.AspNetCore.Routing.Matching @@ -18,7 +19,7 @@ namespace Microsoft.AspNetCore.Routing.Matching _inner = inner; } - public async override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public async override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { if (httpContext == null) { @@ -35,7 +36,7 @@ namespace Microsoft.AspNetCore.Routing.Matching if (context.Handler != null) { - feature.Values = context.RouteData.Values; + feature.RouteValues = context.RouteData.Values; await context.Handler(httpContext); } } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcherBuilder.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcherBuilder.cs index e9c5b7ddc5..b151d4cf4e 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcherBuilder.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcherBuilder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Internal; using Microsoft.AspNetCore.Routing.Template; using Microsoft.AspNetCore.Routing.Tree; @@ -16,14 +17,14 @@ namespace Microsoft.AspNetCore.Routing.Matching { internal class TreeRouterMatcherBuilder : MatcherBuilder { - private readonly List _endpoints; + private readonly List _endpoints; public TreeRouterMatcherBuilder() { - _endpoints = new List(); + _endpoints = new List(); } - public override void AddEndpoint(MatcherEndpoint endpoint) + public override void AddEndpoint(RouteEndpoint endpoint) { _endpoints.Add(endpoint); } @@ -48,7 +49,7 @@ namespace Microsoft.AspNetCore.Routing.Matching { var candidates = group.ToArray(); - // MatcherEndpoint.Values contains the default values parsed from the template + // RouteEndpoint.Values contains the default values parsed from the template // as well as those specified with a literal. We need to separate those // for legacy cases. var endpoint = group.First(); @@ -75,10 +76,10 @@ namespace Microsoft.AspNetCore.Routing.Matching private class SelectorRouter : IRouter { private readonly EndpointSelector _selector; - private readonly MatcherEndpoint[] _candidates; + private readonly RouteEndpoint[] _candidates; private readonly int[] _scores; - public SelectorRouter(EndpointSelector selector, MatcherEndpoint[] candidates) + public SelectorRouter(EndpointSelector selector, RouteEndpoint[] candidates) { _selector = selector; _candidates = candidates; @@ -93,7 +94,7 @@ namespace Microsoft.AspNetCore.Routing.Matching public async Task RouteAsync(RouteContext context) { - var feature = context.HttpContext.Features.Get(); + var feature = (EndpointFeature)context.HttpContext.Features.Get(); // This is needed due to a quirk of our tests - they reuse the endpoint feature. feature.Endpoint = null; diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcherConformanceTest.cs index f4c346edd4..e2c3a73108 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/TreeRouterMatcherConformanceTest.cs @@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Routing.Matching return Task.CompletedTask; } - internal override Matcher CreateMatcher(params MatcherEndpoint[] endpoints) + internal override Matcher CreateMatcher(params RouteEndpoint[] endpoints) { var builder = new TreeRouterMatcherBuilder(); for (var i = 0; i < endpoints.Length; i++) diff --git a/test/Microsoft.AspNetCore.Routing.Tests/RouteValueBasedEndpointFinderTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/RouteValueBasedEndpointFinderTest.cs index 60712a0fe7..5b475247bb 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/RouteValueBasedEndpointFinderTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/RouteValueBasedEndpointFinderTest.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Internal; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Patterns; @@ -34,7 +35,7 @@ namespace Microsoft.AspNetCore.Routing Assert.NotNull(finder.NamedMatches); Assert.True(finder.NamedMatches.TryGetValue("named", out var namedMatches)); var namedMatch = Assert.Single(namedMatches); - var actual = Assert.IsType(namedMatch.Match.Entry.Data); + var actual = Assert.IsType(namedMatch.Match.Entry.Data); Assert.Same(endpoint2, actual); } @@ -55,8 +56,8 @@ namespace Microsoft.AspNetCore.Routing Assert.NotNull(finder.NamedMatches); Assert.True(finder.NamedMatches.TryGetValue("named", out var namedMatches)); Assert.Equal(2, namedMatches.Count); - Assert.Same(endpoint2, Assert.IsType(namedMatches[0].Match.Entry.Data)); - Assert.Same(endpoint3, Assert.IsType(namedMatches[1].Match.Entry.Data)); + Assert.Same(endpoint2, Assert.IsType(namedMatches[0].Match.Entry.Data)); + Assert.Same(endpoint3, Assert.IsType(namedMatches[1].Match.Entry.Data)); } [Fact] @@ -76,8 +77,8 @@ namespace Microsoft.AspNetCore.Routing Assert.NotNull(finder.NamedMatches); Assert.True(finder.NamedMatches.TryGetValue("named", out var namedMatches)); Assert.Equal(2, namedMatches.Count); - Assert.Same(endpoint2, Assert.IsType(namedMatches[0].Match.Entry.Data)); - Assert.Same(endpoint3, Assert.IsType(namedMatches[1].Match.Entry.Data)); + Assert.Same(endpoint2, Assert.IsType(namedMatches[0].Match.Entry.Data)); + Assert.Same(endpoint3, Assert.IsType(namedMatches[1].Match.Entry.Data)); } [Fact] @@ -97,7 +98,7 @@ namespace Microsoft.AspNetCore.Routing // Assert 1 Assert.NotNull(finder.AllMatches); var match = Assert.Single(finder.AllMatches); - var actual = Assert.IsType(match.Entry.Data); + var actual = Assert.IsType(match.Entry.Data); Assert.Same(endpoint1, actual); // Arrange 2 @@ -127,22 +128,22 @@ namespace Microsoft.AspNetCore.Routing finder.AllMatches, (m) => { - actual = Assert.IsType(m.Entry.Data); + actual = Assert.IsType(m.Entry.Data); Assert.Same(endpoint1, actual); }, (m) => { - actual = Assert.IsType(m.Entry.Data); + actual = Assert.IsType(m.Entry.Data); Assert.Same(endpoint2, actual); }, (m) => { - actual = Assert.IsType(m.Entry.Data); + actual = Assert.IsType(m.Entry.Data); Assert.Same(endpoint3, actual); }, (m) => { - actual = Assert.IsType(m.Entry.Data); + actual = Assert.IsType(m.Entry.Data); Assert.Same(endpoint4, actual); }); } @@ -231,7 +232,7 @@ namespace Microsoft.AspNetCore.Routing objectPool); } - private MatcherEndpoint CreateEndpoint( + private RouteEndpoint CreateEndpoint( string template, object defaults = null, object requiredValues = null, @@ -249,8 +250,8 @@ namespace Microsoft.AspNetCore.Routing metadataCollection = new EndpointMetadataCollection(metadata); } - return new MatcherEndpoint( - MatcherEndpoint.EmptyInvoker, + return new RouteEndpoint( + TestConstants.EmptyRequestDelegate, RoutePatternFactory.Parse(template, defaults, parameterPolicies: null), order, metadataCollection, diff --git a/test/Microsoft.AspNetCore.Routing.Tests/TestConstants.cs b/test/Microsoft.AspNetCore.Routing.Tests/TestConstants.cs new file mode 100644 index 0000000000..0a32a95155 --- /dev/null +++ b/test/Microsoft.AspNetCore.Routing.Tests/TestConstants.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Routing +{ + public static class TestConstants + { + internal static readonly RequestDelegate EmptyRequestDelegate = (context) => Task.CompletedTask; + } +} diff --git a/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/DynamicEndpointDataSource.cs b/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/DynamicEndpointDataSource.cs index 71f45c09c6..5459883875 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/DynamicEndpointDataSource.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/DynamicEndpointDataSource.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Routing.TestObjects diff --git a/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/TestEndpoint.cs b/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/TestEndpoint.cs deleted file mode 100644 index ab0ff046d8..0000000000 --- a/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/TestEndpoint.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Routing.TestObjects -{ - internal class TestEndpoint : Endpoint - { - public TestEndpoint(EndpointMetadataCollection metadata, string displayName) - : base(metadata, displayName) - { - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/TestMatcher.cs b/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/TestMatcher.cs index d3d5544292..5da00c6f25 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/TestMatcher.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/TestObjects/TestMatcher.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Matching; namespace Microsoft.AspNetCore.Routing.TestObjects @@ -16,12 +17,12 @@ namespace Microsoft.AspNetCore.Routing.TestObjects _isHandled = isHandled; } - public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature) + public override Task MatchAsync(HttpContext httpContext, EndpointFeature feature) { if (_isHandled) { - feature.Values = new RouteValueDictionary(new { controller = "Home", action = "Index" }); - feature.Endpoint = new TestEndpoint(EndpointMetadataCollection.Empty, "Test endpoint"); + feature.RouteValues = new RouteValueDictionary(new { controller = "Home", action = "Index" }); + feature.Endpoint = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "Test endpoint"); } return Task.CompletedTask;