Merge pull request #8524 from aspnet/rynowak/endpoint-selector-master

Rynowak/endpoint selector master
This commit is contained in:
Ryan Nowak 2018-09-30 14:55:28 -07:00 committed by GitHub
commit e9c7b08d10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 50 additions and 52 deletions

View File

@ -48,8 +48,8 @@
<MicrosoftAspNetCoreRazorTagHelpersTestingSourcesPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreRazorTagHelpersTestingSourcesPackageVersion> <MicrosoftAspNetCoreRazorTagHelpersTestingSourcesPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreRazorTagHelpersTestingSourcesPackageVersion>
<MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion> <MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion>
<MicrosoftAspNetCoreResponseCachingPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreResponseCachingPackageVersion> <MicrosoftAspNetCoreResponseCachingPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreResponseCachingPackageVersion>
<MicrosoftAspNetCoreRoutingAbstractionsPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreRoutingAbstractionsPackageVersion> <MicrosoftAspNetCoreRoutingAbstractionsPackageVersion>3.0.0-a-alpha1-endpoint-selector-master-17042</MicrosoftAspNetCoreRoutingAbstractionsPackageVersion>
<MicrosoftAspNetCoreRoutingPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreRoutingPackageVersion> <MicrosoftAspNetCoreRoutingPackageVersion>3.0.0-a-alpha1-endpoint-selector-master-17042</MicrosoftAspNetCoreRoutingPackageVersion>
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreServerIISIntegrationPackageVersion> <MicrosoftAspNetCoreServerIISIntegrationPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreServerKestrelPackageVersion> <MicrosoftAspNetCoreServerKestrelPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreSessionPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreSessionPackageVersion> <MicrosoftAspNetCoreSessionPackageVersion>3.0.0-alpha1-10549</MicrosoftAspNetCoreSessionPackageVersion>

View File

@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
// Internal for testing // Internal for testing
internal bool ShouldRunActionConstraints => _actionConstraintCache.CurrentCache.HasActionConstraints; internal bool ShouldRunActionConstraints => _actionConstraintCache.CurrentCache.HasActionConstraints;
public Task ApplyAsync(HttpContext httpContext, EndpointFeature endpointFeature, CandidateSet candidateSet) public Task ApplyAsync(HttpContext httpContext, EndpointSelectorContext context, CandidateSet candidateSet)
{ {
// PERF: we can skip over action constraints if there aren't any app-wide. // PERF: we can skip over action constraints if there aren't any app-wide.
// //
@ -64,14 +64,14 @@ namespace Microsoft.AspNetCore.Mvc.Routing
// set as valid. This is O(2n) vs O(n**2) // set as valid. This is O(2n) vs O(n**2)
for (var i = 0; i < candidateSet.Count; i++) for (var i = 0; i < candidateSet.Count; i++)
{ {
candidateSet[i].IsValidCandidate = false; candidateSet.SetValidity(i, false);
} }
if (finalMatches != null) if (finalMatches != null)
{ {
for (var i = 0; i < finalMatches.Count; i++) for (var i = 0; i < finalMatches.Count; i++)
{ {
candidateSet[finalMatches[i].index].IsValidCandidate = true; candidateSet.SetValidity(finalMatches[i].index, true);
} }
} }
} }
@ -91,9 +91,9 @@ namespace Microsoft.AspNetCore.Mvc.Routing
// Perf: Avoid allocations // Perf: Avoid allocations
for (var i = 0; i < candidateSet.Count; i++) for (var i = 0; i < candidateSet.Count; i++)
{ {
ref var candidate = ref candidateSet[i]; if (candidateSet.IsValidCandidate(i))
if (candidate.IsValidCandidate)
{ {
ref var candidate = ref candidateSet[i];
if (score != null && score != candidate.Score) if (score != null && score != candidate.Score)
{ {
// This is the end of a group. // This is the end of a group.

View File

@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
public async Task Endpoints_InvokeReturnedEndpoint_ActionInvokerProviderCalled() public async Task Endpoints_InvokeReturnedEndpoint_ActionInvokerProviderCalled()
{ {
// Arrange // Arrange
var endpointFeature = new EndpointFeature var endpointFeature = new EndpointSelectorContext
{ {
RouteValues = new RouteValueDictionary() RouteValues = new RouteValueDictionary()
}; };

View File

@ -232,7 +232,7 @@ namespace Microsoft.AspNetCore.Routing
{ {
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
var feature = new EndpointFeature var feature = new EndpointSelectorContext
{ {
RouteValues = new RouteValueDictionary(ambientValues) RouteValues = new RouteValueDictionary(ambientValues)
}; };

View File

@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var urlHelper = CreateUrlHelper(new[] { endpoint1, endpoint2 }); var urlHelper = CreateUrlHelper(new[] { endpoint1, endpoint2 });
// Set the endpoint feature and current context just as a normal request to MVC app would be // Set the endpoint feature and current context just as a normal request to MVC app would be
var endpointFeature = new EndpointFeature(); var endpointFeature = new EndpointSelectorContext();
urlHelper.ActionContext.HttpContext.Features.Set<IEndpointFeature>(endpointFeature); urlHelper.ActionContext.HttpContext.Features.Set<IEndpointFeature>(endpointFeature);
urlHelper.ActionContext.HttpContext.Features.Set<IRouteValuesFeature>(endpointFeature); urlHelper.ActionContext.HttpContext.Features.Set<IRouteValuesFeature>(endpointFeature);
endpointFeature.Endpoint = endpoint1; endpointFeature.Endpoint = endpoint1;
@ -154,7 +154,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
protected override IUrlHelper CreateUrlHelper(ActionContext actionContext) protected override IUrlHelper CreateUrlHelper(ActionContext actionContext)
{ {
var httpContext = actionContext.HttpContext; var httpContext = actionContext.HttpContext;
httpContext.Features.Set<IEndpointFeature>(new EndpointFeature() httpContext.Features.Set<IEndpointFeature>(new EndpointSelectorContext()
{ {
Endpoint = new Endpoint( Endpoint = new Endpoint(
context => Task.CompletedTask, context => Task.CompletedTask,

View File

@ -232,7 +232,7 @@ namespace Microsoft.AspNetCore.Routing
{ {
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
var feature = new EndpointFeature var feature = new EndpointSelectorContext
{ {
RouteValues = new RouteValueDictionary(ambientValues) RouteValues = new RouteValueDictionary(ambientValues)
}; };

View File

@ -35,11 +35,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var selector = CreateSelector(actions); var selector = CreateSelector(actions);
// Act // Act
await selector.ApplyAsync(new DefaultHttpContext(), new EndpointFeature(), candidateSet); await selector.ApplyAsync(new DefaultHttpContext(), new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.True(candidateSet[0].IsValidCandidate); Assert.True(candidateSet.IsValidCandidate(0));
Assert.True(candidateSet[1].IsValidCandidate); Assert.True(candidateSet.IsValidCandidate(1));
} }
[Fact] [Fact]
@ -68,11 +68,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var httpContext = CreateHttpContext("POST"); var httpContext = CreateHttpContext("POST");
// Act // Act
await selector.ApplyAsync(httpContext, new EndpointFeature(), candidateSet); await selector.ApplyAsync(httpContext, new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.True(candidateSet[0].IsValidCandidate); Assert.True(candidateSet.IsValidCandidate(0));
Assert.False(candidateSet[1].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(1));
} }
[Fact] [Fact]
@ -103,11 +103,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var httpContext = CreateHttpContext("POST"); var httpContext = CreateHttpContext("POST");
// Act // Act
await selector.ApplyAsync(httpContext, new EndpointFeature(), candidateSet); await selector.ApplyAsync(httpContext, new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.False(candidateSet[0].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(0));
Assert.False(candidateSet[1].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(1));
} }
[Fact] [Fact]
@ -139,11 +139,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var httpContext = CreateHttpContext("POST"); var httpContext = CreateHttpContext("POST");
// Act // Act
await selector.ApplyAsync(httpContext, new EndpointFeature(), candidateSet); await selector.ApplyAsync(httpContext, new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.False(candidateSet[0].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(0));
Assert.False(candidateSet[1].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(1));
} }
// Due to ordering of stages, the first action will be better. // Due to ordering of stages, the first action will be better.
@ -174,11 +174,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var httpContext = CreateHttpContext("POST"); var httpContext = CreateHttpContext("POST");
// Act // Act
await selector.ApplyAsync(httpContext, new EndpointFeature(), candidateSet); await selector.ApplyAsync(httpContext, new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.True(candidateSet[0].IsValidCandidate); Assert.True(candidateSet.IsValidCandidate(0));
Assert.False(candidateSet[1].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(1));
} }
[Fact] [Fact]
@ -205,19 +205,19 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var actions = new ActionDescriptor[] { best, another, worst }; var actions = new ActionDescriptor[] { best, another, worst };
var candidateSet = CreateCandidateSet(actions); var candidateSet = CreateCandidateSet(actions);
candidateSet[0].IsValidCandidate = false; candidateSet.SetValidity(0, false);
candidateSet[1].IsValidCandidate = false; candidateSet.SetValidity(1, false);
var selector = CreateSelector(actions); var selector = CreateSelector(actions);
var httpContext = CreateHttpContext("POST"); var httpContext = CreateHttpContext("POST");
// Act // Act
await selector.ApplyAsync(httpContext, new EndpointFeature(), candidateSet); await selector.ApplyAsync(httpContext, new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.False(candidateSet[0].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(0));
Assert.False(candidateSet[1].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(1));
Assert.True(candidateSet[2].IsValidCandidate); Assert.True(candidateSet.IsValidCandidate(2));
} }
[Fact] [Fact]
@ -247,12 +247,12 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var httpContext = CreateHttpContext("POST"); var httpContext = CreateHttpContext("POST");
// Act // Act
await selector.ApplyAsync(httpContext, new EndpointFeature(), candidateSet); await selector.ApplyAsync(httpContext, new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.False(candidateSet[0].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(0));
Assert.True(candidateSet[1].IsValidCandidate); Assert.True(candidateSet.IsValidCandidate(1));
Assert.False(candidateSet[2].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(2));
} }
// Due to ordering of stages, the first action will be better. // Due to ordering of stages, the first action will be better.
@ -288,11 +288,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var httpContext = CreateHttpContext("POST"); var httpContext = CreateHttpContext("POST");
// Act // Act
await selector.ApplyAsync(httpContext, new EndpointFeature(), candidateSet); await selector.ApplyAsync(httpContext, new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.True(candidateSet[0].IsValidCandidate); Assert.True(candidateSet.IsValidCandidate(0));
Assert.False(candidateSet[1].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(1));
} }
[Fact] [Fact]
@ -329,12 +329,12 @@ namespace Microsoft.AspNetCore.Mvc.Routing
var httpContext = CreateHttpContext("POST"); var httpContext = CreateHttpContext("POST");
// Act // Act
await selector.ApplyAsync(httpContext, new EndpointFeature(), candidateSet); await selector.ApplyAsync(httpContext, new EndpointSelectorContext(), candidateSet);
// Assert // Assert
Assert.True(candidateSet[0].IsValidCandidate); Assert.True(candidateSet.IsValidCandidate(0));
Assert.False(candidateSet[1].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(1));
Assert.False(candidateSet[2].IsValidCandidate); Assert.False(candidateSet.IsValidCandidate(2));
} }
[Fact] [Fact]
@ -452,18 +452,16 @@ namespace Microsoft.AspNetCore.Mvc.Routing
private static CandidateSet CreateCandidateSet(ActionDescriptor[] actions) private static CandidateSet CreateCandidateSet(ActionDescriptor[] actions)
{ {
var candidateSet = new CandidateSet( var values = new RouteValueDictionary[actions.Length];
actions.Select(CreateEndpoint).ToArray(),
new int[actions.Length]);
for (var i = 0; i < actions.Length; i++) for (var i = 0; i < actions.Length; i++)
{ {
if (candidateSet[i].IsValidCandidate) values[i] = new RouteValueDictionary();
{
candidateSet[i].Values = new RouteValueDictionary();
}
} }
var candidateSet = new CandidateSet(
actions.Select(CreateEndpoint).ToArray(),
values,
new int[actions.Length]);
return candidateSet; return candidateSet;
} }