Merge pull request #887 from dotnet-maestro-bot/merge/release/2.2-to-master
[automated] Merge branch 'release/2.2' => 'master'
This commit is contained in:
commit
74336f10c7
|
|
@ -1,126 +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.Http;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Defines a contract to generate a URL from a template.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// A <see cref="LinkGenerationTemplate"/> can be created from <see cref="LinkGenerator.GetTemplateByAddress{TAddress}(TAddress, LinkGenerationTemplateOptions)"/>
|
|
||||||
/// by supplying an address value which has matching endpoints. The returned <see cref="LinkGenerationTemplate"/>
|
|
||||||
/// will be bound to the endpoints matching the address that was originally provided.
|
|
||||||
/// </remarks>
|
|
||||||
public abstract class LinkGenerationTemplate
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Generates a URI with an absolute path based on the provided values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
|
|
||||||
/// <param name="values">The route values. Used to expand parameters in the route template. Optional.</param>
|
|
||||||
/// <param name="pathBase">
|
|
||||||
/// An optional URI path base. Prepended to the path in the resulting URI. If not provided, the value of <see cref="HttpRequest.PathBase"/> will be used.
|
|
||||||
/// </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 abstract string GetPath(
|
|
||||||
HttpContext httpContext,
|
|
||||||
object values,
|
|
||||||
PathString? pathBase = default,
|
|
||||||
FragmentString fragment = default,
|
|
||||||
LinkOptions options = default);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generates a URI with an absolute path based on the provided values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values">The route values. Used to 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 abstract string GetPath(
|
|
||||||
object values,
|
|
||||||
PathString pathBase = default,
|
|
||||||
FragmentString fragment = default,
|
|
||||||
LinkOptions options = default);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generates an absolute URI based on the provided values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
|
|
||||||
/// <param name="values">The route values. Used to expand parameters in the route template. Optional.</param>
|
|
||||||
/// <param name="scheme">
|
|
||||||
/// The URI scheme, applied to the resulting URI. Optional. If not provided, the value of <see cref="HttpRequest.Scheme"/> will be used.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="host">
|
|
||||||
/// The URI host/authority, applied to the resulting URI. Optional. If not provided, the value <see cref="HttpRequest.Host"/> will be used.
|
|
||||||
/// See the remarks section for details about the security implications of the <paramref name="host"/>.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="pathBase">
|
|
||||||
/// An optional URI path base. Prepended to the path in the resulting URI. If not provided, the value of <see cref="HttpRequest.PathBase"/> will be used.
|
|
||||||
/// </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>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// The value of <paramref name="host" /> should be a trusted value. Relying on the value of the current request
|
|
||||||
/// can allow untrusted input to influence the resulting URI unless the <c>Host</c> header has been validated.
|
|
||||||
/// See the deployment documentation for instructions on how to properly validate the <c>Host</c> header in
|
|
||||||
/// your deployment environment.
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
public abstract string GetUri(
|
|
||||||
HttpContext httpContext,
|
|
||||||
object values,
|
|
||||||
string scheme = default,
|
|
||||||
HostString? host = default,
|
|
||||||
PathString? pathBase = default,
|
|
||||||
FragmentString fragment = default,
|
|
||||||
LinkOptions options = default);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generates an absolute URI based on the provided values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values">The route values. Used to 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.
|
|
||||||
/// See the remarks section for details about the security implications of the <paramref name="host"/>.
|
|
||||||
/// </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>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// The value of <paramref name="host" /> should be a trusted value. Relying on the value of the current request
|
|
||||||
/// can allow untrusted input to influence the resulting URI unless the <c>Host</c> header has been validated.
|
|
||||||
/// See the deployment documentation for instructions on how to properly validate the <c>Host</c> header in
|
|
||||||
/// your deployment environment.
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
public abstract string GetUri(
|
|
||||||
object values,
|
|
||||||
string scheme,
|
|
||||||
HostString host,
|
|
||||||
PathString pathBase = default,
|
|
||||||
FragmentString fragment = default,
|
|
||||||
LinkOptions options = default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +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.
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Contains options for creating a <see cref="LinkGenerationTemplate" />.
|
|
||||||
/// </summary>
|
|
||||||
public class LinkGenerationTemplateOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether the template will use route values from the current request
|
|
||||||
/// when generating a URI.
|
|
||||||
/// </summary>
|
|
||||||
public bool UseAmbientValues { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -147,16 +147,5 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
PathString pathBase = default,
|
PathString pathBase = default,
|
||||||
FragmentString fragment = default,
|
FragmentString fragment = default,
|
||||||
LinkOptions options = default);
|
LinkOptions options = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a <see cref="LinkGenerationTemplate"/> based on the provided <paramref name="address"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TAddress">The address type.</typeparam>
|
|
||||||
/// <param name="address">The address value. Used to resolve endpoints.</param>
|
|
||||||
/// <param name="options">Options for the created <see cref="LinkGenerationTemplate"/>.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// A <see cref="LinkGenerationTemplate"/> if one or more endpoints matching the address can be found, otherwise <c>null</c>.
|
|
||||||
/// </returns>
|
|
||||||
public abstract LinkGenerationTemplate GetTemplateByAddress<TAddress>(TAddress address, LinkGenerationTemplateOptions options = null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,20 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DefaultEndpointDataSource : EndpointDataSource
|
public sealed class DefaultEndpointDataSource : EndpointDataSource
|
||||||
{
|
{
|
||||||
private readonly List<Endpoint> _endpoints;
|
private readonly IReadOnlyList<Endpoint> _endpoints;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="DefaultEndpointDataSource" /> class.
|
/// Initializes a new instance of the <see cref="DefaultEndpointDataSource" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="endpoints">The <see cref="Endpoint"/> instances that the data source will return.</param>
|
/// <param name="endpoints">The <see cref="Endpoint"/> instances that the data source will return.</param>
|
||||||
public DefaultEndpointDataSource(params Endpoint[] endpoints)
|
public DefaultEndpointDataSource(params Endpoint[] endpoints)
|
||||||
: this((IEnumerable<Endpoint>) endpoints)
|
|
||||||
{
|
{
|
||||||
|
if (endpoints == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(endpoints));
|
||||||
|
}
|
||||||
|
|
||||||
|
_endpoints = (Endpoint[])endpoints.Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -36,8 +41,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
throw new ArgumentNullException(nameof(endpoints));
|
throw new ArgumentNullException(nameof(endpoints));
|
||||||
}
|
}
|
||||||
|
|
||||||
_endpoints = new List<Endpoint>();
|
_endpoints = new List<Endpoint>(endpoints);
|
||||||
_endpoints.AddRange(endpoints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,120 +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.Http;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
|
||||||
{
|
|
||||||
internal sealed class DefaultLinkGenerationTemplate : LinkGenerationTemplate
|
|
||||||
{
|
|
||||||
public DefaultLinkGenerationTemplate(DefaultLinkGenerator linkGenerator, List<RouteEndpoint> endpoints, LinkGenerationTemplateOptions options)
|
|
||||||
{
|
|
||||||
LinkGenerator = linkGenerator;
|
|
||||||
Endpoints = endpoints;
|
|
||||||
Options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultLinkGenerator LinkGenerator { get; }
|
|
||||||
|
|
||||||
public List<RouteEndpoint> Endpoints { get; }
|
|
||||||
|
|
||||||
public LinkGenerationTemplateOptions Options { get; }
|
|
||||||
|
|
||||||
public override string GetPath(
|
|
||||||
HttpContext httpContext,
|
|
||||||
object values,
|
|
||||||
PathString? pathBase = default,
|
|
||||||
FragmentString fragment = default,
|
|
||||||
LinkOptions options = default)
|
|
||||||
{
|
|
||||||
if (httpContext == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(httpContext));
|
|
||||||
}
|
|
||||||
|
|
||||||
return LinkGenerator.GetPathByEndpoints(
|
|
||||||
Endpoints,
|
|
||||||
new RouteValueDictionary(values),
|
|
||||||
GetAmbientValues(httpContext),
|
|
||||||
pathBase ?? httpContext.Request.PathBase,
|
|
||||||
fragment,
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetPath(
|
|
||||||
object values,
|
|
||||||
PathString pathBase = default,
|
|
||||||
FragmentString fragment = default,
|
|
||||||
LinkOptions options = default)
|
|
||||||
{
|
|
||||||
return LinkGenerator.GetPathByEndpoints(
|
|
||||||
Endpoints,
|
|
||||||
new RouteValueDictionary(values),
|
|
||||||
ambientValues: null,
|
|
||||||
pathBase: pathBase,
|
|
||||||
fragment: fragment,
|
|
||||||
options: options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetUri(
|
|
||||||
HttpContext httpContext,
|
|
||||||
object values,
|
|
||||||
string scheme = default,
|
|
||||||
HostString? host = default,
|
|
||||||
PathString? pathBase = default,
|
|
||||||
FragmentString fragment = default,
|
|
||||||
LinkOptions options = default)
|
|
||||||
{
|
|
||||||
if (httpContext == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(httpContext));
|
|
||||||
}
|
|
||||||
|
|
||||||
return LinkGenerator.GetUriByEndpoints(
|
|
||||||
Endpoints,
|
|
||||||
new RouteValueDictionary(values),
|
|
||||||
GetAmbientValues(httpContext),
|
|
||||||
scheme ?? httpContext.Request.Scheme,
|
|
||||||
host ?? httpContext.Request.Host,
|
|
||||||
pathBase ?? httpContext.Request.PathBase,
|
|
||||||
fragment,
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetUri(
|
|
||||||
object values,
|
|
||||||
string scheme,
|
|
||||||
HostString host,
|
|
||||||
PathString pathBase = default,
|
|
||||||
FragmentString fragment = default,
|
|
||||||
LinkOptions options = default)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(scheme))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("A scheme must be provided.", nameof(scheme));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!host.HasValue)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("A host must be provided.", nameof(host));
|
|
||||||
}
|
|
||||||
|
|
||||||
return LinkGenerator.GetUriByEndpoints(
|
|
||||||
Endpoints,
|
|
||||||
new RouteValueDictionary(values),
|
|
||||||
ambientValues: null,
|
|
||||||
scheme: scheme,
|
|
||||||
host: host,
|
|
||||||
pathBase: pathBase,
|
|
||||||
fragment: fragment,
|
|
||||||
options: options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RouteValueDictionary GetAmbientValues(HttpContext httpContext)
|
|
||||||
{
|
|
||||||
return (Options?.UseAmbientValues ?? false) ? DefaultLinkGenerator.GetAmbientValues(httpContext) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -189,17 +189,6 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
options: options);
|
options: options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override LinkGenerationTemplate GetTemplateByAddress<TAddress>(TAddress address, LinkGenerationTemplateOptions options = default)
|
|
||||||
{
|
|
||||||
var endpoints = GetEndpoints(address);
|
|
||||||
if (endpoints.Count == 0)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DefaultLinkGenerationTemplate(this, endpoints, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RouteEndpoint> GetEndpoints<TAddress>(TAddress address)
|
private List<RouteEndpoint> GetEndpoints<TAddress>(TAddress address)
|
||||||
{
|
{
|
||||||
var addressingScheme = _serviceProvider.GetRequiredService<IEndpointAddressScheme<TAddress>>();
|
var addressingScheme = _serviceProvider.GetRequiredService<IEndpointAddressScheme<TAddress>>();
|
||||||
|
|
@ -217,7 +206,6 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
return endpoints;
|
return endpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also called from DefaultLinkGenerationTemplate
|
|
||||||
public string GetPathByEndpoints(
|
public string GetPathByEndpoints(
|
||||||
List<RouteEndpoint> endpoints,
|
List<RouteEndpoint> endpoints,
|
||||||
RouteValueDictionary values,
|
RouteValueDictionary values,
|
||||||
|
|
|
||||||
|
|
@ -242,18 +242,29 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
// Used by TemplateBinder.TryBindValues - the new code path of LinkGenerator
|
// Used by TemplateBinder.TryBindValues - the new code path of LinkGenerator
|
||||||
public PathString ToPathString()
|
public PathString ToPathString()
|
||||||
{
|
{
|
||||||
if (_path.Length > 0 && _path[0] != '/')
|
PathString pathString;
|
||||||
|
|
||||||
|
if (_path.Length > 0)
|
||||||
{
|
{
|
||||||
// Normalize generated paths so that they always contain a leading slash.
|
if (_path[0] != '/')
|
||||||
_path.Insert(0, '/');
|
{
|
||||||
|
// Normalize generated paths so that they always contain a leading slash.
|
||||||
|
_path.Insert(0, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AppendTrailingSlash && _path[_path.Length - 1] != '/')
|
||||||
|
{
|
||||||
|
_path.Append('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
pathString = new PathString(_path.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pathString = PathString.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AppendTrailingSlash && _path.Length > 0 && _path[_path.Length - 1] != '/')
|
return pathString;
|
||||||
{
|
|
||||||
_path.Append('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PathString(_path.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by TemplateBinder.TryBindValues - the new code path of LinkGenerator
|
// Used by TemplateBinder.TryBindValues - the new code path of LinkGenerator
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,6 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class LinkGeneratorEndpointNameAddressExtensions
|
public static class LinkGeneratorEndpointNameAddressExtensions
|
||||||
{
|
{
|
||||||
private static readonly LinkGenerationTemplateOptions _templateOptions = new LinkGenerationTemplateOptions()
|
|
||||||
{
|
|
||||||
UseAmbientValues = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a URI with an absolute path based on the provided values.
|
/// Generates a URI with an absolute path based on the provided values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -227,28 +222,5 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
return generator.GetUriByAddress<string>(endpointName, new RouteValueDictionary(values), scheme, host, pathBase, fragment, options);
|
return generator.GetUriByAddress<string>(endpointName, new RouteValueDictionary(values), scheme, host, pathBase, fragment, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a <see cref="LinkGenerationTemplate"/> based on the provided <paramref name="endpointName"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="generator">The <see cref="LinkGenerator"/>.</param>
|
|
||||||
/// <param name="endpointName">The endpoint name. Used to resolve endpoints. 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 GetTemplateByName(this LinkGenerator generator, string endpointName)
|
|
||||||
{
|
|
||||||
if (generator == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(generator));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endpointName == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(endpointName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return generator.GetTemplateByAddress<string>(endpointName, _templateOptions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,6 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class LinkGeneratorRouteValuesAddressExtensions
|
public static class LinkGeneratorRouteValuesAddressExtensions
|
||||||
{
|
{
|
||||||
private static readonly LinkGenerationTemplateOptions _templateOptions = new LinkGenerationTemplateOptions()
|
|
||||||
{
|
|
||||||
UseAmbientValues = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a URI with an absolute path based on the provided values.
|
/// Generates a URI with an absolute path based on the provided values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -202,29 +197,6 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
return generator.GetUriByAddress<RouteValuesAddress>(address, address.ExplicitValues, scheme, host, pathBase, fragment, options);
|
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, _templateOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RouteValuesAddress CreateAddress(HttpContext httpContext, string routeName, object values)
|
private static RouteValuesAddress CreateAddress(HttpContext httpContext, string routeName, object values)
|
||||||
{
|
{
|
||||||
return new RouteValuesAddress()
|
return new RouteValuesAddress()
|
||||||
|
|
|
||||||
|
|
@ -75,16 +75,20 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
int? foundScore = null;
|
int? foundScore = null;
|
||||||
for (var i = 0; i < candidateSet.Count; i++)
|
for (var i = 0; i < candidateSet.Count; i++)
|
||||||
{
|
{
|
||||||
|
if (!candidateSet.IsValidCandidate(i))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ref var state = ref candidateSet[i];
|
ref var state = ref candidateSet[i];
|
||||||
var isValid = candidateSet.IsValidCandidate(i);
|
if (foundScore == null)
|
||||||
if (isValid && foundScore == null)
|
|
||||||
{
|
{
|
||||||
// This is the first match we've seen - speculatively assign it.
|
// This is the first match we've seen - speculatively assign it.
|
||||||
endpoint = state.Endpoint;
|
endpoint = state.Endpoint;
|
||||||
values = state.Values;
|
values = state.Values;
|
||||||
foundScore = state.Score;
|
foundScore = state.Score;
|
||||||
}
|
}
|
||||||
else if (isValid && foundScore < state.Score)
|
else if (foundScore < state.Score)
|
||||||
{
|
{
|
||||||
// This candidate is lower priority than the one we've seen
|
// This candidate is lower priority than the one we've seen
|
||||||
// so far, we can stop.
|
// so far, we can stop.
|
||||||
|
|
@ -92,7 +96,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
// Don't worry about the 'null < state.Score' case, it returns false.
|
// Don't worry about the 'null < state.Score' case, it returns false.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (isValid && foundScore == state.Score)
|
else if (foundScore == state.Score)
|
||||||
{
|
{
|
||||||
// This is the second match we've found of the same score, so there
|
// This is the second match we've found of the same score, so there
|
||||||
// must be an ambiguity.
|
// must be an ambiguity.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -26,6 +25,34 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
endpoint => Assert.Equal("2", endpoint.DisplayName));
|
endpoint => Assert.Equal("2", endpoint.DisplayName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_Params_ShouldMakeCopyOfEndpoints()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "1");
|
||||||
|
var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "2");
|
||||||
|
var endpoints = new[] { endpoint1, endpoint2 };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var dataSource = new DefaultEndpointDataSource(endpoints);
|
||||||
|
Array.Resize(ref endpoints, 1);
|
||||||
|
endpoints[0] = null;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(2, dataSource.Endpoints.Count);
|
||||||
|
Assert.Contains(endpoint1, dataSource.Endpoints);
|
||||||
|
Assert.Contains(endpoint2, dataSource.Endpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_Params_ShouldThrowArgumentNullExceptionWhenEndpointsIsNull()
|
||||||
|
{
|
||||||
|
Endpoint[] endpoints = null;
|
||||||
|
|
||||||
|
var actual = Assert.Throws<ArgumentNullException>(() => new DefaultEndpointDataSource(endpoints));
|
||||||
|
Assert.Equal("endpoints", actual.ParamName);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Constructor_Enumerable_EndpointsInitialized()
|
public void Constructor_Enumerable_EndpointsInitialized()
|
||||||
{
|
{
|
||||||
|
|
@ -41,5 +68,33 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
endpoint => Assert.Equal("1", endpoint.DisplayName),
|
endpoint => Assert.Equal("1", endpoint.DisplayName),
|
||||||
endpoint => Assert.Equal("2", endpoint.DisplayName));
|
endpoint => Assert.Equal("2", endpoint.DisplayName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_Enumerable_ShouldMakeCopyOfEndpoints()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "1");
|
||||||
|
var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "2");
|
||||||
|
var endpoints = new List<Endpoint> { endpoint1, endpoint2 };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var dataSource = new DefaultEndpointDataSource((IEnumerable<Endpoint>)endpoints);
|
||||||
|
endpoints.RemoveAt(0);
|
||||||
|
endpoints[0] = null;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(2, dataSource.Endpoints.Count);
|
||||||
|
Assert.Contains(endpoint1, dataSource.Endpoints);
|
||||||
|
Assert.Contains(endpoint2, dataSource.Endpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_Enumerable_ShouldThrowArgumentNullExceptionWhenEndpointsIsNull()
|
||||||
|
{
|
||||||
|
IEnumerable<Endpoint> endpoints = null;
|
||||||
|
|
||||||
|
var actual = Assert.Throws<ArgumentNullException>(() => new DefaultEndpointDataSource(endpoints));
|
||||||
|
Assert.Equal("endpoints", actual.ParamName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,207 +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.Collections.Generic;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
|
||||||
{
|
|
||||||
// Tests DefaultLinkGenerationTemplate functionality - these are pretty light since most of the functionality
|
|
||||||
// is a direct subset of DefaultLinkGenerator
|
|
||||||
//
|
|
||||||
// Does not cover template processing in detail, those scenarios are validated by TemplateBinderTests
|
|
||||||
// and DefaultLinkGeneratorProcessTemplateTest
|
|
||||||
public class DefaultLinkGenerationTemplateTest : LinkGeneratorTestBase
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public void GetPath_WithoutHttpContext_WithPathBaseAndFragment()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}");
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}");
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator();
|
|
||||||
var template = new DefaultLinkGenerationTemplate(linkGenerator, new List<RouteEndpoint>() { endpoint1, endpoint2, }, options: null);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var path = template.GetPath(
|
|
||||||
values: new RouteValueDictionary(new { controller = "Home", action = "In?dex", query = "some?query" }),
|
|
||||||
new PathString("/Foo/Bar?encodeme?"),
|
|
||||||
new FragmentString("#Fragment?"),
|
|
||||||
new LinkOptions() { AppendTrailingSlash = true, });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("/Foo/Bar%3Fencodeme%3F/Home/In%3Fdex/?query=some%3Fquery#Fragment?", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetPath_WithHttpContext_WithPathBaseAndFragment()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}");
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}");
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator();
|
|
||||||
var template = new DefaultLinkGenerationTemplate(linkGenerator, new List<RouteEndpoint>() { endpoint1, endpoint2, }, options: null);
|
|
||||||
|
|
||||||
var httpContext = CreateHttpContext();
|
|
||||||
httpContext.Request.PathBase = new PathString("/Foo/Bar?encodeme?");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var path = template.GetPath(
|
|
||||||
httpContext,
|
|
||||||
values: new RouteValueDictionary(new { controller = "Home", action = "In?dex", query = "some?query" }),
|
|
||||||
fragment: new FragmentString("#Fragment?"),
|
|
||||||
options: new LinkOptions() { AppendTrailingSlash = true, });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("/Foo/Bar%3Fencodeme%3F/Home/In%3Fdex/?query=some%3Fquery#Fragment?", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetUri_WithoutHttpContext_WithPathBaseAndFragment()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}");
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}");
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator();
|
|
||||||
var template = new DefaultLinkGenerationTemplate(linkGenerator, new List<RouteEndpoint>() { endpoint1, endpoint2, }, options: null);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var path = template.GetUri(
|
|
||||||
values: new RouteValueDictionary(new { controller = "Home", action = "In?dex", query = "some?query" }),
|
|
||||||
"http",
|
|
||||||
new HostString("example.com"),
|
|
||||||
new PathString("/Foo/Bar?encodeme?"),
|
|
||||||
new FragmentString("#Fragment?"),
|
|
||||||
new LinkOptions() { AppendTrailingSlash = true, });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("http://example.com/Foo/Bar%3Fencodeme%3F/Home/In%3Fdex/?query=some%3Fquery#Fragment?", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetUri_WithHttpContext_WithPathBaseAndFragment()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}");
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}");
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator();
|
|
||||||
var template = new DefaultLinkGenerationTemplate(linkGenerator, new List<RouteEndpoint>() { endpoint1, endpoint2, }, options: null);
|
|
||||||
|
|
||||||
var httpContext = CreateHttpContext();
|
|
||||||
httpContext.Request.Scheme = "http";
|
|
||||||
httpContext.Request.Host = new HostString("example.com");
|
|
||||||
httpContext.Request.PathBase = new PathString("/Foo/Bar?encodeme?");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var uri = template.GetUri(
|
|
||||||
httpContext,
|
|
||||||
values: new RouteValueDictionary(new { controller = "Home", action = "In?dex", query = "some?query" }),
|
|
||||||
fragment: new FragmentString("#Fragment?"),
|
|
||||||
options: new LinkOptions() { AppendTrailingSlash = true, });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("http://example.com/Foo/Bar%3Fencodeme%3F/Home/In%3Fdex/?query=some%3Fquery#Fragment?", uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetPath_WithHttpContext_IncludesAmbientValues_WhenUseAmbientValuesIsTrue()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}");
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}");
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator();
|
|
||||||
var template = new DefaultLinkGenerationTemplate(linkGenerator, new List<RouteEndpoint>() { endpoint1, endpoint2, }, options: new LinkGenerationTemplateOptions()
|
|
||||||
{
|
|
||||||
UseAmbientValues = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
var httpContext = CreateHttpContext(new { controller = "Home", });
|
|
||||||
httpContext.Request.Scheme = "http";
|
|
||||||
httpContext.Request.Host = new HostString("example.com");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var uri = template.GetPath(httpContext, values: new RouteValueDictionary(new { action = "Index", }));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("/Home/Index", uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetPath_WithHttpContext_ExcludesAmbientValues_WhenUseAmbientValuesIsFalse()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}");
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}");
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator();
|
|
||||||
var template = new DefaultLinkGenerationTemplate(linkGenerator, new List<RouteEndpoint>() { endpoint1, endpoint2, }, options: new LinkGenerationTemplateOptions()
|
|
||||||
{
|
|
||||||
UseAmbientValues = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
var httpContext = CreateHttpContext(new { controller = "Home", });
|
|
||||||
httpContext.Request.Scheme = "http";
|
|
||||||
httpContext.Request.Host = new HostString("example.com");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var uri = template.GetPath(httpContext, values: new RouteValueDictionary(new { action = "Index", }));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Null(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetUri_WithHttpContext_IncludesAmbientValues_WhenUseAmbientValuesIsTrue()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}");
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}");
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator();
|
|
||||||
var template = new DefaultLinkGenerationTemplate(linkGenerator, new List<RouteEndpoint>() { endpoint1, endpoint2, }, options: new LinkGenerationTemplateOptions()
|
|
||||||
{
|
|
||||||
UseAmbientValues = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
var httpContext = CreateHttpContext(new { controller = "Home", });
|
|
||||||
httpContext.Request.Scheme = "http";
|
|
||||||
httpContext.Request.Host = new HostString("example.com");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var uri = template.GetUri(httpContext, values: new { action = "Index", });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("http://example.com/Home/Index", uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetUri_WithHttpContext_ExcludesAmbientValues_WhenUseAmbientValuesIsFalse()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}");
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}");
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator();
|
|
||||||
var template = new DefaultLinkGenerationTemplate(linkGenerator, new List<RouteEndpoint>() { endpoint1, endpoint2, }, options: new LinkGenerationTemplateOptions()
|
|
||||||
{
|
|
||||||
UseAmbientValues = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
var httpContext = CreateHttpContext(new { controller = "Home", });
|
|
||||||
httpContext.Request.Scheme = "http";
|
|
||||||
httpContext.Request.Host = new HostString("example.com");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var uri = template.GetUri(httpContext, values: new { action = "Index", });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Null(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -524,42 +524,6 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
Assert.Equal("ftp://example.com:5000/Home/Index", uri);
|
Assert.Equal("ftp://example.com:5000/Home/Index", uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetTemplateByAddress_WithNoMatch_ReturnsNull()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}", metadata: new object[] { new IntMetadata(1), });
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}", metadata: new object[] { new IntMetadata(1), });
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var template = linkGenerator.GetTemplateByAddress(address: 0);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Null(template);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetTemplateByAddress_WithMatch_ReturnsTemplate()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id}", metadata: new object[] { new IntMetadata(1), });
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("{controller}/{action}/{id?}", metadata: new object[] { new IntMetadata(1), });
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var template = linkGenerator.GetTemplateByAddress(address: 1);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.NotNull(template);
|
|
||||||
Assert.Collection(
|
|
||||||
Assert.IsType<DefaultLinkGenerationTemplate>(template).Endpoints,
|
|
||||||
e => Assert.Same(endpoint1, e),
|
|
||||||
e => Assert.Same(endpoint2, e));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetTemplateBinder_CanCache()
|
public void GetTemplateBinder_CanCache()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -65,5 +65,36 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(expected, uriBuilldingContext.ToString());
|
Assert.Equal(expected, uriBuilldingContext.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("/Author", false, false, "/UrlEncode[[Author]]")]
|
||||||
|
[InlineData("/Author", false, true, "/UrlEncode[[Author]]")]
|
||||||
|
[InlineData("/Author", true, false, "/UrlEncode[[Author]]/")]
|
||||||
|
[InlineData("/Author", true, true, "/UrlEncode[[Author]]/")]
|
||||||
|
[InlineData("/Author/", false, false, "/UrlEncode[[Author]]/")]
|
||||||
|
[InlineData("/Author/", false, true, "/UrlEncode[[Author/]]")]
|
||||||
|
[InlineData("/Author/", true, false, "/UrlEncode[[Author]]/")]
|
||||||
|
[InlineData("/Author/", true, true, "/UrlEncode[[Author/]]/")]
|
||||||
|
[InlineData("Author", false, false, "/UrlEncode[[Author]]")]
|
||||||
|
[InlineData("Author", false, true, "/UrlEncode[[Author]]")]
|
||||||
|
[InlineData("Author", true, false, "/UrlEncode[[Author]]/")]
|
||||||
|
[InlineData("Author", true, true, "/UrlEncode[[Author]]/")]
|
||||||
|
[InlineData("", false, false, "")]
|
||||||
|
[InlineData("", false, true, "")]
|
||||||
|
[InlineData("", true, false, "")]
|
||||||
|
[InlineData("", true, true, "")]
|
||||||
|
public void ToPathString(string url, bool appendTrailingSlash, bool encodeSlashes, string expected)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var urlTestEncoder = new UrlTestEncoder();
|
||||||
|
var uriBuilldingContext = new UriBuildingContext(urlTestEncoder);
|
||||||
|
uriBuilldingContext.AppendTrailingSlash = appendTrailingSlash;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
uriBuilldingContext.Accept(url, encodeSlashes);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, uriBuilldingContext.ToPathString().Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,24 +149,5 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("http://example.com/Foo/Bar%3Fencodeme%3F/some%23-other-endpoint/In%3Fdex/?query=some%3Fquery#Fragment?", uri);
|
Assert.Equal("http://example.com/Foo/Bar%3Fencodeme%3F/some%23-other-endpoint/In%3Fdex/?query=some%3Fquery#Fragment?", uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetTemplateByName_CreatesTemplate()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint("some-endpoint/{p}", metadata: new[] { new EndpointNameMetadata("name1"), });
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint("some#-other-endpoint/{p}", metadata: new[] { new EndpointNameMetadata("name2"), });
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var template = linkGenerator.GetTemplateByName(endpointName: "name2");
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.NotNull(template);
|
|
||||||
Assert.Collection(
|
|
||||||
Assert.IsType<DefaultLinkGenerationTemplate>(template).Endpoints.Cast<RouteEndpoint>().OrderBy(e => e.RoutePattern.RawText),
|
|
||||||
e => Assert.Same(endpoint2, e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,31 +201,5 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("http://example.com/Foo/Bar%3Fencodeme%3F/Home/Index/?query=some%3Fquery#Fragment?", uri);
|
Assert.Equal("http://example.com/Foo/Bar%3Fencodeme%3F/Home/Index/?query=some%3Fquery#Fragment?", uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetTemplateByRouteValues_CreatesTemplate()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var endpoint1 = EndpointFactory.CreateRouteEndpoint(
|
|
||||||
"{controller}/{action}/{id}",
|
|
||||||
metadata: new[] { new RouteValuesAddressMetadata(new RouteValueDictionary(new { controller = "Home", action = "In?dex", })) });
|
|
||||||
var endpoint2 = EndpointFactory.CreateRouteEndpoint(
|
|
||||||
"{controller}/{action}/{id?}",
|
|
||||||
metadata: new[] { new RouteValuesAddressMetadata(new RouteValueDictionary(new { controller = "Home", action = "In?dex", })) });
|
|
||||||
|
|
||||||
var linkGenerator = CreateLinkGenerator(endpoint1, endpoint2);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var template = linkGenerator.GetTemplateByRouteValues(
|
|
||||||
routeName: null,
|
|
||||||
values: new RouteValueDictionary(new { controller = "Home", action = "In?dex", query = "some?query" }));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.NotNull(template);
|
|
||||||
Assert.Collection(
|
|
||||||
Assert.IsType<DefaultLinkGenerationTemplate>(template).Endpoints.Cast<RouteEndpoint>().OrderBy(e => e.RoutePattern.RawText),
|
|
||||||
e => Assert.Same(endpoint2, e),
|
|
||||||
e => Assert.Same(endpoint1, e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue