Various improvments to route values link APIs
- Add docs - Add support for templates - Remove undesirable constructor parameter - misc cleanup
This commit is contained in:
parent
c683844817
commit
57cc8aea96
|
|
@ -60,8 +60,7 @@ namespace RoutingSample.Web
|
|||
return new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
.UseStartup(startupType)
|
||||
.ConfigureLogging(l => l.AddConsole().SetMinimumLevel(LogLevel.Debug));
|
||||
.UseStartup(startupType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,19 @@ namespace Microsoft.AspNetCore.Routing
|
|||
/// </summary>
|
||||
public static class LinkGeneratorRouteValuesAddressExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a URI with an absolute path based on the provided values.
|
||||
/// </summary>
|
||||
/// <param name="generator">The <see cref="LinkGenerator"/>.</param>
|
||||
/// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
|
||||
/// <param name="routeName">The route name. Used to resolve endpoints. Optional.</param>
|
||||
/// <param name="values">The route values. Used to resolve endpoints and expand parameters in the route template. Optional.</param>
|
||||
/// <param name="fragment">An optional URI fragment. Appended to the resulting URI.</param>
|
||||
/// <param name="options">
|
||||
/// An optional <see cref="LinkOptions"/>. Settings on provided object override the settings with matching
|
||||
/// names from <c>RouteOptions</c>.
|
||||
/// </param>
|
||||
/// <returns>A URI with an absolute path, or <c>null</c>.</returns>
|
||||
public static string GetPathByRouteValues(
|
||||
this LinkGenerator generator,
|
||||
HttpContext httpContext,
|
||||
|
|
@ -28,6 +41,19 @@ namespace Microsoft.AspNetCore.Routing
|
|||
return generator.GetPathByAddress<RouteValuesAddress>(httpContext, address, address.ExplicitValues, fragment, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a URI with an absolute path based on the provided values.
|
||||
/// </summary>
|
||||
/// <param name="generator">The <see cref="LinkGenerator"/>.</param>
|
||||
/// <param name="routeName">The route name. Used to resolve endpoints. Optional.</param>
|
||||
/// <param name="values">The route values. Used to resolve endpoints and expand parameters in the route template. Optional.</param>
|
||||
/// <param name="pathBase">An optional URI path base. Prepended to the path in the resulting URI.</param>
|
||||
/// <param name="fragment">An optional URI fragment. Appended to the resulting URI.</param>
|
||||
/// <param name="options">
|
||||
/// An optional <see cref="LinkOptions"/>. Settings on provided object override the settings with matching
|
||||
/// names from <c>RouteOptions</c>.
|
||||
/// </param>
|
||||
/// <returns>A URI with an absolute path, or <c>null</c>.</returns>
|
||||
public static string GetPathByRouteValues(
|
||||
this LinkGenerator generator,
|
||||
string routeName,
|
||||
|
|
@ -45,6 +71,19 @@ namespace Microsoft.AspNetCore.Routing
|
|||
return generator.GetPathByAddress<RouteValuesAddress>(address, address.ExplicitValues, pathBase, fragment, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates an absolute URI based on the provided values.
|
||||
/// </summary>
|
||||
/// <param name="generator">The <see cref="LinkGenerator"/>.</param>
|
||||
/// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
|
||||
/// <param name="routeName">The route name. Used to resolve endpoints. Optional.</param>
|
||||
/// <param name="values">The route values. Used to resolve endpoints and expand parameters in the route template. Optional.</param>
|
||||
/// <param name="fragment">An optional URI fragment. Appended to the resulting URI.</param>
|
||||
/// <param name="options">
|
||||
/// An optional <see cref="LinkOptions"/>. Settings on provided object override the settings with matching
|
||||
/// names from <c>RouteOptions</c>.
|
||||
/// </param>
|
||||
/// <returns>A URI with an absolute path, or <c>null</c>.</returns>
|
||||
public static string GetUriByRouteValues(
|
||||
this LinkGenerator generator,
|
||||
HttpContext httpContext,
|
||||
|
|
@ -62,6 +101,21 @@ namespace Microsoft.AspNetCore.Routing
|
|||
return generator.GetUriByAddress<RouteValuesAddress>(httpContext, address, address.ExplicitValues, fragment, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates an absolute URI based on the provided values.
|
||||
/// </summary>
|
||||
/// <param name="generator">The <see cref="LinkGenerator"/>.</param>
|
||||
/// <param name="routeName">The route name. Used to resolve endpoints. Optional.</param>
|
||||
/// <param name="values">The route values. Used to resolve endpoints and expand parameters in the route template. Optional.</param>
|
||||
/// <param name="scheme">The URI scheme, applied to the resulting URI.</param>
|
||||
/// <param name="host">The URI host/authority, applied to the resulting URI.</param>
|
||||
/// <param name="pathBase">An optional URI path base. Prepended to the path in the resulting URI.</param>
|
||||
/// <param name="fragment">An optional URI fragment. Appended to the resulting URI.</param>
|
||||
/// <param name="options">
|
||||
/// An optional <see cref="LinkOptions"/>. Settings on provided object override the settings with matching
|
||||
/// names from <c>RouteOptions</c>.
|
||||
/// </param>
|
||||
/// <returns>An absolute URI, or <c>null</c>.</returns>
|
||||
public static string GetUriByRouteValues(
|
||||
this LinkGenerator generator,
|
||||
string routeName,
|
||||
|
|
@ -81,7 +135,29 @@ namespace Microsoft.AspNetCore.Routing
|
|||
return generator.GetUriByAddress<RouteValuesAddress>(address, address.ExplicitValues, scheme, host, pathBase, fragment, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="LinkGenerationTemplate"/> based on the provided <paramref name="routeName"/> and <paramref name="values"/>.
|
||||
/// </summary>
|
||||
/// <param name="generator">The <see cref="LinkGenerator"/>.</param>
|
||||
/// <param name="routeName">The route name. Used to resolve endpoints. Optional.</param>
|
||||
/// <param name="values">The route values. Used to resolve endpoints and expand parameters in the route template. Optional.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="LinkGenerationTemplate"/> if one or more endpoints matching the address can be found, otherwise <c>null</c>.
|
||||
/// </returns>
|
||||
public static LinkGenerationTemplate GetTemplateByRouteValues(
|
||||
this LinkGenerator generator,
|
||||
string routeName,
|
||||
object values)
|
||||
{
|
||||
if (generator == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(generator));
|
||||
}
|
||||
|
||||
var address = CreateAddress(httpContext: null, routeName, values);
|
||||
return generator.GetTemplateByAddress<RouteValuesAddress>(address);
|
||||
}
|
||||
|
||||
private static RouteValuesAddress CreateAddress(HttpContext httpContext, string routeName, object values)
|
||||
{
|
||||
return new RouteValuesAddress()
|
||||
|
|
|
|||
|
|
@ -6,33 +6,27 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing.Internal;
|
||||
using Microsoft.AspNetCore.Routing.Matching;
|
||||
using Microsoft.AspNetCore.Routing.Template;
|
||||
using Microsoft.AspNetCore.Routing.Tree;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
{
|
||||
internal class RouteValuesBasedEndpointFinder : IEndpointFinder<RouteValuesAddress>
|
||||
{
|
||||
private readonly CompositeEndpointDataSource _endpointDataSource;
|
||||
private readonly ObjectPool<UriBuildingContext> _objectPool;
|
||||
private readonly CompositeEndpointDataSource _dataSource;
|
||||
private LinkGenerationDecisionTree _allMatchesLinkGenerationTree;
|
||||
private IDictionary<string, List<OutboundMatchResult>> _namedMatchResults;
|
||||
|
||||
public RouteValuesBasedEndpointFinder(
|
||||
CompositeEndpointDataSource endpointDataSource,
|
||||
ObjectPool<UriBuildingContext> objectPool)
|
||||
public RouteValuesBasedEndpointFinder(CompositeEndpointDataSource dataSource)
|
||||
{
|
||||
_endpointDataSource = endpointDataSource;
|
||||
_objectPool = objectPool;
|
||||
_dataSource = dataSource;
|
||||
|
||||
// Build initial matches
|
||||
BuildOutboundMatches();
|
||||
|
||||
// Register for changes in endpoints
|
||||
Extensions.Primitives.ChangeToken.OnChange(
|
||||
_endpointDataSource.GetChangeToken,
|
||||
_dataSource.GetChangeToken,
|
||||
HandleChange);
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +62,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
// re-register the callback as the change token is one time use only and a new change token
|
||||
// is produced every time
|
||||
Extensions.Primitives.ChangeToken.OnChange(
|
||||
_endpointDataSource.GetChangeToken,
|
||||
_dataSource.GetChangeToken,
|
||||
HandleChange);
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +98,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
var namedOutboundMatchResults = new Dictionary<string, List<OutboundMatchResult>>(
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var endpoints = _endpointDataSource.Endpoints.OfType<RouteEndpoint>();
|
||||
var endpoints = _dataSource.Endpoints.OfType<RouteEndpoint>();
|
||||
foreach (var endpoint in endpoints)
|
||||
{
|
||||
// Do not consider an endpoint for link generation if the following marker metadata is on it
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Routing.Internal;
|
|||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
using Microsoft.AspNetCore.Routing.TestObjects;
|
||||
using Microsoft.AspNetCore.Routing.Tree;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
|
|
@ -83,13 +82,9 @@ namespace Microsoft.AspNetCore.Routing
|
|||
// Arrange 1
|
||||
var endpoint1 = CreateEndpoint("/a");
|
||||
var dynamicDataSource = new DynamicEndpointDataSource(new[] { endpoint1 });
|
||||
var objectPoolProvider = new DefaultObjectPoolProvider();
|
||||
var objectPool = objectPoolProvider.Create(new UriBuilderContextPooledObjectPolicy());
|
||||
|
||||
// Act 1
|
||||
var finder = new CustomRouteValuesBasedEndpointFinder(
|
||||
new CompositeEndpointDataSource(new[] { dynamicDataSource }),
|
||||
objectPool);
|
||||
var finder = new CustomRouteValuesBasedEndpointFinder(new CompositeEndpointDataSource(new[] { dynamicDataSource }));
|
||||
|
||||
// Assert 1
|
||||
Assert.NotNull(finder.AllMatches);
|
||||
|
|
@ -218,14 +213,9 @@ namespace Microsoft.AspNetCore.Routing
|
|||
return CreateEndpointFinder(new DefaultEndpointDataSource(endpoints));
|
||||
}
|
||||
|
||||
private CustomRouteValuesBasedEndpointFinder CreateEndpointFinder(params EndpointDataSource[] endpointDataSources)
|
||||
private CustomRouteValuesBasedEndpointFinder CreateEndpointFinder(params EndpointDataSource[] dataSources)
|
||||
{
|
||||
var objectPoolProvider = new DefaultObjectPoolProvider();
|
||||
var objectPool = objectPoolProvider.Create(new UriBuilderContextPooledObjectPolicy());
|
||||
|
||||
return new CustomRouteValuesBasedEndpointFinder(
|
||||
new CompositeEndpointDataSource(endpointDataSources),
|
||||
objectPool);
|
||||
return new CustomRouteValuesBasedEndpointFinder(new CompositeEndpointDataSource(dataSources));
|
||||
}
|
||||
|
||||
private RouteEndpoint CreateEndpoint(
|
||||
|
|
@ -256,10 +246,8 @@ namespace Microsoft.AspNetCore.Routing
|
|||
|
||||
private class CustomRouteValuesBasedEndpointFinder : RouteValuesBasedEndpointFinder
|
||||
{
|
||||
public CustomRouteValuesBasedEndpointFinder(
|
||||
CompositeEndpointDataSource endpointDataSource,
|
||||
ObjectPool<UriBuildingContext> objectPool)
|
||||
: base(endpointDataSource, objectPool)
|
||||
public CustomRouteValuesBasedEndpointFinder(CompositeEndpointDataSource dataSource)
|
||||
: base(dataSource)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue