Merge pull request #846 from dotnet-maestro-bot/merge/release/2.2-to-master
[automated] Merge branch 'release/2.2' => 'master'
This commit is contained in:
commit
93dc6dd5f5
|
|
@ -8,10 +8,10 @@ using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing.LinkGeneration
|
namespace Microsoft.AspNetCore.Routing.LinkGeneration
|
||||||
{
|
{
|
||||||
public class SingleRouteRouteValuesBasedEndpointFinderBenchmark : EndpointRoutingBenchmarkBase
|
public class SingleRouteRouteValuesAddressSchemeBenchmark : EndpointRoutingBenchmarkBase
|
||||||
{
|
{
|
||||||
private IEndpointFinder<RouteValuesAddress> _finder;
|
private IEndpointAddressScheme<RouteValuesAddress> _implementation;
|
||||||
private TestEndpointFinder _baseFinder;
|
private TestAddressScheme _baseline;
|
||||||
private (HttpContext HttpContext, RouteValueDictionary AmbientValues) _requestContext;
|
private (HttpContext HttpContext, RouteValueDictionary AmbientValues) _requestContext;
|
||||||
|
|
||||||
[GlobalSetup]
|
[GlobalSetup]
|
||||||
|
|
@ -23,8 +23,8 @@ namespace Microsoft.AspNetCore.Routing.LinkGeneration
|
||||||
|
|
||||||
SetupEndpoints(CreateEndpoint(template, defaults, requiredValues: requiredValues, routeName: "ProductDetails"));
|
SetupEndpoints(CreateEndpoint(template, defaults, requiredValues: requiredValues, routeName: "ProductDetails"));
|
||||||
var services = CreateServices();
|
var services = CreateServices();
|
||||||
_finder = services.GetRequiredService<IEndpointFinder<RouteValuesAddress>>();
|
_implementation = services.GetRequiredService<IEndpointAddressScheme<RouteValuesAddress>>();
|
||||||
_baseFinder = new TestEndpointFinder(Endpoints[0]);
|
_baseline = new TestAddressScheme(Endpoints[0]);
|
||||||
|
|
||||||
_requestContext = CreateCurrentRequestContext();
|
_requestContext = CreateCurrentRequestContext();
|
||||||
}
|
}
|
||||||
|
|
@ -32,13 +32,13 @@ namespace Microsoft.AspNetCore.Routing.LinkGeneration
|
||||||
[Benchmark(Baseline = true)]
|
[Benchmark(Baseline = true)]
|
||||||
public void Baseline()
|
public void Baseline()
|
||||||
{
|
{
|
||||||
var actual = _baseFinder.FindEndpoints(address: 0);
|
var actual = _baseline.FindEndpoints(address: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void RouteValues()
|
public void RouteValues()
|
||||||
{
|
{
|
||||||
var actual = _finder.FindEndpoints(new RouteValuesAddress
|
var actual = _implementation.FindEndpoints(new RouteValuesAddress
|
||||||
{
|
{
|
||||||
AmbientValues = _requestContext.AmbientValues,
|
AmbientValues = _requestContext.AmbientValues,
|
||||||
ExplicitValues = new RouteValueDictionary(new { controller = "Products", action = "Details" }),
|
ExplicitValues = new RouteValueDictionary(new { controller = "Products", action = "Details" }),
|
||||||
|
|
@ -49,18 +49,18 @@ namespace Microsoft.AspNetCore.Routing.LinkGeneration
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void RouteName()
|
public void RouteName()
|
||||||
{
|
{
|
||||||
var actual = _finder.FindEndpoints(new RouteValuesAddress
|
var actual = _implementation.FindEndpoints(new RouteValuesAddress
|
||||||
{
|
{
|
||||||
AmbientValues = _requestContext.AmbientValues,
|
AmbientValues = _requestContext.AmbientValues,
|
||||||
RouteName = "ProductDetails"
|
RouteName = "ProductDetails"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestEndpointFinder : IEndpointFinder<int>
|
private class TestAddressScheme : IEndpointAddressScheme<int>
|
||||||
{
|
{
|
||||||
private readonly Endpoint _endpoint;
|
private readonly Endpoint _endpoint;
|
||||||
|
|
||||||
public TestEndpointFinder(Endpoint endpoint)
|
public TestAddressScheme(Endpoint endpoint)
|
||||||
{
|
{
|
||||||
_endpoint = endpoint;
|
_endpoint = endpoint;
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +202,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
private List<RouteEndpoint> GetEndpoints<TAddress>(TAddress address)
|
private List<RouteEndpoint> GetEndpoints<TAddress>(TAddress address)
|
||||||
{
|
{
|
||||||
var addressingScheme = _serviceProvider.GetRequiredService<IEndpointFinder<TAddress>>();
|
var addressingScheme = _serviceProvider.GetRequiredService<IEndpointAddressScheme<TAddress>>();
|
||||||
var endpoints = addressingScheme.FindEndpoints(address).OfType<RouteEndpoint>().ToList();
|
var endpoints = addressingScheme.FindEndpoints(address).OfType<RouteEndpoint>().ToList();
|
||||||
|
|
||||||
if (endpoints.Count == 0)
|
if (endpoints.Count == 0)
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
|
|
||||||
// Link generation related services
|
// Link generation related services
|
||||||
services.TryAddSingleton<LinkGenerator, DefaultLinkGenerator>();
|
services.TryAddSingleton<LinkGenerator, DefaultLinkGenerator>();
|
||||||
services.TryAddSingleton<IEndpointFinder<string>, EndpointNameEndpointFinder>();
|
services.TryAddSingleton<IEndpointAddressScheme<string>, EndpointNameAddressScheme>();
|
||||||
services.TryAddSingleton<IEndpointFinder<RouteValuesAddress>, RouteValuesBasedEndpointFinder>();
|
services.TryAddSingleton<IEndpointAddressScheme<RouteValuesAddress>, RouteValuesAddressScheme>();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Endpoint Selection
|
// Endpoint Selection
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@ using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
internal class EndpointNameEndpointFinder : IEndpointFinder<string>
|
internal class EndpointNameAddressScheme : IEndpointAddressScheme<string>
|
||||||
{
|
{
|
||||||
private readonly DataSourceDependentCache<Dictionary<string, Endpoint[]>> _cache;
|
private readonly DataSourceDependentCache<Dictionary<string, Endpoint[]>> _cache;
|
||||||
|
|
||||||
public EndpointNameEndpointFinder(CompositeEndpointDataSource dataSource)
|
public EndpointNameAddressScheme(CompositeEndpointDataSource dataSource)
|
||||||
{
|
{
|
||||||
_cache = new DataSourceDependentCache<Dictionary<string, Endpoint[]>>(dataSource, Initialize);
|
_cache = new DataSourceDependentCache<Dictionary<string, Endpoint[]>>(dataSource, Initialize);
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
string GetEndpointName(Endpoint endpoint)
|
string GetEndpointName(Endpoint endpoint)
|
||||||
{
|
{
|
||||||
if (endpoint.Metadata.GetMetadata<ISuppressLinkGenerationMetadata>() != null)
|
if (endpoint.Metadata.GetMetadata<ISuppressLinkGenerationMetadata>()?.SuppressLinkGeneration == true)
|
||||||
{
|
{
|
||||||
// Skip anything that's suppressed for linking.
|
// Skip anything that's suppressed for linking.
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -7,13 +7,13 @@ using Microsoft.AspNetCore.Http;
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a contract to find endpoints based on the supplied lookup information.
|
/// Defines a contract to find endpoints based on the provided address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
public interface IEndpointFinder<TAddress>
|
public interface IEndpointAddressScheme<TAddress>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds endpoints based on the supplied lookup information.
|
/// Finds endpoints based on the provided <paramref name="address"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">The information used to look up endpoints.</param>
|
/// <param name="address">The information used to look up endpoints.</param>
|
||||||
/// <returns>A collection of <see cref="Endpoint"/>.</returns>
|
/// <returns>A collection of <see cref="Endpoint"/>.</returns>
|
||||||
|
|
@ -4,10 +4,14 @@
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents metadata used during link generation.
|
/// Represents metadata used during link generation. If <see cref="SuppressLinkGeneration"/> is <c>true</c>
|
||||||
/// The associated endpoint will not be considered for link generation.
|
/// the associated endpoint will not be used for link generation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISuppressLinkGenerationMetadata
|
public interface ISuppressLinkGenerationMetadata
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the assocated endpoint should be used for link generation.
|
||||||
|
/// </summary>
|
||||||
|
bool SuppressLinkGeneration { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,10 +4,14 @@
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Metadata used to prevent URL matching. The associated endpoint will not be
|
/// Metadata used to prevent URL matching. If <see cref="SuppressMatching"/> is <c>true</c> the
|
||||||
/// considered URL matching for incoming requests.
|
/// associated endpoint will not be considered for URL matching.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISuppressMatchingMetadata
|
public interface ISuppressMatchingMetadata
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the assocated endpoint should be used for URL matching.
|
||||||
|
/// </summary>
|
||||||
|
bool SuppressMatching { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
var endpoints = dataSource.Endpoints;
|
var endpoints = dataSource.Endpoints;
|
||||||
for (var i = 0; i < endpoints.Count; i++)
|
for (var i = 0; i < endpoints.Count; i++)
|
||||||
{
|
{
|
||||||
if (endpoints[i] is RouteEndpoint endpoint && endpoint.Metadata.GetMetadata<ISuppressMatchingMetadata>() == null)
|
if (endpoints[i] is RouteEndpoint endpoint && endpoint.Metadata.GetMetadata<ISuppressMatchingMetadata>()?.SuppressMatching == true)
|
||||||
{
|
{
|
||||||
builder.AddEndpoint(endpoint);
|
builder.AddEndpoint(endpoint);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
// By design we only look at RouteEndpoint 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
|
// register other endpoint types, which are non-routable, and it's
|
||||||
// ok that we won't route to them.
|
// ok that we won't route to them.
|
||||||
if (endpoints[i] is RouteEndpoint endpoint && endpoint.Metadata.GetMetadata<ISuppressMatchingMetadata>() == null)
|
if (endpoints[i] is RouteEndpoint endpoint && endpoint.Metadata.GetMetadata<ISuppressMatchingMetadata>()?.SuppressMatching != true)
|
||||||
{
|
{
|
||||||
builder.AddEndpoint(endpoint);
|
builder.AddEndpoint(endpoint);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
internal class RouteValuesBasedEndpointFinder : IEndpointFinder<RouteValuesAddress>
|
internal class RouteValuesAddressScheme : IEndpointAddressScheme<RouteValuesAddress>
|
||||||
{
|
{
|
||||||
private readonly CompositeEndpointDataSource _dataSource;
|
private readonly CompositeEndpointDataSource _dataSource;
|
||||||
private LinkGenerationDecisionTree _allMatchesLinkGenerationTree;
|
private LinkGenerationDecisionTree _allMatchesLinkGenerationTree;
|
||||||
private IDictionary<string, List<OutboundMatchResult>> _namedMatchResults;
|
private IDictionary<string, List<OutboundMatchResult>> _namedMatchResults;
|
||||||
|
|
||||||
public RouteValuesBasedEndpointFinder(CompositeEndpointDataSource dataSource)
|
public RouteValuesAddressScheme(CompositeEndpointDataSource dataSource)
|
||||||
{
|
{
|
||||||
_dataSource = dataSource;
|
_dataSource = dataSource;
|
||||||
|
|
||||||
|
|
@ -102,9 +102,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoints = _dataSource.Endpoints.OfType<RouteEndpoint>();
|
var endpoints = _dataSource.Endpoints.OfType<RouteEndpoint>();
|
||||||
foreach (var endpoint in endpoints)
|
foreach (var endpoint in endpoints)
|
||||||
{
|
{
|
||||||
// Do not consider an endpoint for link generation if the following marker metadata is on it
|
if (endpoint.Metadata.GetMetadata<ISuppressLinkGenerationMetadata>()?.SuppressLinkGeneration == true)
|
||||||
var suppressLinkGeneration = endpoint.Metadata.GetMetadata<ISuppressLinkGenerationMetadata>();
|
|
||||||
if (suppressLinkGeneration != null)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -4,10 +4,14 @@
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents metadata used during link generation.
|
/// Represents metadata used during link generation. If <see cref="SuppressLinkGeneration"/> is <c>true</c>
|
||||||
/// The associated endpoint will not be considered for link generation.
|
/// the associated endpoint will not be used for link generation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SuppressLinkGenerationMetadata : ISuppressLinkGenerationMetadata
|
public sealed class SuppressLinkGenerationMetadata : ISuppressLinkGenerationMetadata
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the assocated endpoint should be used for link generation.
|
||||||
|
/// </summary>
|
||||||
|
public bool SuppressLinkGeneration => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,10 +4,14 @@
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Metadata used to prevent URL matching. The associated endpoint will not be
|
/// Metadata used to prevent URL matching. If <see cref="SuppressMatching"/> is <c>true</c> the
|
||||||
/// considered URL matching for incoming requests.
|
/// associated endpoint will not be considered for URL matching.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SuppressMatchingMetadata : ISuppressMatchingMetadata
|
public sealed class SuppressMatchingMetadata : ISuppressMatchingMetadata
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the assocated endpoint should be used for URL matching.
|
||||||
|
/// </summary>
|
||||||
|
public bool SuppressMatching => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -599,14 +599,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
protected override void AddAdditionalServices(IServiceCollection services)
|
protected override void AddAdditionalServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IEndpointFinder<int>, IntEndpointFinder>();
|
services.AddSingleton<IEndpointAddressScheme<int>, IntAddressScheme>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IntEndpointFinder : IEndpointFinder<int>
|
private class IntAddressScheme : IEndpointAddressScheme<int>
|
||||||
{
|
{
|
||||||
private readonly CompositeEndpointDataSource _dataSource;
|
private readonly CompositeEndpointDataSource _dataSource;
|
||||||
|
|
||||||
public IntEndpointFinder(CompositeEndpointDataSource dataSource)
|
public IntAddressScheme(CompositeEndpointDataSource dataSource)
|
||||||
{
|
{
|
||||||
_dataSource = dataSource;
|
_dataSource = dataSource;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@ using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
public class EndpointNameEndpointFinderTest
|
public class EndpointNameAddressSchemeTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EndpointFinder_Match_ReturnsMatchingEndpoint()
|
public void AddressScheme_Match_ReturnsMatchingEndpoint()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint(
|
var endpoint1 = EndpointFactory.CreateRouteEndpoint(
|
||||||
|
|
@ -23,10 +23,10 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
"/b",
|
"/b",
|
||||||
metadata: new object[] { new EndpointNameMetadata("name2"), });
|
metadata: new object[] { new EndpointNameMetadata("name2"), });
|
||||||
|
|
||||||
var finder = CreateEndpointFinder(endpoint1, endpoint2);
|
var addressScheme = CreateAddressScheme(endpoint1, endpoint2);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var endpoints = finder.FindEndpoints("name2");
|
var endpoints = addressScheme.FindEndpoints("name2");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(
|
Assert.Collection(
|
||||||
|
|
@ -35,41 +35,41 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EndpointFinder_NoMatch_ReturnsEmptyCollection()
|
public void AddressScheme_NoMatch_ReturnsEmptyCollection()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
||||||
"/a",
|
"/a",
|
||||||
metadata: new object[] { new EndpointNameMetadata("name1"), new SuppressLinkGenerationMetadata(), });
|
metadata: new object[] { new EndpointNameMetadata("name1"), new SuppressLinkGenerationMetadata(), });
|
||||||
|
|
||||||
var finder = CreateEndpointFinder(endpoint);
|
var addressScheme = CreateAddressScheme(endpoint);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var endpoints = finder.FindEndpoints("name2");
|
var endpoints = addressScheme.FindEndpoints("name2");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(endpoints);
|
Assert.Empty(endpoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EndpointFinder_NoMatch_CaseSensitive()
|
public void AddressScheme_NoMatch_CaseSensitive()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
||||||
"/a",
|
"/a",
|
||||||
metadata: new object[] { new EndpointNameMetadata("name1"), new SuppressLinkGenerationMetadata(), });
|
metadata: new object[] { new EndpointNameMetadata("name1"), new SuppressLinkGenerationMetadata(), });
|
||||||
|
|
||||||
var finder = CreateEndpointFinder(endpoint);
|
var addressScheme = CreateAddressScheme(endpoint);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var endpoints = finder.FindEndpoints("NAME1");
|
var endpoints = addressScheme.FindEndpoints("NAME1");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(endpoints);
|
Assert.Empty(endpoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EndpointFinder_UpdatesWhenDataSourceChanges()
|
public void AddressScheme_UpdatesWhenDataSourceChanges()
|
||||||
{
|
{
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint(
|
var endpoint1 = EndpointFactory.CreateRouteEndpoint(
|
||||||
"/a",
|
"/a",
|
||||||
|
|
@ -77,10 +77,10 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var dynamicDataSource = new DynamicEndpointDataSource(new[] { endpoint1 });
|
var dynamicDataSource = new DynamicEndpointDataSource(new[] { endpoint1 });
|
||||||
|
|
||||||
// Act 1
|
// Act 1
|
||||||
var finder = CreateEndpointFinder(dynamicDataSource);
|
var addressScheme = CreateAddressScheme(dynamicDataSource);
|
||||||
|
|
||||||
// Assert 1
|
// Assert 1
|
||||||
var match = Assert.Single(finder.Entries);
|
var match = Assert.Single(addressScheme.Entries);
|
||||||
Assert.Same(endpoint1, match.Value.Single());
|
Assert.Same(endpoint1, match.Value.Single());
|
||||||
|
|
||||||
// Arrange 2
|
// Arrange 2
|
||||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
// Assert 2
|
// Assert 2
|
||||||
Assert.Collection(
|
Assert.Collection(
|
||||||
finder.Entries.OrderBy(kvp => kvp.Key),
|
addressScheme.Entries.OrderBy(kvp => kvp.Key),
|
||||||
(m) =>
|
(m) =>
|
||||||
{
|
{
|
||||||
Assert.Same(endpoint1, m.Value.Single());
|
Assert.Same(endpoint1, m.Value.Single());
|
||||||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EndpointFinder_IgnoresEndpointsWithSuppressLinkGeneration()
|
public void AddressScheme_IgnoresEndpointsWithSuppressLinkGeneration()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
||||||
|
|
@ -114,14 +114,29 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
metadata: new object[] { new EndpointNameMetadata("name1"), new SuppressLinkGenerationMetadata(), });
|
metadata: new object[] { new EndpointNameMetadata("name1"), new SuppressLinkGenerationMetadata(), });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var finder = CreateEndpointFinder(endpoint);
|
var addressScheme = CreateAddressScheme(endpoint);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(finder.Entries);
|
Assert.Empty(addressScheme.Entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EndpointFinder_IgnoresEndpointsWithoutEndpointName()
|
public void AddressScheme_UnsuppressedEndpoint_IsUsed()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
||||||
|
"/a",
|
||||||
|
metadata: new object[] { new EndpointNameMetadata("name1"), new SuppressLinkGenerationMetadata(), new EncourageLinkGenerationMetadata(), });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var addressScheme = CreateAddressScheme(endpoint);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(endpoint, Assert.Single(Assert.Single(addressScheme.Entries).Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddressScheme_IgnoresEndpointsWithoutEndpointName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
||||||
|
|
@ -129,14 +144,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
metadata: new object[] { });
|
metadata: new object[] { });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var finder = CreateEndpointFinder(endpoint);
|
var addressScheme = CreateAddressScheme(endpoint);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(finder.Entries);
|
Assert.Empty(addressScheme.Entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EndpointFinder_ThrowsExceptionForDuplicateEndpoints()
|
public void AddressScheme_ThrowsExceptionForDuplicateEndpoints()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoints = new Endpoint[]
|
var endpoints = new Endpoint[]
|
||||||
|
|
@ -152,10 +167,10 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
EndpointFactory.CreateRouteEndpoint("/f", displayName: "f", metadata: new object[] { new EndpointNameMetadata("name2"), }),
|
EndpointFactory.CreateRouteEndpoint("/f", displayName: "f", metadata: new object[] { new EndpointNameMetadata("name2"), }),
|
||||||
};
|
};
|
||||||
|
|
||||||
var finder = CreateEndpointFinder(endpoints);
|
var addressScheme = CreateAddressScheme(endpoints);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var ex = Assert.Throws<InvalidOperationException>(() => finder.FindEndpoints("any name"));
|
var ex = Assert.Throws<InvalidOperationException>(() => addressScheme.FindEndpoints("any name"));
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(@"The following endpoints with a duplicate endpoint name were found.
|
Assert.Equal(@"The following endpoints with a duplicate endpoint name were found.
|
||||||
|
|
@ -171,14 +186,19 @@ f
|
||||||
", ex.Message);
|
", ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EndpointNameEndpointFinder CreateEndpointFinder(params Endpoint[] endpoints)
|
private EndpointNameAddressScheme CreateAddressScheme(params Endpoint[] endpoints)
|
||||||
{
|
{
|
||||||
return CreateEndpointFinder(new DefaultEndpointDataSource(endpoints));
|
return CreateAddressScheme(new DefaultEndpointDataSource(endpoints));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EndpointNameEndpointFinder CreateEndpointFinder(params EndpointDataSource[] dataSources)
|
private EndpointNameAddressScheme CreateAddressScheme(params EndpointDataSource[] dataSources)
|
||||||
{
|
{
|
||||||
return new EndpointNameEndpointFinder(new CompositeEndpointDataSource(dataSources));
|
return new EndpointNameAddressScheme(new CompositeEndpointDataSource(dataSources));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class EncourageLinkGenerationMetadata : ISuppressLinkGenerationMetadata
|
||||||
|
{
|
||||||
|
public bool SuppressLinkGeneration => false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// Does not cover template processing in detail, those scenarios are validated by TemplateBinderTests
|
// Does not cover template processing in detail, those scenarios are validated by TemplateBinderTests
|
||||||
// and DefaultLinkGeneratorProcessTemplateTest
|
// and DefaultLinkGeneratorProcessTemplateTest
|
||||||
//
|
//
|
||||||
// Does not cover the EndpointNameEndpointFinder in detail. see EndpointNameEndpointFinderTest
|
// Does not cover the EndpointNameAddressScheme in detail. see EndpointNameAddressSchemeTest
|
||||||
public class LinkGeneratorEndpointNameExtensionsTest : LinkGeneratorTestBase
|
public class LinkGeneratorEndpointNameExtensionsTest : LinkGeneratorTestBase
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// Does not cover template processing in detail, those scenarios are validated by TemplateBinderTests
|
// Does not cover template processing in detail, those scenarios are validated by TemplateBinderTests
|
||||||
// and DefaultLinkGeneratorProcessTemplateTest
|
// and DefaultLinkGeneratorProcessTemplateTest
|
||||||
//
|
//
|
||||||
// Does not cover the RouteValueBasedEndpointFinder in detail. see RouteValueBasedEndpointFinderTest
|
// Does not cover the RouteValuesAddressScheme in detail. see RouteValuesAddressSchemeTest
|
||||||
public class LinkGeneratorRouteValuesAddressExtensionsTest : LinkGeneratorTestBase
|
public class LinkGeneratorRouteValuesAddressExtensionsTest : LinkGeneratorTestBase
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
|
||||||
using Microsoft.AspNetCore.Routing.Patterns;
|
using Microsoft.AspNetCore.Routing.Patterns;
|
||||||
using Microsoft.AspNetCore.Routing.TestObjects;
|
using Microsoft.AspNetCore.Routing.TestObjects;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -89,6 +88,27 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
Assert.Empty(inner.Endpoints);
|
Assert.Empty(inner.Endpoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Matcher_UnsuppressedEndpoint_IsUsed()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var dataSource = new DynamicEndpointDataSource();
|
||||||
|
var endpoint = new RouteEndpoint(
|
||||||
|
TestConstants.EmptyRequestDelegate,
|
||||||
|
RoutePatternFactory.Parse("/"),
|
||||||
|
0,
|
||||||
|
new EndpointMetadataCollection(new SuppressMatchingMetadata(), new EncourageMatchingMetadata()),
|
||||||
|
"test");
|
||||||
|
dataSource.AddEndpoint(endpoint);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var matcher = new DataSourceDependentMatcher(dataSource, TestMatcherBuilder.Create);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var inner = Assert.IsType<TestMatcher>(matcher.CurrentMatcher);
|
||||||
|
Assert.Same(endpoint, Assert.Single(inner.Endpoints));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Cache_Reinitializes_WhenDataSourceChanges()
|
public void Cache_Reinitializes_WhenDataSourceChanges()
|
||||||
{
|
{
|
||||||
|
|
@ -139,5 +159,10 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class EncourageMatchingMetadata : ISuppressMatchingMetadata
|
||||||
|
{
|
||||||
|
public bool SuppressMatching => false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
public class RouteValueBasedEndpointFinderTest
|
public class RouteValuesAddressSchemeTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetOutboundMatches_GetsNamedMatchesFor_EndpointsHaving_IRouteNameMetadata()
|
public void GetOutboundMatches_GetsNamedMatchesFor_EndpointsHaving_IRouteNameMetadata()
|
||||||
|
|
@ -22,13 +22,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoint2 = CreateEndpoint("/a", routeName: "named");
|
var endpoint2 = CreateEndpoint("/a", routeName: "named");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var finder = CreateEndpointFinder(endpoint1, endpoint2);
|
var addressScheme = CreateAddressScheme(endpoint1, endpoint2);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(finder.AllMatches);
|
Assert.NotNull(addressScheme.AllMatches);
|
||||||
Assert.Equal(2, finder.AllMatches.Count());
|
Assert.Equal(2, addressScheme.AllMatches.Count());
|
||||||
Assert.NotNull(finder.NamedMatches);
|
Assert.NotNull(addressScheme.NamedMatches);
|
||||||
Assert.True(finder.NamedMatches.TryGetValue("named", out var namedMatches));
|
Assert.True(addressScheme.NamedMatches.TryGetValue("named", out var namedMatches));
|
||||||
var namedMatch = Assert.Single(namedMatches);
|
var namedMatch = Assert.Single(namedMatches);
|
||||||
var actual = Assert.IsType<RouteEndpoint>(namedMatch.Match.Entry.Data);
|
var actual = Assert.IsType<RouteEndpoint>(namedMatch.Match.Entry.Data);
|
||||||
Assert.Same(endpoint2, actual);
|
Assert.Same(endpoint2, actual);
|
||||||
|
|
@ -43,13 +43,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoint3 = CreateEndpoint("/b", routeName: "named");
|
var endpoint3 = CreateEndpoint("/b", routeName: "named");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var finder = CreateEndpointFinder(endpoint1, endpoint2, endpoint3);
|
var addressScheme = CreateAddressScheme(endpoint1, endpoint2, endpoint3);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(finder.AllMatches);
|
Assert.NotNull(addressScheme.AllMatches);
|
||||||
Assert.Equal(3, finder.AllMatches.Count());
|
Assert.Equal(3, addressScheme.AllMatches.Count());
|
||||||
Assert.NotNull(finder.NamedMatches);
|
Assert.NotNull(addressScheme.NamedMatches);
|
||||||
Assert.True(finder.NamedMatches.TryGetValue("named", out var namedMatches));
|
Assert.True(addressScheme.NamedMatches.TryGetValue("named", out var namedMatches));
|
||||||
Assert.Equal(2, namedMatches.Count);
|
Assert.Equal(2, namedMatches.Count);
|
||||||
Assert.Same(endpoint2, Assert.IsType<RouteEndpoint>(namedMatches[0].Match.Entry.Data));
|
Assert.Same(endpoint2, Assert.IsType<RouteEndpoint>(namedMatches[0].Match.Entry.Data));
|
||||||
Assert.Same(endpoint3, Assert.IsType<RouteEndpoint>(namedMatches[1].Match.Entry.Data));
|
Assert.Same(endpoint3, Assert.IsType<RouteEndpoint>(namedMatches[1].Match.Entry.Data));
|
||||||
|
|
@ -64,13 +64,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoint3 = CreateEndpoint("/b", routeName: "NaMed");
|
var endpoint3 = CreateEndpoint("/b", routeName: "NaMed");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var finder = CreateEndpointFinder(endpoint1, endpoint2, endpoint3);
|
var addressScheme = CreateAddressScheme(endpoint1, endpoint2, endpoint3);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(finder.AllMatches);
|
Assert.NotNull(addressScheme.AllMatches);
|
||||||
Assert.Equal(3, finder.AllMatches.Count());
|
Assert.Equal(3, addressScheme.AllMatches.Count());
|
||||||
Assert.NotNull(finder.NamedMatches);
|
Assert.NotNull(addressScheme.NamedMatches);
|
||||||
Assert.True(finder.NamedMatches.TryGetValue("named", out var namedMatches));
|
Assert.True(addressScheme.NamedMatches.TryGetValue("named", out var namedMatches));
|
||||||
Assert.Equal(2, namedMatches.Count);
|
Assert.Equal(2, namedMatches.Count);
|
||||||
Assert.Same(endpoint2, Assert.IsType<RouteEndpoint>(namedMatches[0].Match.Entry.Data));
|
Assert.Same(endpoint2, Assert.IsType<RouteEndpoint>(namedMatches[0].Match.Entry.Data));
|
||||||
Assert.Same(endpoint3, Assert.IsType<RouteEndpoint>(namedMatches[1].Match.Entry.Data));
|
Assert.Same(endpoint3, Assert.IsType<RouteEndpoint>(namedMatches[1].Match.Entry.Data));
|
||||||
|
|
@ -84,11 +84,11 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var dynamicDataSource = new DynamicEndpointDataSource(new[] { endpoint1 });
|
var dynamicDataSource = new DynamicEndpointDataSource(new[] { endpoint1 });
|
||||||
|
|
||||||
// Act 1
|
// Act 1
|
||||||
var finder = new CustomRouteValuesBasedEndpointFinder(new CompositeEndpointDataSource(new[] { dynamicDataSource }));
|
var addressScheme = new CustomRouteValuesBasedAddressScheme(new CompositeEndpointDataSource(new[] { dynamicDataSource }));
|
||||||
|
|
||||||
// Assert 1
|
// Assert 1
|
||||||
Assert.NotNull(finder.AllMatches);
|
Assert.NotNull(addressScheme.AllMatches);
|
||||||
var match = Assert.Single(finder.AllMatches);
|
var match = Assert.Single(addressScheme.AllMatches);
|
||||||
var actual = Assert.IsType<RouteEndpoint>(match.Entry.Data);
|
var actual = Assert.IsType<RouteEndpoint>(match.Entry.Data);
|
||||||
Assert.Same(endpoint1, actual);
|
Assert.Same(endpoint1, actual);
|
||||||
|
|
||||||
|
|
@ -114,9 +114,9 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
dynamicDataSource.AddEndpoint(endpoint4);
|
dynamicDataSource.AddEndpoint(endpoint4);
|
||||||
|
|
||||||
// Assert 3
|
// Assert 3
|
||||||
Assert.NotNull(finder.AllMatches);
|
Assert.NotNull(addressScheme.AllMatches);
|
||||||
Assert.Collection(
|
Assert.Collection(
|
||||||
finder.AllMatches,
|
addressScheme.AllMatches,
|
||||||
(m) =>
|
(m) =>
|
||||||
{
|
{
|
||||||
actual = Assert.IsType<RouteEndpoint>(m.Entry.Data);
|
actual = Assert.IsType<RouteEndpoint>(m.Entry.Data);
|
||||||
|
|
@ -148,10 +148,10 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
defaults: new { controller = "Orders", action = "GetById" },
|
defaults: new { controller = "Orders", action = "GetById" },
|
||||||
requiredValues: new { controller = "Orders", action = "GetById" },
|
requiredValues: new { controller = "Orders", action = "GetById" },
|
||||||
routeName: "OrdersApi");
|
routeName: "OrdersApi");
|
||||||
var finder = CreateEndpointFinder(expected);
|
var addressScheme = CreateAddressScheme(expected);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var foundEndpoints = finder.FindEndpoints(
|
var foundEndpoints = addressScheme.FindEndpoints(
|
||||||
new RouteValuesAddress
|
new RouteValuesAddress
|
||||||
{
|
{
|
||||||
ExplicitValues = new RouteValueDictionary(new { id = 10 }),
|
ExplicitValues = new RouteValueDictionary(new { id = 10 }),
|
||||||
|
|
@ -167,7 +167,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
[Fact]
|
[Fact]
|
||||||
public void FindEndpoints_AlwaysReturnsEndpointsByRouteName_IgnoringMissingRequiredParameterValues()
|
public void FindEndpoints_AlwaysReturnsEndpointsByRouteName_IgnoringMissingRequiredParameterValues()
|
||||||
{
|
{
|
||||||
// Here 'id' is the required value. The endpoint finder would always return an endpoint by looking up
|
// Here 'id' is the required value. The endpoint addressScheme would always return an endpoint by looking up
|
||||||
// name only. Its the link generator which uses these endpoints finally to generate a link or not
|
// name only. Its the link generator which uses these endpoints finally to generate a link or not
|
||||||
// based on the required parameter values being present or not.
|
// based on the required parameter values being present or not.
|
||||||
|
|
||||||
|
|
@ -177,10 +177,10 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
defaults: new { controller = "Orders", action = "GetById" },
|
defaults: new { controller = "Orders", action = "GetById" },
|
||||||
requiredValues: new { controller = "Orders", action = "GetById" },
|
requiredValues: new { controller = "Orders", action = "GetById" },
|
||||||
routeName: "OrdersApi");
|
routeName: "OrdersApi");
|
||||||
var finder = CreateEndpointFinder(expected);
|
var addressScheme = CreateAddressScheme(expected);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var foundEndpoints = finder.FindEndpoints(
|
var foundEndpoints = addressScheme.FindEndpoints(
|
||||||
new RouteValuesAddress
|
new RouteValuesAddress
|
||||||
{
|
{
|
||||||
ExplicitValues = new RouteValueDictionary(),
|
ExplicitValues = new RouteValueDictionary(),
|
||||||
|
|
@ -202,20 +202,35 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
metadataCollection: new EndpointMetadataCollection(new[] { new SuppressLinkGenerationMetadata() }));
|
metadataCollection: new EndpointMetadataCollection(new[] { new SuppressLinkGenerationMetadata() }));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var finder = CreateEndpointFinder(endpoint);
|
var addressScheme = CreateAddressScheme(endpoint);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(finder.AllMatches);
|
Assert.Empty(addressScheme.AllMatches);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CustomRouteValuesBasedEndpointFinder CreateEndpointFinder(params Endpoint[] endpoints)
|
[Fact]
|
||||||
|
public void AddressScheme_UnsuppressedEndpoint_IsUsed()
|
||||||
{
|
{
|
||||||
return CreateEndpointFinder(new DefaultEndpointDataSource(endpoints));
|
// Arrange
|
||||||
|
var endpoint = EndpointFactory.CreateRouteEndpoint(
|
||||||
|
"/a",
|
||||||
|
metadata: new object[] { new SuppressLinkGenerationMetadata(), new EncourageLinkGenerationMetadata(), });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var addressScheme = CreateAddressScheme(endpoint);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(endpoint, Assert.Single(addressScheme.AllMatches).Entry.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CustomRouteValuesBasedEndpointFinder CreateEndpointFinder(params EndpointDataSource[] dataSources)
|
private CustomRouteValuesBasedAddressScheme CreateAddressScheme(params Endpoint[] endpoints)
|
||||||
{
|
{
|
||||||
return new CustomRouteValuesBasedEndpointFinder(new CompositeEndpointDataSource(dataSources));
|
return CreateAddressScheme(new DefaultEndpointDataSource(endpoints));
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomRouteValuesBasedAddressScheme CreateAddressScheme(params EndpointDataSource[] dataSources)
|
||||||
|
{
|
||||||
|
return new CustomRouteValuesBasedAddressScheme(new CompositeEndpointDataSource(dataSources));
|
||||||
}
|
}
|
||||||
|
|
||||||
private RouteEndpoint CreateEndpoint(
|
private RouteEndpoint CreateEndpoint(
|
||||||
|
|
@ -244,9 +259,9 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CustomRouteValuesBasedEndpointFinder : RouteValuesBasedEndpointFinder
|
private class CustomRouteValuesBasedAddressScheme : RouteValuesAddressScheme
|
||||||
{
|
{
|
||||||
public CustomRouteValuesBasedEndpointFinder(CompositeEndpointDataSource dataSource)
|
public CustomRouteValuesBasedAddressScheme(CompositeEndpointDataSource dataSource)
|
||||||
: base(dataSource)
|
: base(dataSource)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -263,5 +278,10 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class EncourageLinkGenerationMetadata : ISuppressLinkGenerationMetadata
|
||||||
|
{
|
||||||
|
public bool SuppressLinkGeneration => false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue