11// Copyright (c) .NET Foundation. All rights reserved.
22// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33
4+ using System . Collections . Generic ;
45using System . Threading . Tasks ;
56using Microsoft . AspNetCore . Http ;
67using Microsoft . AspNetCore . Routing ;
@@ -20,23 +21,73 @@ namespace Microsoft.AspNetCore.Mvc.Routing
2021 /// <para>
2122 /// The route values returned from a <see cref="TransformAsync(HttpContext, RouteValueDictionary)"/> implementation
2223 /// will be used to select an action based on matching of the route values. All actions that match the route values
23- /// will be considered as candidates, and may be further disambiguated by <see cref="IEndpointSelectorPolicy" />
24- /// implementations such as <see cref="HttpMethodMatcherPolicy" />.
24+ /// will be considered as candidates, and may be further disambiguated by
25+ /// <see cref="FilterAsync(HttpContext, RouteValueDictionary, IReadOnlyList{Endpoint})" /> as well as
26+ /// <see cref="IEndpointSelectorPolicy" /> implementations such as <see cref="HttpMethodMatcherPolicy" />.
27+ /// </para>
28+ /// <para>
29+ /// Operations on a <see cref="DynamicRouteValueTransformer" /> instance will be called for each dynamic endpoint
30+ /// in the following sequence:
31+ ///
32+ /// <list type="bullet">
33+ /// <item><description><see cref="State" /> is set</description></item>
34+ /// <item><description><see cref="TransformAsync(HttpContext, RouteValueDictionary)"/></description></item>
35+ /// <item><description><see cref="FilterAsync(HttpContext, RouteValueDictionary, IReadOnlyList{Endpoint})" /></description></item>
36+ /// </list>
37+ ///
38+ /// Implementations that are registered with the service collection as transient may safely use class
39+ /// members to persist state across these operations.
2540 /// </para>
2641 /// <para>
2742 /// Implementations <see cref="DynamicRouteValueTransformer" /> should be registered with the service
2843 /// collection as type <see cref="DynamicRouteValueTransformer" />. Implementations can use any service
29- /// lifetime.
44+ /// lifetime. Implementations that make use of <see cref="State" /> must be registered as transient.
3045 /// </para>
3146 /// </remarks>
3247 public abstract class DynamicRouteValueTransformer
3348 {
49+ /// <summary>
50+ /// Gets or sets a state value. An arbitrary value passed to the transformer from where it was registered.
51+ /// </summary>
52+ /// <remarks>
53+ /// Implementations that make use of <see cref="State" /> must be registered as transient with the service
54+ /// collection.
55+ /// </remarks>
56+ public object State { get ; set ; }
57+
3458 /// <summary>
3559 /// Creates a set of transformed route values that will be used to select an action.
3660 /// </summary>
3761 /// <param name="httpContext">The <see cref="HttpContext" /> associated with the current request.</param>
3862 /// <param name="values">The route values associated with the current match. Implementations should not modify <paramref name="values"/>.</param>
3963 /// <returns>A task which asynchronously returns a set of route values.</returns>
4064 public abstract ValueTask < RouteValueDictionary > TransformAsync ( HttpContext httpContext , RouteValueDictionary values ) ;
65+
66+ /// <summary>
67+ /// Filters the set of endpoints that were chosen as a result of lookup based on the route values returned by
68+ /// <see cref="TransformAsync(HttpContext, RouteValueDictionary)" />.
69+ /// </summary>
70+ /// <param name="httpContext">The <see cref="HttpContext" /> associated with the current request.</param>
71+ /// <param name="values">The route values returned from <see cref="TransformAsync(HttpContext, RouteValueDictionary)" />.</param>
72+ /// <param name="endpoints">
73+ /// The endpoints that were chosen as a result of lookup based on the route values returned by
74+ /// <see cref="TransformAsync(HttpContext, RouteValueDictionary)" />.
75+ /// </param>
76+ /// <returns>Asynchronously returns a list of endpoints to apply to the matches collection.</returns>
77+ /// <remarks>
78+ /// <para>
79+ /// Implementations of <see cref="FilterAsync(HttpContext, RouteValueDictionary, IReadOnlyList{Endpoint})" /> may further
80+ /// refine the list of endpoints chosen based on route value matching by returning a new list of endpoints based on
81+ /// <paramref name="endpoints" />.
82+ /// </para>
83+ /// <para>
84+ /// <see cref="FilterAsync(HttpContext, RouteValueDictionary, IReadOnlyList{Endpoint})" /> will not be called in the case
85+ /// where zero endpoints were matched based on route values.
86+ /// </para>
87+ /// </remarks>
88+ public virtual ValueTask < IReadOnlyList < Endpoint > > FilterAsync ( HttpContext httpContext , RouteValueDictionary values , IReadOnlyList < Endpoint > endpoints )
89+ {
90+ return new ValueTask < IReadOnlyList < Endpoint > > ( endpoints ) ;
91+ }
4192 }
4293}
0 commit comments