Fix endpoint constraint cache (#555)
This commit is contained in:
parent
6a6bd3f0da
commit
9efa7665c9
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
|
@ -50,38 +51,48 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
|||
return GetEndpointConstraintsFromEntry(entry, httpContext, endpoint);
|
||||
}
|
||||
|
||||
if (endpoint.Metadata == null || endpoint.Metadata.Count == 0)
|
||||
List<EndpointConstraintItem> items = null;
|
||||
|
||||
if (endpoint.Metadata != null && endpoint.Metadata.Count > 0)
|
||||
{
|
||||
return null;
|
||||
items = endpoint.Metadata
|
||||
.OfType<IEndpointConstraintMetadata>()
|
||||
.Select(m => new EndpointConstraintItem(m))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
var items = endpoint.Metadata
|
||||
.OfType<IEndpointConstraintMetadata>()
|
||||
.Select(m => new EndpointConstraintItem(m))
|
||||
.ToList();
|
||||
IReadOnlyList<IEndpointConstraint> endpointConstraints = null;
|
||||
|
||||
ExecuteProviders(httpContext, endpoint, items);
|
||||
|
||||
var endpointConstraints = ExtractEndpointConstraints(items);
|
||||
|
||||
var allEndpointConstraintsCached = true;
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
if (items != null && items.Count > 0)
|
||||
{
|
||||
var item = items[i];
|
||||
if (!item.IsReusable)
|
||||
ExecuteProviders(httpContext, endpoint, items);
|
||||
|
||||
endpointConstraints = ExtractEndpointConstraints(items);
|
||||
|
||||
var allEndpointConstraintsCached = true;
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
item.Constraint = null;
|
||||
allEndpointConstraintsCached = false;
|
||||
var item = items[i];
|
||||
if (!item.IsReusable)
|
||||
{
|
||||
item.Constraint = null;
|
||||
allEndpointConstraintsCached = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allEndpointConstraintsCached)
|
||||
{
|
||||
entry = new CacheEntry(endpointConstraints);
|
||||
if (allEndpointConstraintsCached)
|
||||
{
|
||||
entry = new CacheEntry(endpointConstraints);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry = new CacheEntry(items);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entry = new CacheEntry(items);
|
||||
// No constraints
|
||||
entry = new CacheEntry();
|
||||
}
|
||||
|
||||
cache.Entries.TryAdd(endpoint, entry);
|
||||
|
|
@ -90,13 +101,17 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
|||
|
||||
private IReadOnlyList<IEndpointConstraint> GetEndpointConstraintsFromEntry(CacheEntry entry, HttpContext httpContext, Endpoint endpoint)
|
||||
{
|
||||
Debug.Assert(entry.EndpointConstraints != null || entry.Items != null);
|
||||
|
||||
if (entry.EndpointConstraints != null)
|
||||
{
|
||||
return entry.EndpointConstraints;
|
||||
}
|
||||
|
||||
if (entry.Items == null)
|
||||
{
|
||||
// Endpoint has no constraints
|
||||
return null;
|
||||
}
|
||||
|
||||
var items = new List<EndpointConstraintItem>(entry.Items.Count);
|
||||
for (var i = 0; i < entry.Items.Count; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -210,6 +210,49 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
|||
Assert.Same(action, actionWithConstraints);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectBestCandidate_MultipleCallsNoConstraint_ReturnsEndpoint()
|
||||
{
|
||||
// Arrange
|
||||
var noConstraint = new TestEndpoint(EndpointMetadataCollection.Empty, "noConstraint");
|
||||
|
||||
var actions = new Endpoint[] { noConstraint };
|
||||
|
||||
var selector = CreateSelector(actions);
|
||||
var context = CreateHttpContext("POST");
|
||||
|
||||
// Act
|
||||
var action1 = selector.SelectBestCandidate(context, actions);
|
||||
var action2 = selector.SelectBestCandidate(context, actions);
|
||||
|
||||
// Assert
|
||||
Assert.Same(action1, noConstraint);
|
||||
Assert.Same(action2, noConstraint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectBestCandidate_MultipleCallsNonConstraintMetadata_ReturnsEndpoint()
|
||||
{
|
||||
// Arrange
|
||||
var noConstraint = new TestEndpoint(new EndpointMetadataCollection(new[]
|
||||
{
|
||||
new object(),
|
||||
}), "noConstraint");
|
||||
|
||||
var actions = new Endpoint[] { noConstraint };
|
||||
|
||||
var selector = CreateSelector(actions);
|
||||
var context = CreateHttpContext("POST");
|
||||
|
||||
// Act
|
||||
var action1 = selector.SelectBestCandidate(context, actions);
|
||||
var action2 = selector.SelectBestCandidate(context, actions);
|
||||
|
||||
// Assert
|
||||
Assert.Same(action1, noConstraint);
|
||||
Assert.Same(action2, noConstraint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectBestCandidate_EndpointConstraintFactory_ReturnsNull()
|
||||
{
|
||||
|
|
@ -225,10 +268,12 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
|||
var context = CreateHttpContext("POST");
|
||||
|
||||
// Act
|
||||
var action = selector.SelectBestCandidate(context, actions);
|
||||
var action1 = selector.SelectBestCandidate(context, actions);
|
||||
var action2 = selector.SelectBestCandidate(context, actions);
|
||||
|
||||
// Assert
|
||||
Assert.Same(action, nullConstraint);
|
||||
Assert.Same(action1, nullConstraint);
|
||||
Assert.Same(action2, nullConstraint);
|
||||
}
|
||||
|
||||
// There's a custom constraint provider registered that only understands BooleanConstraintMarker
|
||||
|
|
|
|||
Loading…
Reference in New Issue