diff --git a/src/Microsoft.AspNetCore.Routing/Matchers/TreeMatcher.cs b/src/Microsoft.AspNetCore.Routing/Matchers/TreeMatcher.cs index 24149d0fa0..fe887569ae 100644 --- a/src/Microsoft.AspNetCore.Routing/Matchers/TreeMatcher.cs +++ b/src/Microsoft.AspNetCore.Routing/Matchers/TreeMatcher.cs @@ -130,7 +130,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers foreach (var kvp in constraints) { var constraint = kvp.Value; - if (!constraint.Match(httpContext, null, kvp.Key, values, RouteDirection.IncomingRequest)) + if (!constraint.Match(httpContext, new DummyRouter(), kvp.Key, values, RouteDirection.IncomingRequest)) { values.TryGetValue(kvp.Key, out var value); @@ -143,6 +143,19 @@ namespace Microsoft.AspNetCore.Routing.Matchers return true; } + private class DummyRouter : IRouter + { + public VirtualPathData GetVirtualPath(VirtualPathContext context) + { + throw new NotImplementedException(); + } + + public Task RouteAsync(RouteContext context) + { + return Task.CompletedTask; + } + } + private void SelectEndpoint(HttpContext httpContext, IEndpointFeature feature, IReadOnlyList endpoints) { var endpoint = (MatcherEndpoint)_endpointSelector.SelectBestCandidate(httpContext, endpoints); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/BarebonesMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/BarebonesMatcherConformanceTest.cs index 1e9584ec74..cc5d8768fb 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/BarebonesMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/BarebonesMatcherConformanceTest.cs @@ -39,6 +39,13 @@ namespace Microsoft.AspNetCore.Routing.Matchers return Task.CompletedTask; } + // Route constraints not supported + [Fact] + public override Task Match_Constraint() + { + return Task.CompletedTask; + } + internal override Matcher CreateMatcher(params MatcherEndpoint[] endpoints) { var builder = new BarebonesMatcherBuilder(); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherConformanceTest.SingleEndpoint.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherConformanceTest.SingleEndpoint.cs index 58fa2d9282..529dfdacb6 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherConformanceTest.SingleEndpoint.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherConformanceTest.SingleEndpoint.cs @@ -208,6 +208,21 @@ namespace Microsoft.AspNetCore.Routing.Matchers DispatcherAssert.AssertMatch(feature, endpoint, values); } + [Fact] + public virtual async Task Match_Constraint() + { + // Arrange + var (matcher, endpoint) = CreateMatcher("/{p:int}"); + var (httpContext, feature) = CreateContext("/14"); + var values = new RouteValueDictionary(new { p = "14", }); + + // Act + await matcher.MatchAsync(httpContext, feature); + + // Assert + DispatcherAssert.AssertMatch(feature, endpoint, values); + } + [Fact] public virtual async Task Match_SingleParameter_TrailingSlash() { diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/TreeMatcherTests.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/TreeMatcherTests.cs index c876adf739..c21a90dfda 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/TreeMatcherTests.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/TreeMatcherTests.cs @@ -32,6 +32,52 @@ namespace Microsoft.AspNetCore.Routing.Matchers return new TreeMatcher(defaultInlineConstraintResolver, NullLogger.Instance, endpointDataSource, endpointSelector); } + [Fact] + public async Task MatchAsync_ValidRouteConstraint_EndpointMatched() + { + // Arrange + var endpointDataSource = new DefaultEndpointDataSource(new List + { + CreateEndpoint("/{p:int}", 0) + }); + + var treeMatcher = CreateTreeMatcher(endpointDataSource); + + var httpContext = new DefaultHttpContext(); + httpContext.Request.Path = "/1"; + + var endpointFeature = new EndpointFeature(); + + // Act + await treeMatcher.MatchAsync(httpContext, endpointFeature); + + // Assert + Assert.NotNull(endpointFeature.Endpoint); + } + + [Fact] + public async Task MatchAsync_InvalidRouteConstraint_NoEndpointMatched() + { + // Arrange + var endpointDataSource = new DefaultEndpointDataSource(new List + { + CreateEndpoint("/{p:int}", 0) + }); + + var treeMatcher = CreateTreeMatcher(endpointDataSource); + + var httpContext = new DefaultHttpContext(); + httpContext.Request.Path = "/One"; + + var endpointFeature = new EndpointFeature(); + + // Act + await treeMatcher.MatchAsync(httpContext, endpointFeature); + + // Assert + Assert.Null(endpointFeature.Endpoint); + } + [Fact] public async Task MatchAsync_DuplicateTemplatesAndDifferentOrder_LowerOrderEndpointMatched() { diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/TreeRouterMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/TreeRouterMatcherConformanceTest.cs index 1771cf269f..238a68f294 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/TreeRouterMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/TreeRouterMatcherConformanceTest.cs @@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers { return Task.CompletedTask; } + internal override Matcher CreateMatcher(params MatcherEndpoint[] endpoints) { var builder = new TreeRouterMatcherBuilder();