Created LinkGenerationTemplate and friends
This commit is contained in:
parent
b177ba5309
commit
c8946a40e4
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 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>
|
||||||
|
/// Defines a contract to generate a URL from a template.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class LinkGenerationTemplate
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
|
public string MakeUrl(object values)
|
||||||
|
{
|
||||||
|
return MakeUrl(values, options: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values and link options.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
|
public abstract string MakeUrl(object values, LinkOptions options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,78 +6,191 @@ using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines a contract to generate URLs to endpoints.
|
||||||
|
/// </summary>
|
||||||
public abstract class LinkGenerator
|
public abstract class LinkGenerator
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLink(object values)
|
public string GetLink(object values)
|
||||||
{
|
{
|
||||||
return GetLink(httpContext: null, routeName: null, values, options: null);
|
return GetLink(httpContext: null, routeName: null, values, options: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values and link options.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLink(object values, LinkOptions options)
|
public string GetLink(object values, LinkOptions options)
|
||||||
{
|
{
|
||||||
return GetLink(httpContext: null, routeName: null, values, options);
|
return GetLink(httpContext: null, routeName: null, values, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLink(object values, out string link)
|
public bool TryGetLink(object values, out string link)
|
||||||
{
|
{
|
||||||
return TryGetLink(httpContext: null, routeName: null, values, options: null, out link);
|
return TryGetLink(httpContext: null, routeName: null, values, options: null, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values and link options.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLink(object values, LinkOptions options, out string link)
|
public bool TryGetLink(object values, LinkOptions options, out string link)
|
||||||
{
|
{
|
||||||
return TryGetLink(httpContext: null, routeName: null, values, options, out link);
|
return TryGetLink(httpContext: null, routeName: null, values, options, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLink(HttpContext httpContext, object values)
|
public string GetLink(HttpContext httpContext, object values)
|
||||||
{
|
{
|
||||||
return GetLink(httpContext, routeName: null, values, options: null);
|
return GetLink(httpContext, routeName: null, values, options: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLink(HttpContext httpContext, object values, out string link)
|
public bool TryGetLink(HttpContext httpContext, object values, out string link)
|
||||||
{
|
{
|
||||||
return TryGetLink(httpContext, routeName: null, values, options: null, out link);
|
return TryGetLink(httpContext, routeName: null, values, options: null, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values and link options.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLink(HttpContext httpContext, object values, LinkOptions options)
|
public string GetLink(HttpContext httpContext, object values, LinkOptions options)
|
||||||
{
|
{
|
||||||
return GetLink(httpContext, routeName: null, values, options);
|
return GetLink(httpContext, routeName: null, values, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route values and link options.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLink(HttpContext httpContext, object values, LinkOptions options, out string link)
|
public bool TryGetLink(HttpContext httpContext, object values, LinkOptions options, out string link)
|
||||||
{
|
{
|
||||||
return TryGetLink(httpContext, routeName: null, values, options, out link);
|
return TryGetLink(httpContext, routeName: null, values, options, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route name and route values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLink(string routeName, object values)
|
public string GetLink(string routeName, object values)
|
||||||
{
|
{
|
||||||
return GetLink(httpContext: null, routeName, values, options: null);
|
return GetLink(httpContext: null, routeName, values, options: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route name and route values.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLink(string routeName, object values, out string link)
|
public bool TryGetLink(string routeName, object values, out string link)
|
||||||
{
|
{
|
||||||
return TryGetLink(httpContext: null, routeName, values, options: null, out link);
|
return TryGetLink(httpContext: null, routeName, values, options: null, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route name and route values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLink(string routeName, object values, LinkOptions options)
|
public string GetLink(string routeName, object values, LinkOptions options)
|
||||||
{
|
{
|
||||||
return GetLink(httpContext: null, routeName, values, options);
|
return GetLink(httpContext: null, routeName, values, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route name, route values and link options.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLink(string routeName, object values, LinkOptions options, out string link)
|
public bool TryGetLink(string routeName, object values, LinkOptions options, out string link)
|
||||||
{
|
{
|
||||||
return TryGetLink(httpContext: null, routeName, values, options, out link);
|
return TryGetLink(httpContext: null, routeName, values, options, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route name and route values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLink(HttpContext httpContext, string routeName, object values)
|
public string GetLink(HttpContext httpContext, string routeName, object values)
|
||||||
{
|
{
|
||||||
return GetLink(httpContext, routeName, values, options: null);
|
return GetLink(httpContext, routeName, values, options: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route name and route values.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLink(HttpContext httpContext, string routeName, object values, out string link)
|
public bool TryGetLink(HttpContext httpContext, string routeName, object values, out string link)
|
||||||
{
|
{
|
||||||
return TryGetLink(httpContext, routeName, values, options: null, out link);
|
return TryGetLink(httpContext, routeName, values, options: null, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route name, route values and link options.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLink(HttpContext httpContext, string routeName, object values, LinkOptions options)
|
public string GetLink(HttpContext httpContext, string routeName, object values, LinkOptions options)
|
||||||
{
|
{
|
||||||
if (TryGetLink(httpContext, routeName, values, options, out var link))
|
if (TryGetLink(httpContext, routeName, values, options, out var link))
|
||||||
|
|
@ -88,6 +201,16 @@ 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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified route name, route values and link options.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public abstract bool TryGetLink(
|
public abstract bool TryGetLink(
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
string routeName,
|
string routeName,
|
||||||
|
|
@ -95,51 +218,119 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
LinkOptions options,
|
LinkOptions options,
|
||||||
out string link);
|
out string link);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified lookup information and route values.
|
||||||
|
/// This lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for generating a URL.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLinkByAddress<TAddress>(TAddress address, object values)
|
public string GetLinkByAddress<TAddress>(TAddress address, object values)
|
||||||
{
|
{
|
||||||
return GetLinkByAddress(address, httpContext: null, values, options: null);
|
return GetLinkByAddress(httpContext: null, address, values, options: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified lookup information and route values.
|
||||||
|
/// This lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for generating a URL.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLinkByAddress<TAddress>(TAddress address, object values, out string link)
|
public bool TryGetLinkByAddress<TAddress>(TAddress address, object values, out string link)
|
||||||
{
|
{
|
||||||
return TryGetLinkByAddress(address, values, options: null, out link);
|
return TryGetLinkByAddress(address, values, options: null, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified lookup information, route values and link options.
|
||||||
|
/// This lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for generating a URL.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLinkByAddress<TAddress>(TAddress address, object values, LinkOptions options)
|
public string GetLinkByAddress<TAddress>(TAddress address, object values, LinkOptions options)
|
||||||
{
|
{
|
||||||
return GetLinkByAddress(address, httpContext: null, values, options);
|
return GetLinkByAddress(httpContext: null, address, values, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified lookup information, route values and link options.
|
||||||
|
/// This lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for generating a URL.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLinkByAddress<TAddress>(
|
public bool TryGetLinkByAddress<TAddress>(
|
||||||
TAddress address,
|
TAddress address,
|
||||||
object values,
|
object values,
|
||||||
LinkOptions options,
|
LinkOptions options,
|
||||||
out string link)
|
out string link)
|
||||||
{
|
{
|
||||||
return TryGetLinkByAddress(address, httpContext: null, values, options, out link);
|
return TryGetLinkByAddress(httpContext: null, address, values, options, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLinkByAddress<TAddress>(TAddress address, HttpContext httpContext, object values)
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified lookup information, route values and link options.
|
||||||
|
/// This lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for generating a URL.</param>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
|
public string GetLinkByAddress<TAddress>(HttpContext httpContext, TAddress address, object values)
|
||||||
{
|
{
|
||||||
return GetLinkByAddress(address, httpContext, values, options: null);
|
return GetLinkByAddress(httpContext, address, values, options: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified lookup information and route values.
|
||||||
|
/// This lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for generating a URL.</param>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public bool TryGetLinkByAddress<TAddress>(
|
public bool TryGetLinkByAddress<TAddress>(
|
||||||
TAddress address,
|
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
|
TAddress address,
|
||||||
object values,
|
object values,
|
||||||
out string link)
|
out string link)
|
||||||
{
|
{
|
||||||
return TryGetLinkByAddress(address, httpContext, values, options: null, out link);
|
return TryGetLinkByAddress(httpContext, address, values, options: null, out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified lookup information, route values and link options.
|
||||||
|
/// This lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for generating a URL.</param>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <returns>The generated URL.</returns>
|
||||||
public string GetLinkByAddress<TAddress>(
|
public string GetLinkByAddress<TAddress>(
|
||||||
TAddress address,
|
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
|
TAddress address,
|
||||||
object values,
|
object values,
|
||||||
LinkOptions options)
|
LinkOptions options)
|
||||||
{
|
{
|
||||||
if (TryGetLinkByAddress(address, httpContext, values, options, out var link))
|
if (TryGetLinkByAddress(httpContext, address, values, options, out var link))
|
||||||
{
|
{
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
@ -147,11 +338,126 @@ 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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a URL with an absolute path from the specified lookup information, route values and link options.
|
||||||
|
/// This lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// A return value indicates whether the operation succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for generating a URL.</param>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">An object that contains route values.</param>
|
||||||
|
/// <param name="options">The <see cref="LinkOptions"/>.</param>
|
||||||
|
/// <param name="link">The generated URL.</param>
|
||||||
|
/// <returns><c>true</c> if a URL was generated successfully; otherwise, <c>false</c>.</returns>
|
||||||
public abstract bool TryGetLinkByAddress<TAddress>(
|
public abstract bool TryGetLinkByAddress<TAddress>(
|
||||||
TAddress address,
|
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
|
TAddress address,
|
||||||
object values,
|
object values,
|
||||||
LinkOptions options,
|
LinkOptions options,
|
||||||
out string link);
|
out string link);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="LinkGenerationTemplate"/> to generate a URL from the specified route values.
|
||||||
|
/// This template object holds information of the endpoint(s) that were found and which can later be used to
|
||||||
|
/// generate a URL using the <see cref="LinkGenerationTemplate.MakeUrl(object, LinkOptions)"/> api.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">
|
||||||
|
/// An object that contains route values. These values are used to lookup endpoint(s).
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If an endpoint(s) was found successfully, then this returns a template object representing that,
|
||||||
|
/// <c>null</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public LinkGenerationTemplate GetTemplate(object values)
|
||||||
|
{
|
||||||
|
return GetTemplate(httpContext: null, routeName: null, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="LinkGenerationTemplate"/> to generate a URL from the specified route name and route values.
|
||||||
|
/// This template object holds information of the endpoint(s) that were found and which can later be used to
|
||||||
|
/// generate a URL using the <see cref="LinkGenerationTemplate.MakeUrl(object, LinkOptions)"/> api.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="values">
|
||||||
|
/// An object that contains route values. These values are used to lookup for endpoint(s).
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If an endpoint(s) was found successfully, then this returns a template object representing that,
|
||||||
|
/// <c>null</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public LinkGenerationTemplate GetTemplate(string routeName, object values)
|
||||||
|
{
|
||||||
|
return GetTemplate(httpContext: null, routeName, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="LinkGenerationTemplate"/> to generate a URL from the specified route values.
|
||||||
|
/// This template object holds information of the endpoint(s) that were found and which can later be used to
|
||||||
|
/// generate a URL using the <see cref="LinkGenerationTemplate.MakeUrl(object, LinkOptions)"/> api.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="values">
|
||||||
|
/// An object that contains route values. These values are used to lookup for endpoint(s).
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If an endpoint(s) was found successfully, then this returns a template object representing that,
|
||||||
|
/// <c>null</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public LinkGenerationTemplate GetTemplate(HttpContext httpContext, object values)
|
||||||
|
{
|
||||||
|
return GetTemplate(httpContext, routeName: null, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="LinkGenerationTemplate"/> to generate a URL from the specified route name and route values.
|
||||||
|
/// This template object holds information of the endpoint(s) that were found and which can later be used to
|
||||||
|
/// generate a URL using the <see cref="LinkGenerationTemplate.MakeUrl(object, LinkOptions)"/> api.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <param name="routeName">The name of the route to generate the URL to.</param>
|
||||||
|
/// <param name="values">
|
||||||
|
/// An object that contains route values. These values are used to lookup for endpoint(s).
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If an endpoint(s) was found successfully, then this returns a template object representing that,
|
||||||
|
/// <c>null</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public abstract LinkGenerationTemplate GetTemplate(HttpContext httpContext, string routeName, object values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="LinkGenerationTemplate"/> to generate a URL from the specified lookup information.
|
||||||
|
/// This template object holds information of the endpoint(s) that were found and which can later be used to
|
||||||
|
/// generate a URL using the <see cref="LinkGenerationTemplate.MakeUrl(object, LinkOptions)"/> api.
|
||||||
|
/// The lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for creating a template.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If an endpoint(s) was found successfully, then this returns a template object representing that,
|
||||||
|
/// <c>null</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public LinkGenerationTemplate GetTemplateByAddress<TAddress>(TAddress address)
|
||||||
|
{
|
||||||
|
return GetTemplateByAddress(httpContext: null, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="LinkGenerationTemplate"/> to generate a URL from the specified lookup information.
|
||||||
|
/// This template object holds information of the endpoint(s) that were found and which can later be used to
|
||||||
|
/// generate a URL using the <see cref="LinkGenerationTemplate.MakeUrl(object, LinkOptions)"/> api.
|
||||||
|
/// The lookup information is used to find endpoints using a registered 'IEndpointFinder<TAddress>'.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
|
/// <param name="address">The information used to look up endpoints for creating a template.</param>
|
||||||
|
/// <param name="httpContext">The <see cref="HttpContext"/> associated with current request.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If an endpoint(s) was found successfully, then this returns a template object representing that,
|
||||||
|
/// <c>null</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public abstract LinkGenerationTemplate GetTemplateByAddress<TAddress>(
|
||||||
|
HttpContext httpContext,
|
||||||
|
TAddress address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
// 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 Microsoft.AspNetCore.Routing.Matching;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Routing
|
||||||
|
{
|
||||||
|
internal class DefaultLinkGenerationTemplate : LinkGenerationTemplate
|
||||||
|
{
|
||||||
|
public DefaultLinkGenerationTemplate(
|
||||||
|
DefaultLinkGenerator linkGenerator,
|
||||||
|
IEnumerable<MatcherEndpoint> endpoints,
|
||||||
|
HttpContext httpContext,
|
||||||
|
RouteValueDictionary explicitValues,
|
||||||
|
RouteValueDictionary ambientValues)
|
||||||
|
{
|
||||||
|
LinkGenerator = linkGenerator;
|
||||||
|
Endpoints = endpoints;
|
||||||
|
HttpContext = httpContext;
|
||||||
|
EarlierExplicitValues = explicitValues;
|
||||||
|
AmbientValues = ambientValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DefaultLinkGenerator LinkGenerator { get; }
|
||||||
|
|
||||||
|
internal IEnumerable<MatcherEndpoint> Endpoints { get; }
|
||||||
|
|
||||||
|
internal HttpContext HttpContext { get; }
|
||||||
|
|
||||||
|
internal RouteValueDictionary EarlierExplicitValues { get; }
|
||||||
|
|
||||||
|
internal RouteValueDictionary AmbientValues { get; }
|
||||||
|
|
||||||
|
public override string MakeUrl(object values, LinkOptions options)
|
||||||
|
{
|
||||||
|
var currentValues = new RouteValueDictionary(values);
|
||||||
|
var mergedValuesDictionary = new RouteValueDictionary(EarlierExplicitValues);
|
||||||
|
|
||||||
|
foreach (var kvp in currentValues)
|
||||||
|
{
|
||||||
|
mergedValuesDictionary[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var endpoint in Endpoints)
|
||||||
|
{
|
||||||
|
var link = LinkGenerator.MakeLink(
|
||||||
|
HttpContext,
|
||||||
|
endpoint,
|
||||||
|
AmbientValues,
|
||||||
|
mergedValuesDictionary,
|
||||||
|
options);
|
||||||
|
if (link != null)
|
||||||
|
{
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// 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.Linq;
|
using System.Linq;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
@ -54,21 +55,78 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool TryGetLinkByAddress<TAddress>(
|
public override bool TryGetLinkByAddress<TAddress>(
|
||||||
TAddress address,
|
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
|
TAddress address,
|
||||||
object values,
|
object values,
|
||||||
LinkOptions options,
|
LinkOptions options,
|
||||||
out string link)
|
out string link)
|
||||||
{
|
{
|
||||||
return TryGetLinkByAddressInternal(
|
return TryGetLinkByAddressInternal(
|
||||||
address,
|
|
||||||
httpContext,
|
httpContext,
|
||||||
|
address,
|
||||||
explicitValues: values,
|
explicitValues: values,
|
||||||
ambientValues: GetAmbientValues(httpContext),
|
ambientValues: GetAmbientValues(httpContext),
|
||||||
options,
|
options,
|
||||||
out link);
|
out link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override LinkGenerationTemplate GetTemplate(HttpContext httpContext, string routeName, object values)
|
||||||
|
{
|
||||||
|
var ambientValues = GetAmbientValues(httpContext);
|
||||||
|
var explicitValues = new RouteValueDictionary(values);
|
||||||
|
|
||||||
|
return GetTemplateInternal(
|
||||||
|
httpContext,
|
||||||
|
new RouteValuesAddress
|
||||||
|
{
|
||||||
|
RouteName = routeName,
|
||||||
|
ExplicitValues = explicitValues,
|
||||||
|
AmbientValues = ambientValues
|
||||||
|
},
|
||||||
|
ambientValues,
|
||||||
|
explicitValues,
|
||||||
|
values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override LinkGenerationTemplate GetTemplateByAddress<TAddress>(
|
||||||
|
HttpContext httpContext,
|
||||||
|
TAddress address)
|
||||||
|
{
|
||||||
|
return GetTemplateInternal(httpContext, address, values: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string MakeLink(
|
||||||
|
HttpContext httpContext,
|
||||||
|
MatcherEndpoint endpoint,
|
||||||
|
RouteValueDictionary ambientValues,
|
||||||
|
RouteValueDictionary explicitValues,
|
||||||
|
LinkOptions options)
|
||||||
|
{
|
||||||
|
var templateBinder = new TemplateBinder(
|
||||||
|
UrlEncoder.Default,
|
||||||
|
_uriBuildingContextPool,
|
||||||
|
new RouteTemplate(endpoint.RoutePattern),
|
||||||
|
new RouteValueDictionary(endpoint.RoutePattern.Defaults));
|
||||||
|
|
||||||
|
var templateValuesResult = templateBinder.GetValues(
|
||||||
|
ambientValues: ambientValues,
|
||||||
|
explicitValues: explicitValues,
|
||||||
|
requiredKeys: endpoint.RequiredValues.Keys);
|
||||||
|
if (templateValuesResult == null)
|
||||||
|
{
|
||||||
|
// We're missing one of the required values for this route.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MatchesConstraints(httpContext, endpoint, templateValuesResult.CombinedValues))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = templateBinder.BindValues(templateValuesResult.AcceptedValues);
|
||||||
|
return Normalize(url, options);
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryGetLinkByRouteValues(
|
private bool TryGetLinkByRouteValues(
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
string routeName,
|
string routeName,
|
||||||
|
|
@ -86,8 +144,8 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
};
|
};
|
||||||
|
|
||||||
return TryGetLinkByAddressInternal(
|
return TryGetLinkByAddressInternal(
|
||||||
address,
|
|
||||||
httpContext,
|
httpContext,
|
||||||
|
address,
|
||||||
explicitValues: values,
|
explicitValues: values,
|
||||||
ambientValues: ambientValues,
|
ambientValues: ambientValues,
|
||||||
options,
|
options,
|
||||||
|
|
@ -95,8 +153,8 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetLinkByAddressInternal<TAddress>(
|
private bool TryGetLinkByAddressInternal<TAddress>(
|
||||||
TAddress address,
|
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
|
TAddress address,
|
||||||
object explicitValues,
|
object explicitValues,
|
||||||
RouteValueDictionary ambientValues,
|
RouteValueDictionary ambientValues,
|
||||||
LinkOptions options,
|
LinkOptions options,
|
||||||
|
|
@ -104,22 +162,21 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
link = null;
|
link = null;
|
||||||
|
|
||||||
var endpointFinder = _serviceProvider.GetRequiredService<IEndpointFinder<TAddress>>();
|
var endpoints = FindEndpoints(address);
|
||||||
var endpoints = endpointFinder.FindEndpoints(address);
|
|
||||||
if (endpoints == null)
|
if (endpoints == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matcherEndpoints = endpoints.OfType<MatcherEndpoint>();
|
foreach (var endpoint in endpoints)
|
||||||
if (!matcherEndpoints.Any())
|
|
||||||
{
|
{
|
||||||
return false;
|
link = MakeLink(
|
||||||
}
|
httpContext,
|
||||||
|
endpoint,
|
||||||
|
ambientValues,
|
||||||
|
new RouteValueDictionary(explicitValues),
|
||||||
|
options);
|
||||||
|
|
||||||
foreach (var endpoint in matcherEndpoints)
|
|
||||||
{
|
|
||||||
link = GetLink(endpoint);
|
|
||||||
if (link != null)
|
if (link != null)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -127,33 +184,49 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
string GetLink(MatcherEndpoint endpoint)
|
private LinkGenerationTemplate GetTemplateInternal<TAddress>(
|
||||||
|
HttpContext httpContext,
|
||||||
|
TAddress address,
|
||||||
|
object values)
|
||||||
|
{
|
||||||
|
var endpoints = FindEndpoints(address);
|
||||||
|
if (endpoints == null)
|
||||||
{
|
{
|
||||||
var templateBinder = new TemplateBinder(
|
return null;
|
||||||
UrlEncoder.Default,
|
|
||||||
_uriBuildingContextPool,
|
|
||||||
new RouteTemplate(endpoint.RoutePattern),
|
|
||||||
new RouteValueDictionary(endpoint.RoutePattern.Defaults));
|
|
||||||
|
|
||||||
var templateValuesResult = templateBinder.GetValues(
|
|
||||||
ambientValues: ambientValues,
|
|
||||||
explicitValues: new RouteValueDictionary(explicitValues),
|
|
||||||
requiredKeys: endpoint.RequiredValues.Keys);
|
|
||||||
if (templateValuesResult == null)
|
|
||||||
{
|
|
||||||
// We're missing one of the required values for this route.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MatchesConstraints(httpContext, endpoint, templateValuesResult.CombinedValues))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = templateBinder.BindValues(templateValuesResult.AcceptedValues);
|
|
||||||
return Normalize(url, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ambientValues = GetAmbientValues(httpContext);
|
||||||
|
var explicitValues = new RouteValueDictionary(values);
|
||||||
|
|
||||||
|
return new DefaultLinkGenerationTemplate(
|
||||||
|
this,
|
||||||
|
endpoints,
|
||||||
|
httpContext,
|
||||||
|
explicitValues,
|
||||||
|
ambientValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LinkGenerationTemplate GetTemplateInternal<TAddress>(
|
||||||
|
HttpContext httpContext,
|
||||||
|
TAddress address,
|
||||||
|
RouteValueDictionary ambientValues,
|
||||||
|
RouteValueDictionary explicitValues,
|
||||||
|
object values)
|
||||||
|
{
|
||||||
|
var endpoints = FindEndpoints(address);
|
||||||
|
if (endpoints == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DefaultLinkGenerationTemplate(
|
||||||
|
this,
|
||||||
|
endpoints,
|
||||||
|
httpContext,
|
||||||
|
explicitValues,
|
||||||
|
ambientValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool MatchesConstraints(
|
private bool MatchesConstraints(
|
||||||
|
|
@ -234,7 +307,25 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
return feature.Values;
|
return feature.Values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return new RouteValueDictionary();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<MatcherEndpoint> FindEndpoints<TAddress>(TAddress address)
|
||||||
|
{
|
||||||
|
var finder = _serviceProvider.GetRequiredService<IEndpointFinder<TAddress>>();
|
||||||
|
var endpoints = finder.FindEndpoints(address);
|
||||||
|
if (endpoints == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var matcherEndpoints = endpoints.OfType<MatcherEndpoint>();
|
||||||
|
if (!matcherEndpoints.Any())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matcherEndpoints;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,17 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing
|
namespace Microsoft.AspNetCore.Routing
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines a contract to find endpoints based on the supplied lookup information.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TAddress">The address type to look up endpoints.</typeparam>
|
||||||
public interface IEndpointFinder<TAddress>
|
public interface IEndpointFinder<TAddress>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Finds endpoints based on the supplied lookup information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">The information used to look up endpoints.</param>
|
||||||
|
/// <returns>A collection of <see cref="Endpoint"/>.</returns>
|
||||||
IEnumerable<Endpoint> FindEndpoints(TAddress address);
|
IEnumerable<Endpoint> FindEndpoints(TAddress address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1217,7 +1217,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TryGetLink_WithCustomAddress_CanGenerateLink()
|
public void TryGetLinkByAddress_WithCustomAddress_CanGenerateLink()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var services = GetBasicServices();
|
var services = GetBasicServices();
|
||||||
|
|
@ -1237,8 +1237,8 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var canGenerateLink = linkGenerator.TryGetLinkByAddress<INameMetadata>(
|
var canGenerateLink = linkGenerator.TryGetLinkByAddress<INameMetadata>(
|
||||||
address: new NameMetadata("CustomerDetails"),
|
|
||||||
httpContext,
|
httpContext,
|
||||||
|
address: new NameMetadata("CustomerDetails"),
|
||||||
values: new { id = 10 },
|
values: new { id = 10 },
|
||||||
out var link);
|
out var link);
|
||||||
|
|
||||||
|
|
@ -1248,7 +1248,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TryGetLink_WithCustomAddress_CanGenerateLink_RespectsLinkOptions_SuppliedAtCallSite()
|
public void TryGetLinkByAddress_WithCustomAddress_CanGenerateLink_RespectsLinkOptions_SuppliedAtCallSite()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var services = GetBasicServices();
|
var services = GetBasicServices();
|
||||||
|
|
@ -1268,8 +1268,8 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var canGenerateLink = linkGenerator.TryGetLinkByAddress<INameMetadata>(
|
var canGenerateLink = linkGenerator.TryGetLinkByAddress<INameMetadata>(
|
||||||
address: new NameMetadata("CustomerDetails"),
|
|
||||||
httpContext,
|
httpContext,
|
||||||
|
address: new NameMetadata("CustomerDetails"),
|
||||||
values: new { id = 10 },
|
values: new { id = 10 },
|
||||||
new LinkOptions
|
new LinkOptions
|
||||||
{
|
{
|
||||||
|
|
@ -1282,6 +1282,177 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
Assert.Equal("/customers/details/10", link);
|
Assert.Equal("/customers/details/10", link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTemplate_ByRouteValues_ReturnsTemplate()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var endpoint1 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Product/Edit/{id}",
|
||||||
|
requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null });
|
||||||
|
var linkGenerator = CreateLinkGenerator(endpoint1);
|
||||||
|
var values = new RouteValueDictionary(new { controller = "Product", action = "Edit" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var template = linkGenerator.GetTemplate(values);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var defaultTemplate = Assert.IsType<DefaultLinkGenerationTemplate>(template);
|
||||||
|
Assert.Same(linkGenerator, defaultTemplate.LinkGenerator);
|
||||||
|
Assert.Equal(new[] { endpoint1 }, defaultTemplate.Endpoints);
|
||||||
|
Assert.Equal(values, defaultTemplate.EarlierExplicitValues);
|
||||||
|
Assert.Null(defaultTemplate.HttpContext);
|
||||||
|
Assert.Empty(defaultTemplate.AmbientValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTemplate_ByRouteName_ReturnsTemplate()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var endpoint1 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Product/Edit/{id}",
|
||||||
|
requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
metadata: new RouteNameMetadata("EditProduct"));
|
||||||
|
var linkGenerator = CreateLinkGenerator(endpoint1);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var template = linkGenerator.GetTemplate("EditProduct", values: new { });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var defaultTemplate = Assert.IsType<DefaultLinkGenerationTemplate>(template);
|
||||||
|
Assert.Same(linkGenerator, defaultTemplate.LinkGenerator);
|
||||||
|
Assert.Equal(new[] { endpoint1 }, defaultTemplate.Endpoints);
|
||||||
|
Assert.Empty(defaultTemplate.EarlierExplicitValues);
|
||||||
|
Assert.Null(defaultTemplate.HttpContext);
|
||||||
|
Assert.Empty(defaultTemplate.AmbientValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTemplate_ByRouteName_ReturnsTemplate_WithMultipleEndpoints()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var endpoint1 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Product/Edit/{id}",
|
||||||
|
requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
metadata: new RouteNameMetadata("default"));
|
||||||
|
var endpoint2 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Product/Details/{id}",
|
||||||
|
requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
metadata: new RouteNameMetadata("default"));
|
||||||
|
var linkGenerator = CreateLinkGenerator(endpoint1, endpoint2);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var template = linkGenerator.GetTemplate("default", values: new { });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var defaultTemplate = Assert.IsType<DefaultLinkGenerationTemplate>(template);
|
||||||
|
Assert.Same(linkGenerator, defaultTemplate.LinkGenerator);
|
||||||
|
Assert.Equal(new[] { endpoint1, endpoint2 }, defaultTemplate.Endpoints);
|
||||||
|
Assert.Empty(defaultTemplate.EarlierExplicitValues);
|
||||||
|
Assert.Null(defaultTemplate.HttpContext);
|
||||||
|
Assert.Empty(defaultTemplate.AmbientValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTemplateByAddress_ByCustomAddress_ReturnsTemplate()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = GetBasicServices();
|
||||||
|
services.TryAddEnumerable(
|
||||||
|
ServiceDescriptor.Singleton<IEndpointFinder<INameMetadata>, EndpointFinderByName>());
|
||||||
|
var endpoint1 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Product/Edit/{id}",
|
||||||
|
requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null });
|
||||||
|
var endpoint2 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Customers/Details/{id}",
|
||||||
|
requiredValues: new { controller = "Customers", action = "Details" },
|
||||||
|
defaults: new { controller = "Customers", action = "Details" },
|
||||||
|
metadata: new NameMetadata("CustomerDetails"));
|
||||||
|
var linkGenerator = CreateLinkGenerator(new[] { endpoint1, endpoint2 }, new RouteOptions(), services);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var template = linkGenerator.GetTemplateByAddress<INameMetadata>(new NameMetadata("CustomerDetails"));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var defaultTemplate = Assert.IsType<DefaultLinkGenerationTemplate>(template);
|
||||||
|
Assert.Same(linkGenerator, defaultTemplate.LinkGenerator);
|
||||||
|
Assert.Equal(new[] { endpoint2 }, defaultTemplate.Endpoints);
|
||||||
|
Assert.Empty(defaultTemplate.EarlierExplicitValues);
|
||||||
|
Assert.Null(defaultTemplate.HttpContext);
|
||||||
|
Assert.Empty(defaultTemplate.AmbientValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MakeUrl_Honors_LinkOptions()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = GetBasicServices();
|
||||||
|
services.TryAddEnumerable(
|
||||||
|
ServiceDescriptor.Singleton<IEndpointFinder<INameMetadata>, EndpointFinderByName>());
|
||||||
|
var endpoint1 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Product/Edit/{id}",
|
||||||
|
requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null });
|
||||||
|
var endpoint2 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Customers/Details/{id}",
|
||||||
|
requiredValues: new { controller = "Customers", action = "Details" },
|
||||||
|
defaults: new { controller = "Customers", action = "Details" },
|
||||||
|
metadata: new NameMetadata("CustomerDetails"));
|
||||||
|
var linkGenerator = CreateLinkGenerator(new[] { endpoint1, endpoint2 }, new RouteOptions(), services);
|
||||||
|
|
||||||
|
// Act1
|
||||||
|
var template = linkGenerator.GetTemplateByAddress<INameMetadata>(new NameMetadata("CustomerDetails"));
|
||||||
|
|
||||||
|
// Assert1
|
||||||
|
Assert.NotNull(template);
|
||||||
|
|
||||||
|
// Act2
|
||||||
|
var link = template.MakeUrl(new { id = 10 }, new LinkOptions { LowercaseUrls = true });
|
||||||
|
|
||||||
|
// Assert2
|
||||||
|
Assert.Equal("/customers/details/10", link);
|
||||||
|
|
||||||
|
// Act3
|
||||||
|
link = template.MakeUrl(new { id = 25 });
|
||||||
|
|
||||||
|
// Assert3
|
||||||
|
Assert.Equal("/Customers/Details/25", link);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MakeUrl_GeneratesLink_WithExtraRouteValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var endpoint1 = EndpointFactory.CreateMatcherEndpoint(
|
||||||
|
"Product/Edit/{id}",
|
||||||
|
requiredValues: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null },
|
||||||
|
defaults: new { controller = "Product", action = "Edit", area = (string)null, page = (string)null });
|
||||||
|
var linkGenerator = CreateLinkGenerator(endpoint1);
|
||||||
|
|
||||||
|
// Act1
|
||||||
|
var template = linkGenerator.GetTemplate(
|
||||||
|
values: new { controller = "Product", action = "Edit", foo = "bar" });
|
||||||
|
|
||||||
|
// Assert1
|
||||||
|
Assert.NotNull(template);
|
||||||
|
|
||||||
|
// Act2
|
||||||
|
var link = template.MakeUrl(new { id = 10 });
|
||||||
|
|
||||||
|
// Assert2
|
||||||
|
Assert.Equal("/Product/Edit/10?foo=bar", link);
|
||||||
|
|
||||||
|
// Act3
|
||||||
|
link = template.MakeUrl(new { id = 25, foo = "boo" });
|
||||||
|
|
||||||
|
// Assert3
|
||||||
|
Assert.Equal("/Product/Edit/25?foo=boo", link);
|
||||||
|
}
|
||||||
|
|
||||||
private LinkGenerator CreateLinkGenerator(params Endpoint[] endpoints)
|
private LinkGenerator CreateLinkGenerator(params Endpoint[] endpoints)
|
||||||
{
|
{
|
||||||
return CreateLinkGenerator(endpoints, routeOptions: null);
|
return CreateLinkGenerator(endpoints, routeOptions: null);
|
||||||
|
|
@ -1365,5 +1536,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class RouteNameMetadata : IRouteNameMetadata
|
||||||
|
{
|
||||||
|
public RouteNameMetadata(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
public string Name { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue