Added a RouteValuesBasedEndpointFinder
This commit is contained in:
parent
bc5f02444b
commit
1009705283
|
|
@ -32,11 +32,11 @@ namespace Benchmarks
|
||||||
return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength);
|
return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength);
|
||||||
},
|
},
|
||||||
template: "/plaintext",
|
template: "/plaintext",
|
||||||
values: new { },
|
defaults: new RouteValueDictionary(),
|
||||||
|
requiredValues: new RouteValueDictionary(),
|
||||||
order: 0,
|
order: 0,
|
||||||
metadata: EndpointMetadataCollection.Empty,
|
metadata: EndpointMetadataCollection.Empty,
|
||||||
displayName: "Plaintext",
|
displayName: "Plaintext"),
|
||||||
address: null),
|
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,11 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
return new MatcherEndpoint(
|
return new MatcherEndpoint(
|
||||||
(next) => (context) => Task.CompletedTask,
|
(next) => (context) => Task.CompletedTask,
|
||||||
template,
|
template,
|
||||||
new { },
|
new RouteValueDictionary(),
|
||||||
|
new RouteValueDictionary(),
|
||||||
0,
|
0,
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
template,
|
template);
|
||||||
address: null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int[] SampleRequests(int endpointCount, int count)
|
internal static int[] SampleRequests(int endpointCount, int count)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace DispatcherSample.Web
|
||||||
response.ContentLength = payloadLength;
|
response.ContentLength = payloadLength;
|
||||||
return response.Body.WriteAsync(_homePayload, 0, payloadLength);
|
return response.Body.WriteAsync(_homePayload, 0, payloadLength);
|
||||||
},
|
},
|
||||||
"/", new { }, 0, EndpointMetadataCollection.Empty, "Home", address: null),
|
"/", new RouteValueDictionary(), new RouteValueDictionary(), 0, EndpointMetadataCollection.Empty, "Home"),
|
||||||
new MatcherEndpoint((next) => (httpContext) =>
|
new MatcherEndpoint((next) => (httpContext) =>
|
||||||
{
|
{
|
||||||
var response = httpContext.Response;
|
var response = httpContext.Response;
|
||||||
|
|
@ -41,7 +41,7 @@ namespace DispatcherSample.Web
|
||||||
response.ContentLength = payloadLength;
|
response.ContentLength = payloadLength;
|
||||||
return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength);
|
return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength);
|
||||||
},
|
},
|
||||||
"/plaintext", new { }, 0, EndpointMetadataCollection.Empty, "Plaintext", address: null),
|
"/plaintext", new RouteValueDictionary(), new RouteValueDictionary(), 0, EndpointMetadataCollection.Empty, "Plaintext"),
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,15 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
protected Endpoint(
|
protected Endpoint(
|
||||||
EndpointMetadataCollection metadata,
|
EndpointMetadataCollection metadata,
|
||||||
string displayName,
|
string displayName)
|
||||||
Address address)
|
|
||||||
{
|
{
|
||||||
// All are allowed to be null
|
// All are allowed to be null
|
||||||
Metadata = metadata ?? EndpointMetadataCollection.Empty;
|
Metadata = metadata ?? EndpointMetadataCollection.Empty;
|
||||||
DisplayName = displayName;
|
DisplayName = displayName;
|
||||||
Address = address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DisplayName { get; }
|
public string DisplayName { get; }
|
||||||
|
|
||||||
public EndpointMetadataCollection Metadata { get; }
|
public EndpointMetadataCollection Metadata { get; }
|
||||||
|
|
||||||
public Address Address { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
public interface IEndpointFinder
|
public interface IEndpointFinder<TAddress>
|
||||||
{
|
{
|
||||||
IEnumerable<Endpoint> FindEndpoints(Address address);
|
IEnumerable<Endpoint> FindEndpoints(TAddress address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,21 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
public interface ILinkGenerator
|
public interface ILinkGenerator
|
||||||
{
|
{
|
||||||
bool TryGetLink(LinkGeneratorContext context, out string link);
|
bool TryGetLink(
|
||||||
|
IEnumerable<Endpoint> endpoints,
|
||||||
|
RouteValueDictionary explicitValues,
|
||||||
|
RouteValueDictionary ambientValues,
|
||||||
|
out string link);
|
||||||
|
|
||||||
string GetLink(LinkGeneratorContext context);
|
string GetLink(
|
||||||
|
IEnumerable<Endpoint> endpoints,
|
||||||
|
RouteValueDictionary explicitValues,
|
||||||
|
RouteValueDictionary ambientValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.Routing
|
||||||
{
|
{
|
||||||
public class Address
|
public interface INameMetadata
|
||||||
{
|
{
|
||||||
public Address()
|
string Name { get; }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Address(string name)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
public interface IRouteNameMetadata
|
||||||
|
{
|
||||||
|
string Name { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,53 +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.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
|
||||||
{
|
|
||||||
internal class DefaultEndpointFinder : IEndpointFinder
|
|
||||||
{
|
|
||||||
private readonly CompositeEndpointDataSource _endpointDatasource;
|
|
||||||
private readonly ILogger<DefaultEndpointFinder> _logger;
|
|
||||||
|
|
||||||
public DefaultEndpointFinder(
|
|
||||||
CompositeEndpointDataSource endpointDataSource,
|
|
||||||
ILogger<DefaultEndpointFinder> logger)
|
|
||||||
{
|
|
||||||
_endpointDatasource = endpointDataSource;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Endpoint> FindEndpoints(Address lookupAddress)
|
|
||||||
{
|
|
||||||
var allEndpoints = _endpointDatasource.Endpoints;
|
|
||||||
|
|
||||||
if (lookupAddress == null || string.IsNullOrEmpty(lookupAddress.Name))
|
|
||||||
{
|
|
||||||
return allEndpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
var endpointsWithAddress = allEndpoints.Where(ep => ep.Address != null);
|
|
||||||
if (!endpointsWithAddress.Any())
|
|
||||||
{
|
|
||||||
return allEndpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var endpoint in endpointsWithAddress)
|
|
||||||
{
|
|
||||||
if (string.Equals(lookupAddress.Name, endpoint.Address.Name, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return new[] { endpoint };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogDebug(
|
|
||||||
$"Could not find an endpoint having an address with name '{lookupAddress.Name}'.");
|
|
||||||
|
|
||||||
return Enumerable.Empty<Endpoint>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,23 +15,23 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
public class DefaultLinkGenerator : ILinkGenerator
|
public class DefaultLinkGenerator : ILinkGenerator
|
||||||
{
|
{
|
||||||
private readonly IEndpointFinder _endpointFinder;
|
|
||||||
private readonly ObjectPool<UriBuildingContext> _uriBuildingContextPool;
|
private readonly ObjectPool<UriBuildingContext> _uriBuildingContextPool;
|
||||||
private readonly ILogger<DefaultLinkGenerator> _logger;
|
private readonly ILogger<DefaultLinkGenerator> _logger;
|
||||||
|
|
||||||
public DefaultLinkGenerator(
|
public DefaultLinkGenerator(
|
||||||
IEndpointFinder endpointFinder,
|
|
||||||
ObjectPool<UriBuildingContext> uriBuildingContextPool,
|
ObjectPool<UriBuildingContext> uriBuildingContextPool,
|
||||||
ILogger<DefaultLinkGenerator> logger)
|
ILogger<DefaultLinkGenerator> logger)
|
||||||
{
|
{
|
||||||
_endpointFinder = endpointFinder;
|
|
||||||
_uriBuildingContextPool = uriBuildingContextPool;
|
_uriBuildingContextPool = uriBuildingContextPool;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLink(LinkGeneratorContext context)
|
public string GetLink(
|
||||||
|
IEnumerable<Endpoint> endpoints,
|
||||||
|
RouteValueDictionary explicitValues,
|
||||||
|
RouteValueDictionary ambientValues)
|
||||||
{
|
{
|
||||||
if (TryGetLink(context, out var link))
|
if (TryGetLink(endpoints, explicitValues, ambientValues, out var link))
|
||||||
{
|
{
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
@ -39,10 +39,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
throw new InvalidOperationException("Could not find a matching endpoint to generate a link.");
|
throw new InvalidOperationException("Could not find a matching endpoint to generate a link.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetLink(LinkGeneratorContext context, out string link)
|
public bool TryGetLink(
|
||||||
|
IEnumerable<Endpoint> endpoints,
|
||||||
|
RouteValueDictionary explicitValues,
|
||||||
|
RouteValueDictionary ambientValues,
|
||||||
|
out string link)
|
||||||
{
|
{
|
||||||
var address = context.Address;
|
|
||||||
var endpoints = _endpointFinder.FindEndpoints(address);
|
|
||||||
link = null;
|
link = null;
|
||||||
|
|
||||||
if (endpoints == null)
|
if (endpoints == null)
|
||||||
|
|
@ -59,7 +61,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
foreach (var endpoint in matcherEndpoints)
|
foreach (var endpoint in matcherEndpoints)
|
||||||
{
|
{
|
||||||
link = GetLink(endpoint.ParsedTemlate, endpoint.Values, context);
|
link = GetLink(endpoint.ParsedTemplate, endpoint.Defaults, explicitValues, ambientValues);
|
||||||
if (link != null)
|
if (link != null)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -71,19 +73,17 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
private string GetLink(
|
private string GetLink(
|
||||||
RouteTemplate template,
|
RouteTemplate template,
|
||||||
IReadOnlyDictionary<string, object> defaultValues,
|
RouteValueDictionary defaults,
|
||||||
LinkGeneratorContext context)
|
RouteValueDictionary explicitValues,
|
||||||
|
RouteValueDictionary ambientValues)
|
||||||
{
|
{
|
||||||
var defaults = new RouteValueDictionary(defaultValues);
|
|
||||||
var templateBinder = new TemplateBinder(
|
var templateBinder = new TemplateBinder(
|
||||||
UrlEncoder.Default,
|
UrlEncoder.Default,
|
||||||
_uriBuildingContextPool,
|
_uriBuildingContextPool,
|
||||||
template,
|
template,
|
||||||
defaults);
|
defaults);
|
||||||
|
|
||||||
var values = templateBinder.GetValues(
|
var values = templateBinder.GetValues(ambientValues, explicitValues);
|
||||||
new RouteValueDictionary(context.AmbientValues),
|
|
||||||
new RouteValueDictionary(context.SuppliedValues));
|
|
||||||
if (values == null)
|
if (values == null)
|
||||||
{
|
{
|
||||||
// We're missing one of the required values for this route.
|
// We're missing one of the required values for this route.
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
||||||
|
using Microsoft.AspNetCore.Routing.EndpointFinders;
|
||||||
using Microsoft.AspNetCore.Routing.Matchers;
|
using Microsoft.AspNetCore.Routing.Matchers;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
@ -35,7 +37,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
services.TryAddSingleton<MatcherFactory, TreeMatcherFactory>();
|
services.TryAddSingleton<MatcherFactory, TreeMatcherFactory>();
|
||||||
|
|
||||||
// Link generation related services
|
// Link generation related services
|
||||||
services.TryAddSingleton<IEndpointFinder, DefaultEndpointFinder>();
|
services.TryAddSingleton<IEndpointFinder<string>, NameBasedEndpointFinder>();
|
||||||
|
services.TryAddSingleton<IEndpointFinder<RouteValuesBasedEndpointFinderContext>, RouteValuesBasedEndpointFinder>();
|
||||||
services.TryAddSingleton<ILinkGenerator, DefaultLinkGenerator>();
|
services.TryAddSingleton<ILinkGenerator, DefaultLinkGenerator>();
|
||||||
//
|
//
|
||||||
// Endpoint Selection
|
// Endpoint Selection
|
||||||
|
|
|
||||||
|
|
@ -20,18 +20,18 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
new OutboundMatchClassifier());
|
new OutboundMatchClassifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<OutboundMatchResult> GetMatches(VirtualPathContext context)
|
public IList<OutboundMatchResult> GetMatches(RouteValueDictionary values, RouteValueDictionary ambientValues)
|
||||||
{
|
{
|
||||||
// Perf: Avoid allocation for List if there aren't any Matches or Criteria
|
// Perf: Avoid allocation for List if there aren't any Matches or Criteria
|
||||||
if (_root.Matches.Count > 0 || _root.Criteria.Count > 0)
|
if (_root.Matches.Count > 0 || _root.Criteria.Count > 0)
|
||||||
{
|
{
|
||||||
var results = new List<OutboundMatchResult>();
|
var results = new List<OutboundMatchResult>();
|
||||||
Walk(results, context, _root, isFallbackPath: false);
|
Walk(results, values, ambientValues, _root, isFallbackPath: false);
|
||||||
results.Sort(OutboundMatchResultComparer.Instance);
|
results.Sort(OutboundMatchResultComparer.Instance);
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to recursively walk the decision tree based on the provided route data
|
// We need to recursively walk the decision tree based on the provided route data
|
||||||
|
|
@ -61,7 +61,8 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
// The decision tree uses a tree data structure to execute these rules across all candidates at once.
|
// The decision tree uses a tree data structure to execute these rules across all candidates at once.
|
||||||
private void Walk(
|
private void Walk(
|
||||||
List<OutboundMatchResult> results,
|
List<OutboundMatchResult> results,
|
||||||
VirtualPathContext context,
|
RouteValueDictionary values,
|
||||||
|
RouteValueDictionary ambientValues,
|
||||||
DecisionTreeNode<OutboundMatch> node,
|
DecisionTreeNode<OutboundMatch> node,
|
||||||
bool isFallbackPath)
|
bool isFallbackPath)
|
||||||
{
|
{
|
||||||
|
|
@ -78,12 +79,12 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
var key = criterion.Key;
|
var key = criterion.Key;
|
||||||
|
|
||||||
object value;
|
object value;
|
||||||
if (context.Values.TryGetValue(key, out value))
|
if (values.TryGetValue(key, out value))
|
||||||
{
|
{
|
||||||
DecisionTreeNode<OutboundMatch> branch;
|
DecisionTreeNode<OutboundMatch> branch;
|
||||||
if (criterion.Branches.TryGetValue(value ?? string.Empty, out branch))
|
if (criterion.Branches.TryGetValue(value ?? string.Empty, out branch))
|
||||||
{
|
{
|
||||||
Walk(results, context, branch, isFallbackPath);
|
Walk(results, values, ambientValues, branch, isFallbackPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -92,18 +93,18 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
// if an ambient value was supplied. The path explored with the empty value is considered
|
// if an ambient value was supplied. The path explored with the empty value is considered
|
||||||
// the fallback path.
|
// the fallback path.
|
||||||
DecisionTreeNode<OutboundMatch> branch;
|
DecisionTreeNode<OutboundMatch> branch;
|
||||||
if (context.AmbientValues.TryGetValue(key, out value) &&
|
if (ambientValues.TryGetValue(key, out value) &&
|
||||||
!criterion.Branches.Comparer.Equals(value, string.Empty))
|
!criterion.Branches.Comparer.Equals(value, string.Empty))
|
||||||
{
|
{
|
||||||
if (criterion.Branches.TryGetValue(value, out branch))
|
if (criterion.Branches.TryGetValue(value, out branch))
|
||||||
{
|
{
|
||||||
Walk(results, context, branch, isFallbackPath);
|
Walk(results, values, ambientValues, branch, isFallbackPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (criterion.Branches.TryGetValue(string.Empty, out branch))
|
if (criterion.Branches.TryGetValue(string.Empty, out branch))
|
||||||
{
|
{
|
||||||
Walk(results, context, branch, isFallbackPath: true);
|
Walk(results, values, ambientValues, branch, isFallbackPath: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +156,7 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
return StringComparer.Ordinal.Compare(
|
return StringComparer.Ordinal.Compare(
|
||||||
x.Match.Entry.RouteTemplate.TemplateText,
|
x.Match.Entry.RouteTemplate.TemplateText,
|
||||||
y.Match.Entry.RouteTemplate.TemplateText);
|
y.Match.Entry.RouteTemplate.TemplateText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Routing.Template;
|
using Microsoft.AspNetCore.Routing.Template;
|
||||||
|
|
@ -19,12 +18,12 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
public MatcherEndpoint(
|
public MatcherEndpoint(
|
||||||
Func<RequestDelegate, RequestDelegate> invoker,
|
Func<RequestDelegate, RequestDelegate> invoker,
|
||||||
string template,
|
string template,
|
||||||
object values,
|
RouteValueDictionary defaults,
|
||||||
|
RouteValueDictionary requiredValues,
|
||||||
int order,
|
int order,
|
||||||
EndpointMetadataCollection metadata,
|
EndpointMetadataCollection metadata,
|
||||||
string displayName,
|
string displayName)
|
||||||
Address address)
|
: base(metadata, displayName)
|
||||||
: base(metadata, displayName, address)
|
|
||||||
{
|
{
|
||||||
if (invoker == null)
|
if (invoker == null)
|
||||||
{
|
{
|
||||||
|
|
@ -37,24 +36,31 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
}
|
}
|
||||||
|
|
||||||
Invoker = invoker;
|
Invoker = invoker;
|
||||||
Template = template;
|
|
||||||
ParsedTemlate = TemplateParser.Parse(template);
|
|
||||||
var mergedDefaults = GetDefaults(ParsedTemlate, new RouteValueDictionary(values));
|
|
||||||
Values = mergedDefaults;
|
|
||||||
Order = order;
|
Order = order;
|
||||||
|
|
||||||
|
Template = template;
|
||||||
|
ParsedTemplate = TemplateParser.Parse(template);
|
||||||
|
|
||||||
|
RequiredValues = requiredValues;
|
||||||
|
var mergedDefaults = GetDefaults(ParsedTemplate, defaults);
|
||||||
|
Defaults = mergedDefaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Order { get; }
|
public int Order { get; }
|
||||||
public Func<RequestDelegate, RequestDelegate> Invoker { get; }
|
public Func<RequestDelegate, RequestDelegate> Invoker { get; }
|
||||||
public string Template { get; }
|
public string Template { get; }
|
||||||
public IReadOnlyDictionary<string, object> Values { get; }
|
public RouteValueDictionary Defaults { get; }
|
||||||
|
|
||||||
|
// Values required by an endpoint for it to be successfully matched on link generation
|
||||||
|
public RouteValueDictionary RequiredValues { get; }
|
||||||
|
|
||||||
// Todo: needs review
|
// Todo: needs review
|
||||||
public RouteTemplate ParsedTemlate { get; }
|
public RouteTemplate ParsedTemplate { get; }
|
||||||
|
|
||||||
private RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate, RouteValueDictionary defaults)
|
// Merge inline and non inline defaults into one
|
||||||
|
private RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate, RouteValueDictionary nonInlineDefaults)
|
||||||
{
|
{
|
||||||
var result = defaults == null ? new RouteValueDictionary() : new RouteValueDictionary(defaults);
|
var result = nonInlineDefaults == null ? new RouteValueDictionary() : new RouteValueDictionary(nonInlineDefaults);
|
||||||
|
|
||||||
foreach (var parameter in parsedTemplate.Parameters)
|
foreach (var parameter in parsedTemplate.Parameters)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
{
|
{
|
||||||
if (feature.Endpoint is MatcherEndpoint endpoint)
|
if (feature.Endpoint is MatcherEndpoint endpoint)
|
||||||
{
|
{
|
||||||
foreach (var kvp in endpoint.Values)
|
foreach (var kvp in endpoint.Defaults)
|
||||||
{
|
{
|
||||||
if (!feature.Values.ContainsKey(kvp.Key))
|
if (!feature.Values.ContainsKey(kvp.Key))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// 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 System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Routing.Matchers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Routing
|
||||||
|
{
|
||||||
|
internal class NameBasedEndpointFinder : IEndpointFinder<string>
|
||||||
|
{
|
||||||
|
private readonly CompositeEndpointDataSource _endpointDatasource;
|
||||||
|
private readonly ILogger<NameBasedEndpointFinder> _logger;
|
||||||
|
|
||||||
|
public NameBasedEndpointFinder(
|
||||||
|
CompositeEndpointDataSource endpointDataSource,
|
||||||
|
ILogger<NameBasedEndpointFinder> logger)
|
||||||
|
{
|
||||||
|
_endpointDatasource = endpointDataSource;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Endpoint> FindEndpoints(string endpointName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(endpointName))
|
||||||
|
{
|
||||||
|
return Array.Empty<Endpoint>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var endpoints = _endpointDatasource.Endpoints.OfType<MatcherEndpoint>();
|
||||||
|
|
||||||
|
foreach (var endpoint in endpoints)
|
||||||
|
{
|
||||||
|
var nameMetadata = endpoint.Metadata.GetMetadata<INameMetadata>();
|
||||||
|
if (nameMetadata != null &&
|
||||||
|
string.Equals(endpointName, nameMetadata.Name, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return new[] { endpoint };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Array.Empty<Endpoint>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
// 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 System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Routing.EndpointFinders;
|
||||||
|
using Microsoft.AspNetCore.Routing.Internal;
|
||||||
|
using Microsoft.AspNetCore.Routing.Matchers;
|
||||||
|
using Microsoft.AspNetCore.Routing.Template;
|
||||||
|
using Microsoft.AspNetCore.Routing.Tree;
|
||||||
|
using Microsoft.Extensions.ObjectPool;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Routing
|
||||||
|
{
|
||||||
|
internal class RouteValuesBasedEndpointFinder : IEndpointFinder<RouteValuesBasedEndpointFinderContext>
|
||||||
|
{
|
||||||
|
private readonly CompositeEndpointDataSource _endpointDataSource;
|
||||||
|
private readonly IInlineConstraintResolver _inlineConstraintResolver;
|
||||||
|
private readonly ObjectPool<UriBuildingContext> _objectPool;
|
||||||
|
private LinkGenerationDecisionTree _allMatchesLinkGenerationTree;
|
||||||
|
private IDictionary<string, LinkGenerationDecisionTree> _namedMatches;
|
||||||
|
|
||||||
|
public RouteValuesBasedEndpointFinder(
|
||||||
|
CompositeEndpointDataSource endpointDataSource,
|
||||||
|
ObjectPool<UriBuildingContext> objectPool,
|
||||||
|
IInlineConstraintResolver inlineConstraintResolver)
|
||||||
|
{
|
||||||
|
_endpointDataSource = endpointDataSource;
|
||||||
|
_objectPool = objectPool;
|
||||||
|
_inlineConstraintResolver = inlineConstraintResolver;
|
||||||
|
|
||||||
|
BuildOutboundMatches();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Endpoint> FindEndpoints(RouteValuesBasedEndpointFinderContext context)
|
||||||
|
{
|
||||||
|
IEnumerable<OutboundMatchResult> matchResults = null;
|
||||||
|
if (string.IsNullOrEmpty(context.RouteName))
|
||||||
|
{
|
||||||
|
matchResults = _allMatchesLinkGenerationTree.GetMatches(
|
||||||
|
context.ExplicitValues,
|
||||||
|
context.AmbientValues);
|
||||||
|
}
|
||||||
|
else if (_namedMatches.TryGetValue(context.RouteName, out var linkGenerationTree))
|
||||||
|
{
|
||||||
|
matchResults = linkGenerationTree.GetMatches(
|
||||||
|
context.ExplicitValues,
|
||||||
|
context.AmbientValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchResults == null || !matchResults.Any())
|
||||||
|
{
|
||||||
|
return Array.Empty<Endpoint>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchResults
|
||||||
|
.Select(matchResult => matchResult.Match)
|
||||||
|
.Select(match => (MatcherEndpoint)match.Entry.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildOutboundMatches()
|
||||||
|
{
|
||||||
|
var (allOutboundMatches, namedOutboundMatches) = GetOutboundMatches();
|
||||||
|
_namedMatches = GetNamedMatches(namedOutboundMatches);
|
||||||
|
_allMatchesLinkGenerationTree = new LinkGenerationDecisionTree(allOutboundMatches.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private (IEnumerable<OutboundMatch>, IDictionary<string, List<OutboundMatch>>) GetOutboundMatches()
|
||||||
|
{
|
||||||
|
var allOutboundMatches = new List<OutboundMatch>();
|
||||||
|
var namedOutboundMatches = new Dictionary<string, List<OutboundMatch>>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var endpoints = _endpointDataSource.Endpoints.OfType<MatcherEndpoint>();
|
||||||
|
foreach (var endpoint in endpoints)
|
||||||
|
{
|
||||||
|
var entry = CreateOutboundRouteEntry(endpoint);
|
||||||
|
|
||||||
|
var outboundMatch = new OutboundMatch() { Entry = entry };
|
||||||
|
allOutboundMatches.Add(outboundMatch);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(entry.RouteName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<OutboundMatch> matches;
|
||||||
|
if (!namedOutboundMatches.TryGetValue(entry.RouteName, out matches))
|
||||||
|
{
|
||||||
|
matches = new List<OutboundMatch>();
|
||||||
|
namedOutboundMatches.Add(entry.RouteName, matches);
|
||||||
|
}
|
||||||
|
matches.Add(outboundMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (allOutboundMatches, namedOutboundMatches);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OutboundRouteEntry CreateOutboundRouteEntry(MatcherEndpoint endpoint)
|
||||||
|
{
|
||||||
|
var routeNameMetadata = endpoint.Metadata.GetMetadata<IRouteNameMetadata>();
|
||||||
|
var entry = new OutboundRouteEntry()
|
||||||
|
{
|
||||||
|
Handler = NullRouter.Instance,
|
||||||
|
Order = endpoint.Order,
|
||||||
|
Precedence = RoutePrecedence.ComputeOutbound(endpoint.ParsedTemplate),
|
||||||
|
RequiredLinkValues = endpoint.RequiredValues,
|
||||||
|
RouteTemplate = endpoint.ParsedTemplate,
|
||||||
|
Data = endpoint,
|
||||||
|
RouteName = routeNameMetadata?.Name,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: review. These route constriants should be constructed when the endpoint
|
||||||
|
// is built. This way they can be checked for validity on app startup too
|
||||||
|
var constraintBuilder = new RouteConstraintBuilder(
|
||||||
|
_inlineConstraintResolver,
|
||||||
|
endpoint.ParsedTemplate.TemplateText);
|
||||||
|
foreach (var parameter in endpoint.ParsedTemplate.Parameters)
|
||||||
|
{
|
||||||
|
if (parameter.InlineConstraints != null)
|
||||||
|
{
|
||||||
|
if (parameter.IsOptional)
|
||||||
|
{
|
||||||
|
constraintBuilder.SetOptional(parameter.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var constraint in parameter.InlineConstraints)
|
||||||
|
{
|
||||||
|
constraintBuilder.AddResolvedConstraint(parameter.Name, constraint.Constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry.Constraints = constraintBuilder.Build();
|
||||||
|
entry.Defaults = endpoint.Defaults;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IDictionary<string, LinkGenerationDecisionTree> GetNamedMatches(
|
||||||
|
IDictionary<string, List<OutboundMatch>> namedOutboundMatches)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, LinkGenerationDecisionTree>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var namedOutboundMatch in namedOutboundMatches)
|
||||||
|
{
|
||||||
|
result.Add(namedOutboundMatch.Key, new LinkGenerationDecisionTree(namedOutboundMatch.Value.ToArray()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used only to hook up link generation, and it doesn't need to do anything.
|
||||||
|
private class NullRouter : IRouter
|
||||||
|
{
|
||||||
|
public static readonly NullRouter Instance = new NullRouter();
|
||||||
|
|
||||||
|
public VirtualPathData GetVirtualPath(VirtualPathContext context)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task RouteAsync(RouteContext context)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.Routing.EndpointFinders
|
||||||
{
|
{
|
||||||
public class LinkGeneratorContext
|
public class RouteValuesBasedEndpointFinderContext
|
||||||
{
|
{
|
||||||
public Address Address { get; set; }
|
public string RouteName { get; set; }
|
||||||
|
|
||||||
|
public RouteValueDictionary ExplicitValues { get; set; }
|
||||||
|
|
||||||
public RouteValueDictionary AmbientValues { get; set; }
|
public RouteValueDictionary AmbientValues { get; set; }
|
||||||
|
|
||||||
public RouteValueDictionary SuppliedValues { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -58,5 +58,10 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
||||||
/// Gets or sets the <see cref="RouteTemplate"/>.
|
/// Gets or sets the <see cref="RouteTemplate"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RouteTemplate RouteTemplate { get; set; }
|
public RouteTemplate RouteTemplate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the data that is associated with this entry.
|
||||||
|
/// </summary>
|
||||||
|
public object Data { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
||||||
|
|
||||||
// The decision tree will give us back all entries that match the provided route data in the correct
|
// The decision tree will give us back all entries that match the provided route data in the correct
|
||||||
// order. We just need to iterate them and use the first one that can generate a link.
|
// order. We just need to iterate them and use the first one that can generate a link.
|
||||||
var matches = _linkGenerationTree.GetMatches(context);
|
var matches = _linkGenerationTree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
if (matches == null)
|
if (matches == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,161 +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.
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Routing.TestObjects;
|
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
|
||||||
{
|
|
||||||
public class DefaultEndpointFinderTest
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public void FindEndpoints_IgnoresCase_ForRouteNameLookup()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = CreateEndpoint(new Address("home"));
|
|
||||||
var endpoint2 = CreateEndpoint(new Address("admin"));
|
|
||||||
var endpointFinder = CreateDefaultEndpointFinder(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var result = endpointFinder.FindEndpoints(new Address("Admin"));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var endpoint = Assert.Single(result);
|
|
||||||
Assert.Same(endpoint2, endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void FindEndpoints_MultipleEndpointsWithSameName_ReturnsFirstEndpoint_WithMatchingName()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var name = "common-tag-for-all-my-section's-routes";
|
|
||||||
var endpoint1 = CreateEndpoint(new Address(name));
|
|
||||||
var endpoint2 = CreateEndpoint(new Address("admin"));
|
|
||||||
var endpoint3 = CreateEndpoint(new Address(name));
|
|
||||||
var endpoint4 = CreateEndpoint(new Address("products"));
|
|
||||||
var endpointFinder = CreateDefaultEndpointFinder(endpoint1, endpoint2, endpoint3, endpoint4);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var result = endpointFinder.FindEndpoints(new Address(name));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var endpoint = Assert.Single(result);
|
|
||||||
Assert.Same(endpoint, endpoint1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void FindEndpoints_ReturnsAllEndpoints_WhenNoEndpointsHaveAddress()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = CreateEndpoint(address: null);
|
|
||||||
var endpoint2 = CreateEndpoint(address: null);
|
|
||||||
var endpointFinder = CreateDefaultEndpointFinder(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var result = endpointFinder.FindEndpoints(new Address("Admin"));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Collection(
|
|
||||||
result,
|
|
||||||
(ep) => Assert.Same(endpoint1, ep),
|
|
||||||
(ep) => Assert.Same(endpoint2, ep));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void FindEndpoints_ReturnsAllEndpoints_WhenLookupAddress_IsNull()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = CreateEndpoint(new Address("home"));
|
|
||||||
var endpoint2 = CreateEndpoint(new Address("admin"));
|
|
||||||
var endpointFinder = CreateDefaultEndpointFinder(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var result = endpointFinder.FindEndpoints(lookupAddress: null);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Collection(
|
|
||||||
result,
|
|
||||||
(ep) => Assert.Same(endpoint1, ep),
|
|
||||||
(ep) => Assert.Same(endpoint2, ep));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void FindEndpoints_ReturnsAllEndpoints_WhenNoEndpointsHaveAddress_AndLookupAddress_IsNull()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = CreateEndpoint(address: null);
|
|
||||||
var endpoint2 = CreateEndpoint(address: null);
|
|
||||||
var endpointFinder = CreateDefaultEndpointFinder(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var result = endpointFinder.FindEndpoints(lookupAddress: null);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Collection(
|
|
||||||
result,
|
|
||||||
(ep) => Assert.Same(endpoint1, ep),
|
|
||||||
(ep) => Assert.Same(endpoint2, ep));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void FindEndpoints_ReturnsAllEndpoints_WhenNoInformationGiven_OnLookupAddress()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = CreateEndpoint(new Address("home"));
|
|
||||||
var endpoint2 = CreateEndpoint(new Address("admin"));
|
|
||||||
var endpointFinder = CreateDefaultEndpointFinder(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var result = endpointFinder.FindEndpoints(new Address(name: null));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Collection(
|
|
||||||
result,
|
|
||||||
(ep) => Assert.Same(endpoint1, ep),
|
|
||||||
(ep) => Assert.Same(endpoint2, ep));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void FindEndpoints_ReturnsEmpty_WhenNoEndpointFound_WithLookupAddress_Name()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = CreateEndpoint(new Address("home"));
|
|
||||||
var endpoint2 = CreateEndpoint(new Address("admin"));
|
|
||||||
var endpointFinder = CreateDefaultEndpointFinder(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var result = endpointFinder.FindEndpoints(new Address("DoesNotExist"));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Empty(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Endpoint CreateEndpoint(Address address)
|
|
||||||
{
|
|
||||||
return new TestEndpoint(
|
|
||||||
EndpointMetadataCollection.Empty,
|
|
||||||
displayName: null,
|
|
||||||
address: address);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DefaultEndpointFinder CreateDefaultEndpointFinder(params Endpoint[] endpoints)
|
|
||||||
{
|
|
||||||
return new DefaultEndpointFinder(
|
|
||||||
new CompositeEndpointDataSource(new[] { new DefaultEndpointDataSource(endpoints) }),
|
|
||||||
NullLogger<DefaultEndpointFinder>.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class HomeController
|
|
||||||
{
|
|
||||||
public void Index() { }
|
|
||||||
public void Contact() { }
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AdminController
|
|
||||||
{
|
|
||||||
public void Index() { }
|
|
||||||
public void Contact() { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,10 +4,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Routing.EndpointFinders;
|
||||||
using Microsoft.AspNetCore.Routing.Internal;
|
using Microsoft.AspNetCore.Routing.Internal;
|
||||||
using Microsoft.AspNetCore.Routing.Matchers;
|
using Microsoft.AspNetCore.Routing.Matchers;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
|
||||||
using Microsoft.Extensions.ObjectPool;
|
using Microsoft.Extensions.ObjectPool;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -21,11 +21,11 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}");
|
var endpoint = CreateEndpoint("{controller}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(new { controller = "Home" });
|
var context = CreateRouteValuesContext(new { controller = "Home" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home", link);
|
Assert.Equal("/Home", link);
|
||||||
|
|
@ -37,11 +37,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedMessage = "Could not find a matching endpoint to generate a link.";
|
var expectedMessage = "Could not find a matching endpoint to generate a link.";
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}");
|
var endpoint = CreateEndpoint("{controller}/{action}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(new { controller = "Home" });
|
var context = CreateRouteValuesContext(new { controller = "Home" });
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
var exception = Assert.Throws<InvalidOperationException>(() => linkGenerator.GetLink(context));
|
var exception = Assert.Throws<InvalidOperationException>(
|
||||||
|
() => linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues));
|
||||||
Assert.Equal(expectedMessage, exception.Message);
|
Assert.Equal(expectedMessage, exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,11 +51,15 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}");
|
var endpoint = CreateEndpoint("{controller}/{action}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(new { controller = "Home" });
|
var context = CreateRouteValuesContext(new { controller = "Home" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var canGenerateLink = linkGenerator.TryGetLink(context, out var link);
|
var canGenerateLink = linkGenerator.TryGetLink(
|
||||||
|
new[] { endpoint },
|
||||||
|
context.ExplicitValues,
|
||||||
|
context.AmbientValues,
|
||||||
|
out var link);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(canGenerateLink);
|
Assert.False(canGenerateLink);
|
||||||
|
|
@ -68,11 +73,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoint1 = CreateEndpoint("{controller}/{action}/{id?}");
|
var endpoint1 = CreateEndpoint("{controller}/{action}/{id?}");
|
||||||
var endpoint2 = CreateEndpoint("{controller}/{action}");
|
var endpoint2 = CreateEndpoint("{controller}/{action}");
|
||||||
var endpoint3 = CreateEndpoint("{controller}");
|
var endpoint3 = CreateEndpoint("{controller}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint1, endpoint2, endpoint3));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(new { controller = "Home", action = "Index", id = "10" });
|
var context = CreateRouteValuesContext(new { controller = "Home", action = "Index", id = "10" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(
|
||||||
|
new[] { endpoint1, endpoint2, endpoint3 },
|
||||||
|
context.ExplicitValues,
|
||||||
|
context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index/10", link);
|
Assert.Equal("/Home/Index/10", link);
|
||||||
|
|
@ -85,11 +93,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoint1 = CreateEndpoint("{controller}/{action}/{id}");
|
var endpoint1 = CreateEndpoint("{controller}/{action}/{id}");
|
||||||
var endpoint2 = CreateEndpoint("{controller}/{action}");
|
var endpoint2 = CreateEndpoint("{controller}/{action}");
|
||||||
var endpoint3 = CreateEndpoint("{controller}");
|
var endpoint3 = CreateEndpoint("{controller}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint1, endpoint2, endpoint3));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(new { controller = "Home", action = "Index" });
|
var context = CreateRouteValuesContext(new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(
|
||||||
|
new[] { endpoint1, endpoint2, endpoint3 },
|
||||||
|
context.ExplicitValues,
|
||||||
|
context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index", link);
|
Assert.Equal("/Home/Index", link);
|
||||||
|
|
@ -100,13 +111,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}");
|
var endpoint = CreateEndpoint("{controller}/{action}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
suppliedValues: new { name = "name with %special #characters" },
|
suppliedValues: new { name = "name with %special #characters" },
|
||||||
ambientValues: new { controller = "Home", action = "Index" });
|
ambientValues: new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index?name=name%20with%20%25special%20%23characters", link);
|
Assert.Equal("/Home/Index?name=name%20with%20%25special%20%23characters", link);
|
||||||
|
|
@ -117,13 +128,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}");
|
var endpoint = CreateEndpoint("{controller}/{action}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
new { color = new List<string> { "red", "green", "blue" } },
|
new { color = new List<string> { "red", "green", "blue" } },
|
||||||
new { controller = "Home", action = "Index" });
|
new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index?color=red&color=green&color=blue", link);
|
Assert.Equal("/Home/Index?color=red&color=green&color=blue", link);
|
||||||
|
|
@ -134,13 +145,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}");
|
var endpoint = CreateEndpoint("{controller}/{action}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
new { items = new List<int> { 10, 20, 30 } },
|
new { items = new List<int> { 10, 20, 30 } },
|
||||||
new { controller = "Home", action = "Index" });
|
new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index?items=10&items=20&items=30", link);
|
Assert.Equal("/Home/Index?items=10&items=20&items=30", link);
|
||||||
|
|
@ -151,13 +162,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}");
|
var endpoint = CreateEndpoint("{controller}/{action}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
new { color = new List<string> { } },
|
new { color = new List<string> { } },
|
||||||
new { controller = "Home", action = "Index" });
|
new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index", link);
|
Assert.Equal("/Home/Index", link);
|
||||||
|
|
@ -168,13 +179,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}");
|
var endpoint = CreateEndpoint("{controller}/{action}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
new { page = 1, color = new List<string> { "red", "green", "blue" }, message = "textfortest" },
|
new { page = 1, color = new List<string> { "red", "green", "blue" }, message = "textfortest" },
|
||||||
new { controller = "Home", action = "Index" });
|
new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index?page=1&color=red&color=green&color=blue&message=textfortest", link);
|
Assert.Equal("/Home/Index?page=1&color=red&color=green&color=blue&message=textfortest", link);
|
||||||
|
|
@ -185,13 +196,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}");
|
var endpoint = CreateEndpoint("{controller}/{action}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
suppliedValues: new { action = "Index" },
|
suppliedValues: new { action = "Index" },
|
||||||
ambientValues: new { controller = "Home" });
|
ambientValues: new { controller = "Home" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index", link);
|
Assert.Equal("/Home/Index", link);
|
||||||
|
|
@ -201,9 +212,9 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void RouteGenerationRejectsConstraints()
|
//public void RouteGenerationRejectsConstraints()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var context = CreateLinkGeneratorContext(new { p1 = "abcd" });
|
// var context = CreateRouteValuesContext(new { p1 = "abcd" });
|
||||||
|
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// "{p1}/{p2}",
|
// "{p1}/{p2}",
|
||||||
// new { p2 = "catchall" },
|
// new { p2 = "catchall" },
|
||||||
// true,
|
// true,
|
||||||
|
|
@ -220,16 +231,16 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void RouteGenerationAcceptsConstraints()
|
//public void RouteGenerationAcceptsConstraints()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var context = CreateLinkGeneratorContext(new { p1 = "hello", p2 = "1234" });
|
// var context = CreateRouteValuesContext(new { p1 = "hello", p2 = "1234" });
|
||||||
|
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// "{p1}/{p2}",
|
// "{p1}/{p2}",
|
||||||
// new { p2 = "catchall" },
|
// new { p2 = "catchall" },
|
||||||
// true,
|
// true,
|
||||||
// new RouteValueDictionary(new { p2 = "\\d{4}" }));
|
// new RouteValueDictionary(new { p2 = "\\d{4}" }));
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.NotNull(pathData);
|
// Assert.NotNull(pathData);
|
||||||
|
|
@ -242,9 +253,9 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void RouteWithCatchAllRejectsConstraints()
|
//public void RouteWithCatchAllRejectsConstraints()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var context = CreateLinkGeneratorContext(new { p1 = "abcd" });
|
// var context = CreateRouteValuesContext(new { p1 = "abcd" });
|
||||||
|
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// "{p1}/{*p2}",
|
// "{p1}/{*p2}",
|
||||||
// new { p2 = "catchall" },
|
// new { p2 = "catchall" },
|
||||||
// true,
|
// true,
|
||||||
|
|
@ -261,16 +272,16 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void RouteWithCatchAllAcceptsConstraints()
|
//public void RouteWithCatchAllAcceptsConstraints()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var context = CreateLinkGeneratorContext(new { p1 = "hello", p2 = "1234" });
|
// var context = CreateRouteValuesContext(new { p1 = "hello", p2 = "1234" });
|
||||||
|
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// "{p1}/{*p2}",
|
// "{p1}/{*p2}",
|
||||||
// new { p2 = "catchall" },
|
// new { p2 = "catchall" },
|
||||||
// true,
|
// true,
|
||||||
// new RouteValueDictionary(new { p2 = "\\d{4}" }));
|
// new RouteValueDictionary(new { p2 = "\\d{4}" }));
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.NotNull(pathData);
|
// Assert.NotNull(pathData);
|
||||||
|
|
@ -283,7 +294,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLinkWithNonParameterConstraintReturnsUrlWithoutQueryString()
|
//public void GetLinkWithNonParameterConstraintReturnsUrlWithoutQueryString()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var context = CreateLinkGeneratorContext(new { p1 = "hello", p2 = "1234" });
|
// var context = CreateRouteValuesContext(new { p1 = "hello", p2 = "1234" });
|
||||||
|
|
||||||
// var target = new Mock<IRouteConstraint>();
|
// var target = new Mock<IRouteConstraint>();
|
||||||
// target
|
// target
|
||||||
|
|
@ -297,14 +308,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// .Returns(true)
|
// .Returns(true)
|
||||||
// .Verifiable();
|
// .Verifiable();
|
||||||
|
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// "{p1}/{p2}",
|
// "{p1}/{p2}",
|
||||||
// new { p2 = "catchall" },
|
// new { p2 = "catchall" },
|
||||||
// true,
|
// true,
|
||||||
// new RouteValueDictionary(new { p2 = target.Object }));
|
// new RouteValueDictionary(new { p2 = target.Object }));
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.NotNull(pathData);
|
// Assert.NotNull(pathData);
|
||||||
|
|
@ -322,13 +333,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var constraint = new CapturingConstraint();
|
// var constraint = new CapturingConstraint();
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// template: "slug/{controller}/{action}",
|
// template: "slug/{controller}/{action}",
|
||||||
// defaultValues: null,
|
// defaultValues: null,
|
||||||
// handleRequest: true,
|
// handleRequest: true,
|
||||||
// constraints: new { c = constraint });
|
// constraints: new { c = constraint });
|
||||||
|
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Store" },
|
// values: new { action = "Store" },
|
||||||
// ambientValues: new { Controller = "Home", action = "Blog", extra = "42" });
|
// ambientValues: new { Controller = "Home", action = "Blog", extra = "42" });
|
||||||
|
|
||||||
|
|
@ -336,7 +347,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// new { controller = "Home", action = "Store", extra = "42" });
|
// new { controller = "Home", action = "Store", extra = "42" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/slug/Home/Store", link);
|
// Assert.Equal("/slug/Home/Store", link);
|
||||||
|
|
@ -353,13 +364,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var constraint = new CapturingConstraint();
|
// var constraint = new CapturingConstraint();
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// template: "slug/{controller}/{action}",
|
// template: "slug/{controller}/{action}",
|
||||||
// defaultValues: new { otherthing = "17" },
|
// defaultValues: new { otherthing = "17" },
|
||||||
// handleRequest: true,
|
// handleRequest: true,
|
||||||
// constraints: new { c = constraint });
|
// constraints: new { c = constraint });
|
||||||
|
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Store" },
|
// values: new { action = "Store" },
|
||||||
// ambientValues: new { Controller = "Home", action = "Blog" });
|
// ambientValues: new { Controller = "Home", action = "Blog" });
|
||||||
|
|
||||||
|
|
@ -367,7 +378,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// new { controller = "Home", action = "Store" });
|
// new { controller = "Home", action = "Store" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/slug/Home/Store", link);
|
// Assert.Equal("/slug/Home/Store", link);
|
||||||
|
|
@ -383,13 +394,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var constraint = new CapturingConstraint();
|
// var constraint = new CapturingConstraint();
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// template: "slug/{controller}/{action}",
|
// template: "slug/{controller}/{action}",
|
||||||
// defaultValues: new { action = "Index" },
|
// defaultValues: new { action = "Index" },
|
||||||
// handleRequest: true,
|
// handleRequest: true,
|
||||||
// constraints: new { c = constraint });
|
// constraints: new { c = constraint });
|
||||||
|
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { controller = "Shopping" },
|
// values: new { controller = "Shopping" },
|
||||||
// ambientValues: new { Controller = "Home", action = "Blog" });
|
// ambientValues: new { Controller = "Home", action = "Blog" });
|
||||||
|
|
||||||
|
|
@ -397,7 +408,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// new { controller = "Shopping", action = "Index" });
|
// new { controller = "Shopping", action = "Index" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/slug/Shopping", link);
|
// Assert.Equal("/slug/Shopping", link);
|
||||||
|
|
@ -414,13 +425,13 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var constraint = new CapturingConstraint();
|
// var constraint = new CapturingConstraint();
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// template: "slug/{controller}/{action}",
|
// template: "slug/{controller}/{action}",
|
||||||
// defaultValues: new { otherthing = "17", thirdthing = "13" },
|
// defaultValues: new { otherthing = "17", thirdthing = "13" },
|
||||||
// handleRequest: true,
|
// handleRequest: true,
|
||||||
// constraints: new { c = constraint });
|
// constraints: new { c = constraint });
|
||||||
|
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Store", thirdthing = "13" },
|
// values: new { action = "Store", thirdthing = "13" },
|
||||||
// ambientValues: new { Controller = "Home", action = "Blog", otherthing = "17" });
|
// ambientValues: new { Controller = "Home", action = "Blog", otherthing = "17" });
|
||||||
|
|
||||||
|
|
@ -428,7 +439,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// new { controller = "Home", action = "Store", otherthing = "17", thirdthing = "13" });
|
// new { controller = "Home", action = "Store", otherthing = "17", thirdthing = "13" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/slug/Home/Store", link);
|
// Assert.Equal("/slug/Home/Store", link);
|
||||||
|
|
@ -442,12 +453,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_InlineConstraints_Success()
|
//public void GetLink_InlineConstraints_Success()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint("{controller}/{action}/{id:int}");
|
// var endpoint = CreateEndpoints("{controller}/{action}/{id:int}");
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home", id = 4 });
|
// values: new { action = "Index", controller = "Home", id = 4 });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/Home/Index/4", link);
|
// Assert.Equal("/Home/Index/4", link);
|
||||||
|
|
@ -459,8 +470,8 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_InlineConstraints_NonMatchingvalue()
|
//public void GetLink_InlineConstraints_NonMatchingvalue()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint("{controller}/{action}/{id:int}");
|
// var endpoint = CreateEndpoints("{controller}/{action}/{id:int}");
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home", id = "asf" });
|
// values: new { action = "Index", controller = "Home", id = "asf" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
|
|
@ -474,12 +485,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_InlineConstraints_OptionalParameter_ValuePresent()
|
//public void GetLink_InlineConstraints_OptionalParameter_ValuePresent()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint("{controller}/{action}/{id:int?}");
|
// var endpoint = CreateEndpoints("{controller}/{action}/{id:int?}");
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home", id = 98 });
|
// values: new { action = "Index", controller = "Home", id = 98 });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/Home/Index/98", link);
|
// Assert.Equal("/Home/Index/98", link);
|
||||||
|
|
@ -491,12 +502,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_InlineConstraints_OptionalParameter_ValueNotPresent()
|
//public void GetLink_InlineConstraints_OptionalParameter_ValueNotPresent()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint("{controller}/{action}/{id:int?}");
|
// var endpoint = CreateEndpoints("{controller}/{action}/{id:int?}");
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home" });
|
// values: new { action = "Index", controller = "Home" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/Home/Index", link);
|
// Assert.Equal("/Home/Index", link);
|
||||||
|
|
@ -508,8 +519,8 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_InlineConstraints_OptionalParameter_ValuePresent_ConstraintFails()
|
//public void GetLink_InlineConstraints_OptionalParameter_ValuePresent_ConstraintFails()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint("{controller}/{action}/{id:int?}");
|
// var endpoint = CreateEndpoints("{controller}/{action}/{id:int?}");
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home", id = "sdfd" });
|
// values: new { action = "Index", controller = "Home", id = "sdfd" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
|
|
@ -523,12 +534,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_InlineConstraints_CompositeInlineConstraint()
|
//public void GetLink_InlineConstraints_CompositeInlineConstraint()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint("{controller}/{action}/{id:int:range(1,20)}");
|
// var endpoint = CreateEndpoints("{controller}/{action}/{id:int:range(1,20)}");
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home", id = 14 });
|
// values: new { action = "Index", controller = "Home", id = 14 });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/Home/Index/14", link);
|
// Assert.Equal("/Home/Index/14", link);
|
||||||
|
|
@ -541,17 +552,17 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var constraint = new MaxLengthRouteConstraint(20);
|
// var constraint = new MaxLengthRouteConstraint(20);
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// template: "{controller}/{action}/{name:alpha}",
|
// template: "{controller}/{action}/{name:alpha}",
|
||||||
// defaultValues: null,
|
// defaultValues: null,
|
||||||
// handleRequest: true,
|
// handleRequest: true,
|
||||||
// constraints: new { name = constraint });
|
// constraints: new { name = constraint });
|
||||||
|
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home", name = "products" });
|
// values: new { action = "Index", controller = "Home", name = "products" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/Home/Index/products", link);
|
// Assert.Equal("/Home/Index/products", link);
|
||||||
|
|
@ -564,12 +575,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}/{name?}");
|
var endpoint = CreateEndpoint("{controller}/{action}/{name?}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
suppliedValues: new { action = "Index", controller = "Home", name = "products" });
|
suppliedValues: new { action = "Index", controller = "Home", name = "products" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index/products", link);
|
Assert.Equal("/Home/Index/products", link);
|
||||||
|
|
@ -580,12 +591,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}/{name?}");
|
var endpoint = CreateEndpoint("{controller}/{action}/{name?}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
suppliedValues: new { action = "Index", controller = "Home" });
|
suppliedValues: new { action = "Index", controller = "Home" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index", link);
|
Assert.Equal("/Home/Index", link);
|
||||||
|
|
@ -598,12 +609,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoint = CreateEndpoint(
|
var endpoint = CreateEndpoint(
|
||||||
template: "{controller}/{action}/{name?}",
|
template: "{controller}/{action}/{name?}",
|
||||||
defaultValues: new { name = "default-products" });
|
defaultValues: new { name = "default-products" });
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
suppliedValues: new { action = "Index", controller = "Home", name = "products" });
|
suppliedValues: new { action = "Index", controller = "Home", name = "products" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index/products", link);
|
Assert.Equal("/Home/Index/products", link);
|
||||||
|
|
@ -616,12 +627,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
var endpoint = CreateEndpoint(
|
var endpoint = CreateEndpoint(
|
||||||
template: "{controller}/{action}/{name?}",
|
template: "{controller}/{action}/{name?}",
|
||||||
defaultValues: new { name = "products" });
|
defaultValues: new { name = "products" });
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
suppliedValues: new { action = "Index", controller = "Home" });
|
suppliedValues: new { action = "Index", controller = "Home" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index", link);
|
Assert.Equal("/Home/Index", link);
|
||||||
|
|
@ -632,12 +643,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}/{name}");
|
var endpoint = CreateEndpoint("{controller}/{action}/{name}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
suppliedValues: new { action = "Index", controller = "Home", name = "products", format = "json" });
|
suppliedValues: new { action = "Index", controller = "Home", name = "products", format = "json" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index/products?format=json", link);
|
Assert.Equal("/Home/Index/products?format=json", link);
|
||||||
|
|
@ -647,17 +658,17 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_OptionalParameter_FollowedByDotAfterSlash_ParameterPresent()
|
//public void GetLink_OptionalParameter_FollowedByDotAfterSlash_ParameterPresent()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// template: "{controller}/{action}/.{name?}",
|
// template: "{controller}/{action}/.{name?}",
|
||||||
// defaultValues: null,
|
// defaultValues: null,
|
||||||
// handleRequest: true,
|
// handleRequest: true,
|
||||||
// constraints: null);
|
// constraints: null);
|
||||||
|
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home", name = "products" });
|
// values: new { action = "Index", controller = "Home", name = "products" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/Home/Index/.products", link);
|
// Assert.Equal("/Home/Index/.products", link);
|
||||||
|
|
@ -669,17 +680,17 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_OptionalParameter_FollowedByDotAfterSlash_ParameterNotPresent()
|
//public void GetLink_OptionalParameter_FollowedByDotAfterSlash_ParameterNotPresent()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// template: "{controller}/{action}/.{name?}",
|
// template: "{controller}/{action}/.{name?}",
|
||||||
// defaultValues: null,
|
// defaultValues: null,
|
||||||
// handleRequest: true,
|
// handleRequest: true,
|
||||||
// constraints: null);
|
// constraints: null);
|
||||||
|
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { action = "Index", controller = "Home" });
|
// values: new { action = "Index", controller = "Home" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/Home/Index/", link);
|
// Assert.Equal("/Home/Index/", link);
|
||||||
|
|
@ -692,12 +703,12 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var endpoint = CreateEndpoint("{controller}/{action}/{name?}");
|
var endpoint = CreateEndpoint("{controller}/{action}/{name?}");
|
||||||
var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
var linkGenerator = CreateLinkGenerator();
|
||||||
var context = CreateLinkGeneratorContext(
|
var context = CreateRouteValuesContext(
|
||||||
suppliedValues: new { action = "Index", controller = "Home" });
|
suppliedValues: new { action = "Index", controller = "Home" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var link = linkGenerator.GetLink(context);
|
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("/Home/Index", link);
|
Assert.Equal("/Home/Index", link);
|
||||||
|
|
@ -707,14 +718,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_TwoOptionalParameters_OneValueFromAmbientValues()
|
//public void GetLink_TwoOptionalParameters_OneValueFromAmbientValues()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint("a/{b=15}/{c?}/{d?}");
|
// var endpoint = CreateEndpoints("a/{b=15}/{c?}/{d?}");
|
||||||
// var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
// var linkGenerator = CreateLinkGenerator();
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// suppliedValues: new { },
|
// suppliedValues: new { },
|
||||||
// ambientValues: new { c = "17" });
|
// ambientValues: new { c = "17" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/a/15/17", link);
|
// Assert.Equal("/a/15/17", link);
|
||||||
|
|
@ -724,14 +735,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_OptionalParameterAfterDefault_OneValueFromAmbientValues()
|
//public void GetLink_OptionalParameterAfterDefault_OneValueFromAmbientValues()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint("a/{b=15}/{c?}");
|
// var endpoint = CreateEndpoints("a/{b=15}/{c?}");
|
||||||
// var linkGenerator = CreateLinkGenerator(CreateEndpointFinder(endpoint));
|
// var linkGenerator = CreateLinkGenerator();
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// suppliedValues: new { },
|
// suppliedValues: new { },
|
||||||
// ambientValues: new { c = "17" });
|
// ambientValues: new { c = "17" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal("/a/15/17", link);
|
// Assert.Equal("/a/15/17", link);
|
||||||
|
|
@ -741,18 +752,18 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//public void GetLink_TwoOptionalParametersAfterDefault_LastValueFromAmbientValues()
|
//public void GetLink_TwoOptionalParametersAfterDefault_LastValueFromAmbientValues()
|
||||||
//{
|
//{
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var endpoint = CreateEndpoint(
|
// var endpoint = CreateEndpoints(
|
||||||
// template: "a/{b=15}/{c?}/{d?}",
|
// template: "a/{b=15}/{c?}/{d?}",
|
||||||
// defaultValues: null,
|
// defaultValues: null,
|
||||||
// handleRequest: true,
|
// handleRequest: true,
|
||||||
// constraints: null);
|
// constraints: null);
|
||||||
|
|
||||||
// var context = CreateLinkGeneratorContext(
|
// var context = CreateRouteValuesContext(
|
||||||
// values: new { },
|
// values: new { },
|
||||||
// ambientValues: new { d = "17" });
|
// ambientValues: new { d = "17" });
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var link = linkGenerator.GetLink(context);
|
// var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues);
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.NotNull(pathData);
|
// Assert.NotNull(pathData);
|
||||||
|
|
@ -761,39 +772,32 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
//
|
//
|
||||||
//}
|
//}
|
||||||
|
|
||||||
private LinkGeneratorContext CreateLinkGeneratorContext(object suppliedValues, object ambientValues = null)
|
private RouteValuesBasedEndpointFinderContext CreateRouteValuesContext(object suppliedValues, object ambientValues = null)
|
||||||
{
|
{
|
||||||
var context = new LinkGeneratorContext();
|
var context = new RouteValuesBasedEndpointFinderContext();
|
||||||
context.SuppliedValues = new RouteValueDictionary(suppliedValues);
|
context.ExplicitValues = new RouteValueDictionary(suppliedValues);
|
||||||
context.AmbientValues = new RouteValueDictionary(ambientValues);
|
context.AmbientValues = new RouteValueDictionary(ambientValues);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MatcherEndpoint CreateEndpoint(string template, object defaultValues = null)
|
private MatcherEndpoint CreateEndpoint(string template, object defaultValues = null)
|
||||||
{
|
{
|
||||||
|
var defaults = defaultValues == null ? new RouteValueDictionary() : new RouteValueDictionary(defaultValues);
|
||||||
return new MatcherEndpoint(
|
return new MatcherEndpoint(
|
||||||
next => (httpContext) => Task.CompletedTask,
|
next => (httpContext) => Task.CompletedTask,
|
||||||
template,
|
template,
|
||||||
defaultValues,
|
defaults,
|
||||||
|
new RouteValueDictionary(),
|
||||||
0,
|
0,
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
null,
|
null);
|
||||||
new Address("foo"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ILinkGenerator CreateLinkGenerator(IEndpointFinder endpointFinder)
|
private ILinkGenerator CreateLinkGenerator()
|
||||||
{
|
{
|
||||||
return new DefaultLinkGenerator(
|
return new DefaultLinkGenerator(
|
||||||
endpointFinder,
|
|
||||||
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
|
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
|
||||||
Mock.Of<ILogger<DefaultLinkGenerator>>());
|
Mock.Of<ILogger<DefaultLinkGenerator>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefaultEndpointFinder CreateEndpointFinder(params Endpoint[] endpoints)
|
|
||||||
{
|
|
||||||
return new DefaultEndpointFinder(
|
|
||||||
new CompositeEndpointDataSource(new[] { new DefaultEndpointDataSource(endpoints) }),
|
|
||||||
NullLogger<DefaultEndpointFinder>.Instance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,11 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
// Arrange
|
// Arrange
|
||||||
var defaultEndpoint = new TestEndpoint(
|
var defaultEndpoint = new TestEndpoint(
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
"No constraint endpoint",
|
"No constraint endpoint");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var postEndpoint = new TestEndpoint(
|
var postEndpoint = new TestEndpoint(
|
||||||
new EndpointMetadataCollection(new object[] { new HttpMethodEndpointConstraint(new[] { "POST" }) }),
|
new EndpointMetadataCollection(new object[] { new HttpMethodEndpointConstraint(new[] { "POST" }) }),
|
||||||
"POST constraint endpoint",
|
"POST constraint endpoint");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var endpoints = new Endpoint[]
|
var endpoints = new Endpoint[]
|
||||||
{
|
{
|
||||||
|
|
@ -62,13 +60,11 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
|
|
||||||
var defaultEndpoint1 = new TestEndpoint(
|
var defaultEndpoint1 = new TestEndpoint(
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
"Ambiguous1",
|
"Ambiguous1");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var defaultEndpoint2 = new TestEndpoint(
|
var defaultEndpoint2 = new TestEndpoint(
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
"Ambiguous2",
|
"Ambiguous2");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var endpoints = new Endpoint[]
|
var endpoints = new Endpoint[]
|
||||||
{
|
{
|
||||||
|
|
@ -100,8 +96,8 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
|
|
||||||
var actions = new Endpoint[]
|
var actions = new Endpoint[]
|
||||||
{
|
{
|
||||||
new TestEndpoint(EndpointMetadataCollection.Empty, "A1", address: null),
|
new TestEndpoint(EndpointMetadataCollection.Empty, "A1"),
|
||||||
new TestEndpoint(EndpointMetadataCollection.Empty, "A2", address: null),
|
new TestEndpoint(EndpointMetadataCollection.Empty, "A2"),
|
||||||
};
|
};
|
||||||
var selector = CreateSelector(actions, loggerFactory);
|
var selector = CreateSelector(actions, loggerFactory);
|
||||||
|
|
||||||
|
|
@ -124,13 +120,11 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
// Arrange
|
// Arrange
|
||||||
var actionWithConstraints = new TestEndpoint(
|
var actionWithConstraints = new TestEndpoint(
|
||||||
new EndpointMetadataCollection(new[] { new HttpMethodEndpointConstraint(new string[] { "POST" }) }),
|
new EndpointMetadataCollection(new[] { new HttpMethodEndpointConstraint(new string[] { "POST" }) }),
|
||||||
"Has constraint",
|
"Has constraint");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actionWithoutConstraints = new TestEndpoint(
|
var actionWithoutConstraints = new TestEndpoint(
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
"No constraint",
|
"No constraint");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { actionWithConstraints, actionWithoutConstraints };
|
var actions = new Endpoint[] { actionWithConstraints, actionWithoutConstraints };
|
||||||
|
|
||||||
|
|
@ -150,13 +144,11 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
// Arrange
|
// Arrange
|
||||||
var action1 = new TestEndpoint(
|
var action1 = new TestEndpoint(
|
||||||
new EndpointMetadataCollection(new[] { new BooleanConstraint() { Pass = false, } }),
|
new EndpointMetadataCollection(new[] { new BooleanConstraint() { Pass = false, } }),
|
||||||
"action1",
|
"action1");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var action2 = new TestEndpoint(
|
var action2 = new TestEndpoint(
|
||||||
new EndpointMetadataCollection(new[] { new BooleanConstraint() { Pass = false, } }),
|
new EndpointMetadataCollection(new[] { new BooleanConstraint() { Pass = false, } }),
|
||||||
"action2",
|
"action2");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { action1, action2 };
|
var actions = new Endpoint[] { action1, action2 };
|
||||||
|
|
||||||
|
|
@ -179,16 +171,14 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
new BooleanConstraint() { Pass = false, Order = 0 },
|
new BooleanConstraint() { Pass = false, Order = 0 },
|
||||||
new BooleanConstraint() { Pass = true, Order = 1 },
|
new BooleanConstraint() { Pass = true, Order = 1 },
|
||||||
}),
|
}),
|
||||||
"action1",
|
"action1");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var action2 = new TestEndpoint(new EndpointMetadataCollection(new[]
|
var action2 = new TestEndpoint(new EndpointMetadataCollection(new[]
|
||||||
{
|
{
|
||||||
new BooleanConstraint() { Pass = true, Order = 0 },
|
new BooleanConstraint() { Pass = true, Order = 0 },
|
||||||
new BooleanConstraint() { Pass = false, Order = 1 },
|
new BooleanConstraint() { Pass = false, Order = 1 },
|
||||||
}),
|
}),
|
||||||
"action2",
|
"action2");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { action1, action2 };
|
var actions = new Endpoint[] { action1, action2 };
|
||||||
|
|
||||||
|
|
@ -213,13 +203,11 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
Constraint = new BooleanConstraint() { Pass = true },
|
Constraint = new BooleanConstraint() { Pass = true },
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
"actionWithConstraints",
|
"actionWithConstraints");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actionWithoutConstraints = new TestEndpoint(
|
var actionWithoutConstraints = new TestEndpoint(
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
"actionWithoutConstraints",
|
"actionWithoutConstraints");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { actionWithConstraints, actionWithoutConstraints };
|
var actions = new Endpoint[] { actionWithConstraints, actionWithoutConstraints };
|
||||||
|
|
||||||
|
|
@ -237,7 +225,7 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
public void SelectBestCandidate_MultipleCallsNoConstraint_ReturnsEndpoint()
|
public void SelectBestCandidate_MultipleCallsNoConstraint_ReturnsEndpoint()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var noConstraint = new TestEndpoint(EndpointMetadataCollection.Empty, "noConstraint", address: null);
|
var noConstraint = new TestEndpoint(EndpointMetadataCollection.Empty, "noConstraint");
|
||||||
|
|
||||||
var actions = new Endpoint[] { noConstraint };
|
var actions = new Endpoint[] { noConstraint };
|
||||||
|
|
||||||
|
|
@ -261,8 +249,7 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
{
|
{
|
||||||
new object(),
|
new object(),
|
||||||
}),
|
}),
|
||||||
"noConstraint",
|
"noConstraint");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { noConstraint };
|
var actions = new Endpoint[] { noConstraint };
|
||||||
|
|
||||||
|
|
@ -286,8 +273,7 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
{
|
{
|
||||||
new ConstraintFactory(),
|
new ConstraintFactory(),
|
||||||
}),
|
}),
|
||||||
"nullConstraint",
|
"nullConstraint");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { nullConstraint };
|
var actions = new Endpoint[] { nullConstraint };
|
||||||
|
|
||||||
|
|
@ -312,13 +298,11 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
{
|
{
|
||||||
new BooleanConstraintMarker() { Pass = true },
|
new BooleanConstraintMarker() { Pass = true },
|
||||||
}),
|
}),
|
||||||
"actionWithConstraints",
|
"actionWithConstraints");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actionWithoutConstraints = new TestEndpoint(
|
var actionWithoutConstraints = new TestEndpoint(
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
"actionWithoutConstraints",
|
"actionWithoutConstraints");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { actionWithConstraints, actionWithoutConstraints, };
|
var actions = new Endpoint[] { actionWithConstraints, actionWithoutConstraints, };
|
||||||
|
|
||||||
|
|
@ -341,15 +325,13 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
{
|
{
|
||||||
new BooleanConstraint() { Pass = true, Order = 0, },
|
new BooleanConstraint() { Pass = true, Order = 0, },
|
||||||
}),
|
}),
|
||||||
"best",
|
"best");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var worst = new TestEndpoint(new EndpointMetadataCollection(new[]
|
var worst = new TestEndpoint(new EndpointMetadataCollection(new[]
|
||||||
{
|
{
|
||||||
new BooleanConstraint() { Pass = true, Order = 1, },
|
new BooleanConstraint() { Pass = true, Order = 1, },
|
||||||
}),
|
}),
|
||||||
"worst",
|
"worst");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { best, worst };
|
var actions = new Endpoint[] { best, worst };
|
||||||
|
|
||||||
|
|
@ -374,8 +356,7 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
new BooleanConstraint() { Pass = true, Order = 1, },
|
new BooleanConstraint() { Pass = true, Order = 1, },
|
||||||
new BooleanConstraint() { Pass = true, Order = 2, },
|
new BooleanConstraint() { Pass = true, Order = 2, },
|
||||||
}),
|
}),
|
||||||
"best",
|
"best");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var worst = new TestEndpoint(new EndpointMetadataCollection(new[]
|
var worst = new TestEndpoint(new EndpointMetadataCollection(new[]
|
||||||
{
|
{
|
||||||
|
|
@ -383,8 +364,7 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
new BooleanConstraint() { Pass = true, Order = 1, },
|
new BooleanConstraint() { Pass = true, Order = 1, },
|
||||||
new BooleanConstraint() { Pass = true, Order = 3, },
|
new BooleanConstraint() { Pass = true, Order = 3, },
|
||||||
}),
|
}),
|
||||||
"worst",
|
"worst");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var actions = new Endpoint[] { best, worst };
|
var actions = new Endpoint[] { best, worst };
|
||||||
|
|
||||||
|
|
@ -408,8 +388,7 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
new BooleanConstraint() { Pass = true, Order = 1, },
|
new BooleanConstraint() { Pass = true, Order = 1, },
|
||||||
new BooleanConstraint() { Pass = false, Order = 2, },
|
new BooleanConstraint() { Pass = false, Order = 2, },
|
||||||
}),
|
}),
|
||||||
"nomatch1",
|
"nomatch1");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var nomatch2 = new TestEndpoint(new EndpointMetadataCollection(new[]
|
var nomatch2 = new TestEndpoint(new EndpointMetadataCollection(new[]
|
||||||
{
|
{
|
||||||
|
|
@ -417,10 +396,9 @@ namespace Microsoft.AspNetCore.Routing.EndpointConstraints
|
||||||
new BooleanConstraint() { Pass = true, Order = 1, },
|
new BooleanConstraint() { Pass = true, Order = 1, },
|
||||||
new BooleanConstraint() { Pass = false, Order = 3, },
|
new BooleanConstraint() { Pass = false, Order = 3, },
|
||||||
}),
|
}),
|
||||||
"nomatch2",
|
"nomatch2");
|
||||||
address: null);
|
|
||||||
|
|
||||||
var best = new TestEndpoint(EndpointMetadataCollection.Empty, "best", address: null);
|
var best = new TestEndpoint(EndpointMetadataCollection.Empty, "best");
|
||||||
|
|
||||||
var actions = new Endpoint[] { best, nomatch1, nomatch2 };
|
var actions = new Endpoint[] { best, nomatch1, nomatch2 };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
var context = new EndpointConstraintContext();
|
var context = new EndpointConstraintContext();
|
||||||
|
|
||||||
var endpointSelectorCandidate = new EndpointSelectorCandidate(
|
var endpointSelectorCandidate = new EndpointSelectorCandidate(
|
||||||
new TestEndpoint(EndpointMetadataCollection.Empty, string.Empty, address: null),
|
new TestEndpoint(EndpointMetadataCollection.Empty, string.Empty),
|
||||||
new List<IEndpointConstraint> { constraint });
|
new List<IEndpointConstraint> { constraint });
|
||||||
|
|
||||||
context.Candidates = new List<EndpointSelectorCandidate> { endpointSelectorCandidate };
|
context.Candidates = new List<EndpointSelectorCandidate> { endpointSelectorCandidate };
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
var context = CreateContext(new { });
|
var context = CreateContext(new { });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context);
|
var matches = tree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Same(entry, Assert.Single(matches).Match);
|
Assert.Same(entry, Assert.Single(matches).Match);
|
||||||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
var context = CreateContext(new { controller = "Store", action = "Buy" });
|
var context = CreateContext(new { controller = "Store", action = "Buy" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context);
|
var matches = tree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Same(entry, Assert.Single(matches).Match);
|
Assert.Same(entry, Assert.Single(matches).Match);
|
||||||
|
|
@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
var context = CreateContext(values: null, ambientValues: new { controller = "Store", action = "Buy" });
|
var context = CreateContext(values: null, ambientValues: new { controller = "Store", action = "Buy" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context);
|
var matches = tree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var match = Assert.Single(matches);
|
var match = Assert.Single(matches);
|
||||||
|
|
@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
ambientValues: new { controller = "Store", action = "Cart" });
|
ambientValues: new { controller = "Store", action = "Cart" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context);
|
var matches = tree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var match = Assert.Single(matches);
|
var match = Assert.Single(matches);
|
||||||
|
|
@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
ambientValues: new { controller = "Store", action = "Buy" });
|
ambientValues: new { controller = "Store", action = "Buy" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context);
|
var matches = tree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var match = Assert.Single(matches);
|
var match = Assert.Single(matches);
|
||||||
|
|
@ -136,7 +136,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
var context = CreateContext(new { controller = "Store", action = "AddToCart" });
|
var context = CreateContext(new { controller = "Store", action = "AddToCart" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context);
|
var matches = tree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(matches);
|
Assert.Empty(matches);
|
||||||
|
|
@ -158,7 +158,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
ambientValues: new { controller = "Store", action = "Cart" });
|
ambientValues: new { controller = "Store", action = "Cart" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context);
|
var matches = tree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(matches);
|
Assert.Empty(matches);
|
||||||
|
|
@ -183,7 +183,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
ambientValues: new { controller = "Store", action = "Buy" });
|
ambientValues: new { controller = "Store", action = "Buy" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context);
|
var matches = tree.GetMatches(context.Values, context.AmbientValues);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Same(entry1, Assert.Single(matches).Match);
|
Assert.Same(entry1, Assert.Single(matches).Match);
|
||||||
|
|
@ -209,7 +209,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
ambientValues: new { controller = "Store", action = "Buy" });
|
ambientValues: new { controller = "Store", action = "Buy" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context).Select(m => m.Match).ToList();
|
var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(entries, matches);
|
Assert.Equal(entries, matches);
|
||||||
|
|
@ -233,7 +233,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
var context = CreateContext(new { controller = "Store", action = "Buy", slug = "1234" });
|
var context = CreateContext(new { controller = "Store", action = "Buy", slug = "1234" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context).Select(m => m.Match).ToList();
|
var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(entries, matches);
|
Assert.Equal(entries, matches);
|
||||||
|
|
@ -260,7 +260,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
var context = CreateContext(new { controller = "Store", action = "Buy" });
|
var context = CreateContext(new { controller = "Store", action = "Buy" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context).Select(m => m.Match).ToList();
|
var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(entries, matches);
|
Assert.Equal(entries, matches);
|
||||||
|
|
@ -286,7 +286,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
var context = CreateContext(new { controller = "Store", action = "Buy" });
|
var context = CreateContext(new { controller = "Store", action = "Buy" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context).Select(m => m.Match).ToList();
|
var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(entries, matches);
|
Assert.Equal(entries, matches);
|
||||||
|
|
@ -312,7 +312,7 @@ namespace Microsoft.AspNetCore.Routing.Internal.Routing
|
||||||
var context = CreateContext(new { controller = "Store", action = "Buy" });
|
var context = CreateContext(new { controller = "Store", action = "Buy" });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var matches = tree.GetMatches(context).Select(m => m.Match).ToList();
|
var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(entries, matches);
|
Assert.Equal(entries, matches);
|
||||||
|
|
|
||||||
|
|
@ -34,17 +34,18 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
|
|
||||||
internal static MatcherEndpoint CreateEndpoint(
|
internal static MatcherEndpoint CreateEndpoint(
|
||||||
string template,
|
string template,
|
||||||
object defaults = null,
|
object defaultValues = null,
|
||||||
int? order = null)
|
int? order = null)
|
||||||
{
|
{
|
||||||
|
var defaults = defaultValues == null ? new RouteValueDictionary() : new RouteValueDictionary(defaultValues);
|
||||||
return new MatcherEndpoint(
|
return new MatcherEndpoint(
|
||||||
MatcherEndpoint.EmptyInvoker,
|
MatcherEndpoint.EmptyInvoker,
|
||||||
template,
|
template,
|
||||||
defaults,
|
defaults,
|
||||||
|
new RouteValueDictionary(),
|
||||||
order ?? 0,
|
order ?? 0,
|
||||||
EndpointMetadataCollection.Empty,
|
EndpointMetadataCollection.Empty,
|
||||||
"endpoint: " + template,
|
"endpoint: " + template);
|
||||||
address: null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal (Matcher matcher, MatcherEndpoint endpoint) CreateMatcher(string template)
|
internal (Matcher matcher, MatcherEndpoint endpoint) CreateMatcher(string template)
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
// MatcherEndpoint.Values contains the default values parsed from the template
|
// MatcherEndpoint.Values contains the default values parsed from the template
|
||||||
// as well as those specified with a literal. We need to separate those
|
// as well as those specified with a literal. We need to separate those
|
||||||
// for legacy cases.
|
// for legacy cases.
|
||||||
var defaults = new RouteValueDictionary(endpoint.Values);
|
var defaults = endpoint.Defaults;
|
||||||
for (var i = 0; i < endpoint.ParsedTemlate.Parameters.Count; i++)
|
for (var i = 0; i < endpoint.ParsedTemplate.Parameters.Count; i++)
|
||||||
{
|
{
|
||||||
var parameter = endpoint.ParsedTemlate.Parameters[i];
|
var parameter = endpoint.ParsedTemplate.Parameters[i];
|
||||||
if (parameter.DefaultValue != null)
|
if (parameter.DefaultValue != null)
|
||||||
{
|
{
|
||||||
defaults.Remove(parameter.Name);
|
defaults.Remove(parameter.Name);
|
||||||
|
|
@ -79,7 +79,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
return comparison;
|
return comparison;
|
||||||
}
|
}
|
||||||
|
|
||||||
comparison = RoutePrecedence.ComputeInbound(Endpoint.ParsedTemlate).CompareTo(RoutePrecedence.ComputeInbound(other.Endpoint.ParsedTemlate));
|
comparison = RoutePrecedence.ComputeInbound(Endpoint.ParsedTemplate).CompareTo(RoutePrecedence.ComputeInbound(other.Endpoint.ParsedTemplate));
|
||||||
if (comparison != 0)
|
if (comparison != 0)
|
||||||
{
|
{
|
||||||
return comparison;
|
return comparison;
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,22 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing.Matchers
|
namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
{
|
{
|
||||||
public class TreeMatcherTests
|
public class TreeMatcherTests
|
||||||
{
|
{
|
||||||
private MatcherEndpoint CreateEndpoint(string template, int order, object values = null, EndpointMetadataCollection metadata = null)
|
private MatcherEndpoint CreateEndpoint(string template, int order, object defaultValues = null, EndpointMetadataCollection metadata = null)
|
||||||
{
|
{
|
||||||
return new MatcherEndpoint((next) => null, template, values, order, metadata ?? EndpointMetadataCollection.Empty, template, address: null);
|
var defaults = defaultValues == null ? new RouteValueDictionary() : new RouteValueDictionary(defaultValues);
|
||||||
|
return new MatcherEndpoint((next) => null, template, defaults, new RouteValueDictionary(), order, metadata ?? EndpointMetadataCollection.Empty, template);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TreeMatcher CreateTreeMatcher(EndpointDataSource endpointDataSource)
|
private TreeMatcher CreateTreeMatcher(EndpointDataSource endpointDataSource)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Routing.Internal;
|
using Microsoft.AspNetCore.Routing.Internal;
|
||||||
using Microsoft.AspNetCore.Routing.Template;
|
|
||||||
using Microsoft.AspNetCore.Routing.Tree;
|
using Microsoft.AspNetCore.Routing.Tree;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Microsoft.Extensions.ObjectPool;
|
using Microsoft.Extensions.ObjectPool;
|
||||||
|
|
@ -38,10 +37,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
// MatcherEndpoint.Values contains the default values parsed from the template
|
// MatcherEndpoint.Values contains the default values parsed from the template
|
||||||
// as well as those specified with a literal. We need to separate those
|
// as well as those specified with a literal. We need to separate those
|
||||||
// for legacy cases.
|
// for legacy cases.
|
||||||
var defaults = new RouteValueDictionary(endpoint.Values);
|
var defaults = endpoint.Defaults;
|
||||||
for (var i = 0; i < endpoint.ParsedTemlate.Parameters.Count; i++)
|
for (var i = 0; i < endpoint.ParsedTemplate.Parameters.Count; i++)
|
||||||
{
|
{
|
||||||
var parameter = endpoint.ParsedTemlate.Parameters[i];
|
var parameter = endpoint.ParsedTemplate.Parameters[i];
|
||||||
if (parameter.DefaultValue == null && defaults.ContainsKey(parameter.Name))
|
if (parameter.DefaultValue == null && defaults.ContainsKey(parameter.Name))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
|
|
@ -50,8 +49,8 @@ namespace Microsoft.AspNetCore.Routing.Matchers
|
||||||
}
|
}
|
||||||
|
|
||||||
_inner.MapInbound(
|
_inner.MapInbound(
|
||||||
handler,
|
handler,
|
||||||
endpoint.ParsedTemlate,
|
endpoint.ParsedTemplate,
|
||||||
routeName: null,
|
routeName: null,
|
||||||
order: endpoint.Order);
|
order: endpoint.Order);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ namespace Microsoft.AspNetCore.Routing.TestObjects
|
||||||
{
|
{
|
||||||
internal class TestEndpoint : Endpoint
|
internal class TestEndpoint : Endpoint
|
||||||
{
|
{
|
||||||
public TestEndpoint(EndpointMetadataCollection metadata, string displayName, Address address)
|
public TestEndpoint(EndpointMetadataCollection metadata, string displayName)
|
||||||
: base(metadata, displayName, address)
|
: base(metadata, displayName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Routing.Matchers;
|
using Microsoft.AspNetCore.Routing.Matchers;
|
||||||
|
|
@ -22,7 +20,7 @@ namespace Microsoft.AspNetCore.Routing.TestObjects
|
||||||
{
|
{
|
||||||
if (_isHandled)
|
if (_isHandled)
|
||||||
{
|
{
|
||||||
feature.Endpoint = new TestEndpoint(EndpointMetadataCollection.Empty, "Test endpoint", address: null);
|
feature.Endpoint = new TestEndpoint(EndpointMetadataCollection.Empty, "Test endpoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue