Remove Routing pubternal
This change makes a bunch of random routing classes internal instead of pubternal. Most of these have no use case and aren't valuable at all outside of routing code. The one exception here is that the only way to construct a `TemplateBinder` in 1.0-2.2 is using a constructor that accepts some pubternal types. I don't think it's a good idea to just yank this since the usage is pretty wide. Instead I added a factory service so you can create this, and marked the constructor [Obsolete] where these types are touched. We can make the actual breaking change in the next major release.
This commit is contained in:
parent
d2db4677c9
commit
763720b092
|
|
@ -491,71 +491,19 @@ namespace Microsoft.AspNetCore.Routing.Constraints
|
|||
}
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
{
|
||||
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
public readonly partial struct BufferValue
|
||||
{
|
||||
private readonly object _dummy;
|
||||
private readonly int _dummyPrimitive;
|
||||
public BufferValue(string value, bool requiresEncoding) { throw null; }
|
||||
public bool RequiresEncoding { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public string Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
public partial class DfaGraphWriter
|
||||
{
|
||||
public DfaGraphWriter(System.IServiceProvider services) { }
|
||||
public void Write(Microsoft.AspNetCore.Routing.EndpointDataSource dataSource, System.IO.TextWriter writer) { }
|
||||
}
|
||||
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplayString,nq}")]
|
||||
public partial class LinkGenerationDecisionTree
|
||||
{
|
||||
public LinkGenerationDecisionTree(System.Collections.Generic.IReadOnlyList<Microsoft.AspNetCore.Routing.Tree.OutboundMatch> entries) { }
|
||||
public System.Collections.Generic.IList<Microsoft.AspNetCore.Routing.Internal.OutboundMatchResult> GetMatches(Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteValueDictionary ambientValues) { throw null; }
|
||||
}
|
||||
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
public readonly partial struct OutboundMatchResult
|
||||
{
|
||||
private readonly object _dummy;
|
||||
private readonly int _dummyPrimitive;
|
||||
public OutboundMatchResult(Microsoft.AspNetCore.Routing.Tree.OutboundMatch match, bool isFallbackMatch) { throw null; }
|
||||
public bool IsFallbackMatch { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public Microsoft.AspNetCore.Routing.Tree.OutboundMatch Match { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
public partial struct PathTokenizer : System.Collections.Generic.IEnumerable<Microsoft.Extensions.Primitives.StringSegment>, System.Collections.Generic.IReadOnlyCollection<Microsoft.Extensions.Primitives.StringSegment>, System.Collections.Generic.IReadOnlyList<Microsoft.Extensions.Primitives.StringSegment>, System.Collections.IEnumerable
|
||||
{
|
||||
private object _dummy;
|
||||
private int _dummyPrimitive;
|
||||
public PathTokenizer(Microsoft.AspNetCore.Http.PathString path) { throw null; }
|
||||
public int Count { get { throw null; } }
|
||||
public Microsoft.Extensions.Primitives.StringSegment this[int index] { get { throw null; } }
|
||||
public Microsoft.AspNetCore.Routing.Internal.PathTokenizer.Enumerator GetEnumerator() { throw null; }
|
||||
System.Collections.Generic.IEnumerator<Microsoft.Extensions.Primitives.StringSegment> System.Collections.Generic.IEnumerable<Microsoft.Extensions.Primitives.StringSegment>.GetEnumerator() { throw null; }
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
|
||||
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
public partial struct Enumerator : System.Collections.Generic.IEnumerator<Microsoft.Extensions.Primitives.StringSegment>, System.Collections.IEnumerator, System.IDisposable
|
||||
{
|
||||
private object _dummy;
|
||||
private int _dummyPrimitive;
|
||||
public Enumerator(Microsoft.AspNetCore.Routing.Internal.PathTokenizer tokenizer) { throw null; }
|
||||
public Microsoft.Extensions.Primitives.StringSegment Current { get { throw null; } }
|
||||
object System.Collections.IEnumerator.Current { get { throw null; } }
|
||||
public void Dispose() { }
|
||||
public bool MoveNext() { throw null; }
|
||||
public void Reset() { }
|
||||
}
|
||||
}
|
||||
[System.ObsoleteAttribute("This type will be marked as internal in a future release.")]
|
||||
public enum SegmentState
|
||||
{
|
||||
Beginning = 0,
|
||||
Inside = 1,
|
||||
}
|
||||
public partial class UriBuilderContextPooledObjectPolicy : Microsoft.Extensions.ObjectPool.IPooledObjectPolicy<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext>
|
||||
{
|
||||
public UriBuilderContextPooledObjectPolicy() { }
|
||||
public Microsoft.AspNetCore.Routing.Internal.UriBuildingContext Create() { throw null; }
|
||||
public bool Return(Microsoft.AspNetCore.Routing.Internal.UriBuildingContext obj) { throw null; }
|
||||
}
|
||||
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerToString(),nq}")]
|
||||
[System.ObsoleteAttribute("This type will be marked as internal in a future release.")]
|
||||
public partial class UriBuildingContext
|
||||
{
|
||||
public UriBuildingContext(System.Text.Encodings.Web.UrlEncoder urlEncoder) { }
|
||||
|
|
@ -808,13 +756,21 @@ namespace Microsoft.AspNetCore.Routing.Template
|
|||
}
|
||||
public partial class TemplateBinder
|
||||
{
|
||||
[System.ObsoleteAttribute("This constructor is obsolete and will be marked internal in a future release. Use the TemplateBinderFactory service to create TemplateBinder instances.")]
|
||||
public TemplateBinder(System.Text.Encodings.Web.UrlEncoder urlEncoder, Microsoft.Extensions.ObjectPool.ObjectPool<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext> pool, Microsoft.AspNetCore.Routing.Patterns.RoutePattern pattern, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults, System.Collections.Generic.IEnumerable<string> requiredKeys, System.Collections.Generic.IEnumerable<System.ValueTuple<string, Microsoft.AspNetCore.Routing.IParameterPolicy>> parameterPolicies) { }
|
||||
[System.ObsoleteAttribute("This constructor is obsolete and will be marked internal in a furture release. Use the TemplateBinderFactory service to create TemplateBinder instances.")]
|
||||
public TemplateBinder(System.Text.Encodings.Web.UrlEncoder urlEncoder, Microsoft.Extensions.ObjectPool.ObjectPool<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext> pool, Microsoft.AspNetCore.Routing.Template.RouteTemplate template, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults) { }
|
||||
public string BindValues(Microsoft.AspNetCore.Routing.RouteValueDictionary acceptedValues) { throw null; }
|
||||
public Microsoft.AspNetCore.Routing.Template.TemplateValuesResult GetValues(Microsoft.AspNetCore.Routing.RouteValueDictionary ambientValues, Microsoft.AspNetCore.Routing.RouteValueDictionary values) { throw null; }
|
||||
public static bool RoutePartsEqual(object a, object b) { throw null; }
|
||||
public bool TryProcessConstraints(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.RouteValueDictionary combinedValues, out string parameterName, out Microsoft.AspNetCore.Routing.IRouteConstraint constraint) { throw null; }
|
||||
}
|
||||
public abstract partial class TemplateBinderFactory
|
||||
{
|
||||
protected TemplateBinderFactory() { }
|
||||
public abstract Microsoft.AspNetCore.Routing.Template.TemplateBinder Create(Microsoft.AspNetCore.Routing.Patterns.RoutePattern pattern);
|
||||
public abstract Microsoft.AspNetCore.Routing.Template.TemplateBinder Create(Microsoft.AspNetCore.Routing.Template.RouteTemplate template, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults);
|
||||
}
|
||||
public partial class TemplateMatcher
|
||||
{
|
||||
public TemplateMatcher(Microsoft.AspNetCore.Routing.Template.RouteTemplate template, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults) { }
|
||||
|
|
@ -901,6 +857,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
}
|
||||
public partial class TreeRouteBuilder
|
||||
{
|
||||
[System.ObsoleteAttribute("This constructor will be marked internal in a future release. Use the service provider to create instances of TreeRouteBuilder.")]
|
||||
public TreeRouteBuilder(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.ObjectPool.ObjectPool<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext> objectPool, Microsoft.AspNetCore.Routing.IInlineConstraintResolver constraintResolver) { }
|
||||
public System.Collections.Generic.IList<Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry> InboundEntries { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public System.Collections.Generic.IList<Microsoft.AspNetCore.Routing.Tree.OutboundRouteEntry> OutboundEntries { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
|
|
@ -913,6 +870,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
public partial class TreeRouter : Microsoft.AspNetCore.Routing.IRouter
|
||||
{
|
||||
public static readonly string RouteGroupKey;
|
||||
[System.ObsoleteAttribute("This constructor will be marked obsolete in a future release. Use the TreeRouterBuilder to create instances of TreeRouter.")]
|
||||
public TreeRouter(Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[] trees, System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Routing.Tree.OutboundRouteEntry> linkGenerationEntries, System.Text.Encodings.Web.UrlEncoder urlEncoder, Microsoft.Extensions.ObjectPool.ObjectPool<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext> objectPool, Microsoft.Extensions.Logging.ILogger routeLogger, Microsoft.Extensions.Logging.ILogger constraintLogger, int version) { }
|
||||
public int Version { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public Microsoft.AspNetCore.Routing.VirtualPathData GetVirtualPath(Microsoft.AspNetCore.Routing.VirtualPathContext context) { throw null; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper type for avoiding allocations while building arrays.
|
||||
|
|
@ -166,4 +166,4 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
|||
_array = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
internal sealed class DefaultLinkGenerator : LinkGenerator, IDisposable
|
||||
{
|
||||
private readonly ParameterPolicyFactory _parameterPolicyFactory;
|
||||
private readonly ObjectPool<UriBuildingContext> _uriBuildingContextPool;
|
||||
private readonly TemplateBinderFactory _binderFactory;
|
||||
private readonly ILogger<DefaultLinkGenerator> _logger;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
|
|
@ -38,14 +38,14 @@ namespace Microsoft.AspNetCore.Routing
|
|||
|
||||
public DefaultLinkGenerator(
|
||||
ParameterPolicyFactory parameterPolicyFactory,
|
||||
TemplateBinderFactory binderFactory,
|
||||
EndpointDataSource dataSource,
|
||||
ObjectPool<UriBuildingContext> uriBuildingContextPool,
|
||||
IOptions<RouteOptions> routeOptions,
|
||||
ILogger<DefaultLinkGenerator> logger,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
_parameterPolicyFactory = parameterPolicyFactory;
|
||||
_uriBuildingContextPool = uriBuildingContextPool;
|
||||
_binderFactory = binderFactory;
|
||||
_logger = logger;
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
|
|
@ -282,40 +282,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
|
||||
private TemplateBinder CreateTemplateBinder(RouteEndpoint endpoint)
|
||||
{
|
||||
// Now create the constraints and parameter transformers from the pattern
|
||||
var policies = new List<(string parameterName, IParameterPolicy policy)>();
|
||||
foreach (var kvp in endpoint.RoutePattern.ParameterPolicies)
|
||||
{
|
||||
var parameterName = kvp.Key;
|
||||
|
||||
// It's possible that we don't have an actual route parameter, we need to support that case.
|
||||
var parameter = endpoint.RoutePattern.GetParameter(parameterName);
|
||||
|
||||
// Use the first parameter transformer per parameter
|
||||
var foundTransformer = false;
|
||||
for (var i = 0; i < kvp.Value.Count; i++)
|
||||
{
|
||||
var parameterPolicy = _parameterPolicyFactory.Create(parameter, kvp.Value[i]);
|
||||
if (!foundTransformer && parameterPolicy is IOutboundParameterTransformer parameterTransformer)
|
||||
{
|
||||
policies.Add((parameterName, parameterTransformer));
|
||||
foundTransformer = true;
|
||||
}
|
||||
|
||||
if (parameterPolicy is IRouteConstraint constraint)
|
||||
{
|
||||
policies.Add((parameterName, constraint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new TemplateBinder(
|
||||
UrlEncoder.Default,
|
||||
_uriBuildingContextPool,
|
||||
endpoint.RoutePattern,
|
||||
new RouteValueDictionary(endpoint.RoutePattern.Defaults),
|
||||
endpoint.RoutePattern.RequiredValues.Keys,
|
||||
policies);
|
||||
return _binderFactory.Create(endpoint.RoutePattern);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Routing;
|
|||
using Microsoft.AspNetCore.Routing.Internal;
|
||||
using Microsoft.AspNetCore.Routing.Matching;
|
||||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
using Microsoft.AspNetCore.Routing.Template;
|
||||
using Microsoft.AspNetCore.Routing.Tree;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
@ -34,6 +35,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
services.TryAddTransient<IInlineConstraintResolver, DefaultInlineConstraintResolver>();
|
||||
services.TryAddTransient<ObjectPoolProvider, DefaultObjectPoolProvider>();
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
services.TryAddSingleton<ObjectPool<UriBuildingContext>>(s =>
|
||||
{
|
||||
var provider = s.GetRequiredService<ObjectPoolProvider>();
|
||||
|
|
@ -49,6 +51,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
var constraintResolver = s.GetRequiredService<IInlineConstraintResolver>();
|
||||
return new TreeRouteBuilder(loggerFactory, objectPool, constraintResolver);
|
||||
}));
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
services.TryAddSingleton(typeof(RoutingMarkerService));
|
||||
|
||||
|
|
@ -88,6 +91,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
//
|
||||
// Misc infrastructure
|
||||
//
|
||||
services.TryAddSingleton<TemplateBinderFactory, DefaultTemplateBinderFactory>();
|
||||
services.TryAddSingleton<RoutePatternTransformer, DefaultRoutePatternTransformer>();
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +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.Internal
|
||||
{
|
||||
public readonly struct BufferValue
|
||||
{
|
||||
public BufferValue(string value, bool requiresEncoding)
|
||||
{
|
||||
Value = value;
|
||||
RequiresEncoding = requiresEncoding;
|
||||
}
|
||||
|
||||
public bool RequiresEncoding { get; }
|
||||
|
||||
public string Value { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
{
|
||||
// Segments are treated as all-or-none. We should never output a partial segment.
|
||||
|
|
@ -9,6 +11,7 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
|||
// used a value for {p1}, we have to output the entire segment up to the next "/".
|
||||
// Otherwise we could end up with the partial segment "v1" instead of the entire
|
||||
// segment "v1-v2.xml".
|
||||
[Obsolete("This type will be marked as internal in a future release.")]
|
||||
public enum SegmentState
|
||||
{
|
||||
Beginning,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
|
@ -10,6 +11,7 @@ using Microsoft.AspNetCore.Http;
|
|||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
{
|
||||
[Obsolete("This type will be marked as internal in a future release.")]
|
||||
[DebuggerDisplay("{DebuggerToString(),nq}")]
|
||||
public class UriBuildingContext
|
||||
{
|
||||
|
|
@ -321,5 +323,18 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
|||
{
|
||||
return string.Format("{{Accepted: '{0}' Buffered: '{1}'}}", _path, string.Join("", _buffer));
|
||||
}
|
||||
|
||||
private readonly struct BufferValue
|
||||
{
|
||||
public BufferValue(string value, bool requiresEncoding)
|
||||
{
|
||||
Value = value;
|
||||
RequiresEncoding = requiresEncoding;
|
||||
}
|
||||
|
||||
public bool RequiresEncoding { get; }
|
||||
|
||||
public string Value { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
|
@ -9,7 +9,7 @@ using System.Reflection;
|
|||
using System.Text;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
{
|
||||
internal static class ParameterPolicyActivator
|
||||
{
|
||||
|
|
@ -8,9 +8,9 @@ using System.Diagnostics;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
{
|
||||
public struct PathTokenizer : IReadOnlyList<StringSegment>
|
||||
internal struct PathTokenizer : IReadOnlyList<StringSegment>
|
||||
{
|
||||
private readonly string _path;
|
||||
private int _count;
|
||||
|
|
@ -246,14 +246,16 @@ namespace Microsoft.AspNetCore.Routing
|
|||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
private void EnsureBinder(HttpContext context)
|
||||
{
|
||||
if (_binder == null)
|
||||
{
|
||||
var pool = context.RequestServices.GetRequiredService<ObjectPool<UriBuildingContext>>();
|
||||
_binder = new TemplateBinder(UrlEncoder.Default, pool, ParsedTemplate, Defaults);
|
||||
var binderFactory = context.RequestServices.GetRequiredService<TemplateBinderFactory>();
|
||||
_binder = binderFactory.Create(ParsedTemplate, Defaults);
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
private void EnsureLoggers(HttpContext context)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// A marker class used to determine if all the routing services were added
|
||||
|
|
@ -12,4 +12,4 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
|||
internal class RoutingMarkerService
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Routing.Internal;
|
||||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Template
|
||||
{
|
||||
internal sealed class DefaultTemplateBinderFactory : TemplateBinderFactory
|
||||
{
|
||||
private readonly ParameterPolicyFactory _policyFactory;
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
private readonly ObjectPool<UriBuildingContext> _pool;
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
public DefaultTemplateBinderFactory(
|
||||
ParameterPolicyFactory policyFactory,
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
ObjectPool<UriBuildingContext> pool)
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
{
|
||||
if (policyFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(policyFactory));
|
||||
}
|
||||
|
||||
if (pool == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pool));
|
||||
}
|
||||
|
||||
_policyFactory = policyFactory;
|
||||
_pool = pool;
|
||||
|
||||
}
|
||||
|
||||
public override TemplateBinder Create(RouteTemplate template, RouteValueDictionary defaults)
|
||||
{
|
||||
if (template == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(template));
|
||||
}
|
||||
|
||||
if (defaults == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(defaults));
|
||||
}
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
return new TemplateBinder(UrlEncoder.Default, _pool, template, defaults);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
public override TemplateBinder Create(RoutePattern pattern)
|
||||
{
|
||||
if (pattern == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pattern));
|
||||
}
|
||||
|
||||
// Now create the constraints and parameter transformers from the pattern
|
||||
var policies = new List<(string parameterName, IParameterPolicy policy)>();
|
||||
foreach (var kvp in pattern.ParameterPolicies)
|
||||
{
|
||||
var parameterName = kvp.Key;
|
||||
|
||||
// It's possible that we don't have an actual route parameter, we need to support that case.
|
||||
var parameter = pattern.GetParameter(parameterName);
|
||||
|
||||
// Use the first parameter transformer per parameter
|
||||
var foundTransformer = false;
|
||||
for (var i = 0; i < kvp.Value.Count; i++)
|
||||
{
|
||||
var parameterPolicy = _policyFactory.Create(parameter, kvp.Value[i]);
|
||||
if (!foundTransformer && parameterPolicy is IOutboundParameterTransformer parameterTransformer)
|
||||
{
|
||||
policies.Add((parameterName, parameterTransformer));
|
||||
foundTransformer = true;
|
||||
}
|
||||
|
||||
if (parameterPolicy is IRouteConstraint constraint)
|
||||
{
|
||||
policies.Add((parameterName, constraint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new TemplateBinder(UrlEncoder.Default, _pool, pattern, policies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,9 @@ namespace Microsoft.AspNetCore.Routing.Template
|
|||
public class TemplateBinder
|
||||
{
|
||||
private readonly UrlEncoder _urlEncoder;
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
private readonly ObjectPool<UriBuildingContext> _pool;
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
private readonly (string parameterName, IRouteConstraint constraint)[] _constraints;
|
||||
private readonly RouteValueDictionary _defaults;
|
||||
|
|
@ -40,6 +42,9 @@ namespace Microsoft.AspNetCore.Routing.Template
|
|||
/// <param name="pool">The <see cref="ObjectPool{T}"/>.</param>
|
||||
/// <param name="template">The <see cref="RouteTemplate"/> to bind values to.</param>
|
||||
/// <param name="defaults">The default values for <paramref name="template"/>.</param>
|
||||
[Obsolete(
|
||||
"This constructor is obsolete and will be marked internal in a furture release. Use the TemplateBinderFactory service " +
|
||||
"to create TemplateBinder instances.")]
|
||||
public TemplateBinder(
|
||||
UrlEncoder urlEncoder,
|
||||
ObjectPool<UriBuildingContext> pool,
|
||||
|
|
@ -60,6 +65,9 @@ namespace Microsoft.AspNetCore.Routing.Template
|
|||
/// <param name="parameterPolicies">
|
||||
/// A list of (<see cref="string"/>, <see cref="IParameterPolicy"/>) pairs to evalute when producing a URI.
|
||||
/// </param>
|
||||
[Obsolete(
|
||||
"This constructor is obsolete and will be marked internal in a future release. Use the TemplateBinderFactory service " +
|
||||
"to create TemplateBinder instances.")]
|
||||
public TemplateBinder(
|
||||
UrlEncoder urlEncoder,
|
||||
ObjectPool<UriBuildingContext> pool,
|
||||
|
|
@ -110,6 +118,58 @@ namespace Microsoft.AspNetCore.Routing.Template
|
|||
_slots = AssignSlots(_pattern, _filters);
|
||||
}
|
||||
|
||||
internal TemplateBinder(
|
||||
UrlEncoder urlEncoder,
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
ObjectPool<UriBuildingContext> pool,
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
RoutePattern pattern,
|
||||
IEnumerable<(string parameterName, IParameterPolicy policy)> parameterPolicies)
|
||||
{
|
||||
if (urlEncoder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(urlEncoder));
|
||||
}
|
||||
|
||||
if (pool == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pool));
|
||||
}
|
||||
|
||||
if (pattern == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pattern));
|
||||
}
|
||||
|
||||
// Parameter policies can be null.
|
||||
|
||||
_urlEncoder = urlEncoder;
|
||||
_pool = pool;
|
||||
_pattern = pattern;
|
||||
_defaults = new RouteValueDictionary(pattern.Defaults);
|
||||
_requiredKeys = pattern.RequiredValues.Keys.ToArray();
|
||||
|
||||
// Any default that doesn't have a corresponding parameter is a 'filter' and if a value
|
||||
// is provided for that 'filter' it must match the value in defaults.
|
||||
var filters = new RouteValueDictionary(_defaults);
|
||||
for (var i = 0; i < pattern.Parameters.Count; i++)
|
||||
{
|
||||
filters.Remove(pattern.Parameters[i].Name);
|
||||
}
|
||||
_filters = filters.ToArray();
|
||||
|
||||
_constraints = parameterPolicies
|
||||
?.Where(p => p.policy is IRouteConstraint)
|
||||
.Select(p => (p.parameterName, (IRouteConstraint)p.policy))
|
||||
.ToArray() ?? Array.Empty<(string, IRouteConstraint)>();
|
||||
_parameterTransformers = parameterPolicies
|
||||
?.Where(p => p.policy is IOutboundParameterTransformer)
|
||||
.Select(p => (p.parameterName, (IOutboundParameterTransformer)p.policy))
|
||||
.ToArray() ?? Array.Empty<(string, IOutboundParameterTransformer)>();
|
||||
|
||||
_slots = AssignSlots(_pattern, _filters);
|
||||
}
|
||||
|
||||
// Step 1: Get the list of values we're going to try to use to match and generate this URI
|
||||
public TemplateValuesResult GetValues(RouteValueDictionary ambientValues, RouteValueDictionary values)
|
||||
{
|
||||
|
|
@ -442,6 +502,7 @@ namespace Microsoft.AspNetCore.Routing.Template
|
|||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
private bool TryBindValuesCore(UriBuildingContext context, RouteValueDictionary acceptedValues)
|
||||
{
|
||||
// If we have any output parameter transformers, allow them a chance to influence the parameter values
|
||||
|
|
@ -578,6 +639,7 @@ namespace Microsoft.AspNetCore.Routing.Template
|
|||
}
|
||||
return false;
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
/// <summary>
|
||||
/// Compares two objects for equality as parts of a case-insensitive path.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Template
|
||||
{
|
||||
/// <summary>
|
||||
/// A factory used to create <see cref="TemplateBinder"/> instances.
|
||||
/// </summary>
|
||||
public abstract class TemplateBinderFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="TemplateBinder"/> from the provided <paramref name="template"/> and
|
||||
/// <paramref name="defaults"/>.
|
||||
/// </summary>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="defaults">A collection of extra default values that do not appear in the route template.</param>
|
||||
/// <returns>A <see cref="TemplateBinder"/>.</returns>
|
||||
public abstract TemplateBinder Create(RouteTemplate template, RouteValueDictionary defaults);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="TemplateBinder"/> from the provided <paramref name="pattern"/>.
|
||||
/// </summary>
|
||||
/// <param name="pattern">The <see cref="RoutePattern"/>.</param>
|
||||
/// <returns>A <see cref="TemplateBinder"/>.</returns>
|
||||
public abstract TemplateBinder Create(RoutePattern pattern);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,13 +8,12 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using Microsoft.AspNetCore.Routing.DecisionTree;
|
||||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
using Microsoft.AspNetCore.Routing.Tree;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
namespace Microsoft.AspNetCore.Routing.Tree
|
||||
{
|
||||
// A decision tree that matches link generation entries based on route data.
|
||||
[DebuggerDisplay("{DebuggerDisplayString,nq}")]
|
||||
public class LinkGenerationDecisionTree
|
||||
internal class LinkGenerationDecisionTree
|
||||
{
|
||||
// Fallback value for cases where the ambient values weren't provided.
|
||||
//
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Routing.Tree;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
namespace Microsoft.AspNetCore.Routing.Tree
|
||||
{
|
||||
public readonly struct OutboundMatchResult
|
||||
internal readonly struct OutboundMatchResult
|
||||
{
|
||||
public OutboundMatchResult(OutboundMatch match, bool isFallbackMatch)
|
||||
{
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Routing.Internal;
|
||||
|
|
@ -21,7 +20,9 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
private readonly ILogger _logger;
|
||||
private readonly ILogger _constraintLogger;
|
||||
private readonly UrlEncoder _urlEncoder;
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
private readonly ObjectPool<UriBuildingContext> _objectPool;
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
private readonly IInlineConstraintResolver _constraintResolver;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -30,9 +31,12 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
/// <param name="objectPool">The <see cref="ObjectPool{UrlBuildingContext}"/>.</param>
|
||||
/// <param name="constraintResolver">The <see cref="IInlineConstraintResolver"/>.</param>
|
||||
[Obsolete("This constructor will be marked internal in a future release. Use the service provider to create instances of TreeRouteBuilder.")]
|
||||
public TreeRouteBuilder(
|
||||
ILoggerFactory loggerFactory,
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
ObjectPool<UriBuildingContext> objectPool,
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
IInlineConstraintResolver constraintResolver)
|
||||
{
|
||||
if (loggerFactory == null)
|
||||
|
|
@ -240,6 +244,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
tree.AddEntry(entry);
|
||||
}
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
return new TreeRouter(
|
||||
trees.Values.OrderBy(tree => tree.Order).ToArray(),
|
||||
OutboundEntries,
|
||||
|
|
@ -248,6 +253,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
_logger,
|
||||
_constraintLogger,
|
||||
version);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -40,11 +40,14 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
/// <param name="constraintLogger">The <see cref="ILogger"/> instance used
|
||||
/// in <see cref="RouteConstraintMatcher"/>.</param>
|
||||
/// <param name="version">The version of this route.</param>
|
||||
[Obsolete("This constructor will be marked obsolete in a future release. Use the TreeRouterBuilder to create instances of TreeRouter.")]
|
||||
public TreeRouter(
|
||||
UrlMatchingTree[] trees,
|
||||
IEnumerable<OutboundRouteEntry> linkGenerationEntries,
|
||||
UrlEncoder urlEncoder,
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
ObjectPool<UriBuildingContext> objectPool,
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
ILogger routeLogger,
|
||||
ILogger constraintLogger,
|
||||
int version)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Routing.Internal;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
namespace Microsoft.AspNetCore.Routing
|
||||
{
|
||||
public class UriBuilderContextPooledObjectPolicy : IPooledObjectPolicy<UriBuildingContext>
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
internal class UriBuilderContextPooledObjectPolicy : IPooledObjectPolicy<UriBuildingContext>
|
||||
{
|
||||
public UriBuildingContext Create()
|
||||
{
|
||||
|
|
@ -19,4 +21,5 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
|||
return true;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Extensions.WebEncoders.Testing;
|
||||
|
|
@ -6,6 +6,7 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNetCore.Routing.Internal
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
public class UriBuildingContextTest
|
||||
{
|
||||
[Fact]
|
||||
|
|
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
|||
var value = "a/b b1/c";
|
||||
var expected = "/UrlEncode[[a/b b1/c]]";
|
||||
var uriBuilldingContext = new UriBuildingContext(urlTestEncoder);
|
||||
|
||||
|
||||
// Act
|
||||
uriBuilldingContext.EncodeValue(value, 0, value.Length, encodeSlashes: true);
|
||||
|
||||
|
|
@ -97,4 +98,5 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
|||
Assert.Equal(expected, uriBuilldingContext.ToPathString().Value);
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Routing.Internal;
|
||||
using Microsoft.AspNetCore.Routing.Template;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
|
@ -82,8 +83,8 @@ namespace Microsoft.AspNetCore.Routing
|
|||
|
||||
return new DefaultLinkGenerator(
|
||||
new DefaultParameterPolicyFactory(routeOptions, serviceProvider),
|
||||
serviceProvider.GetRequiredService<TemplateBinderFactory>(),
|
||||
new CompositeEndpointDataSource(routeOptions.Value.EndpointDataSources),
|
||||
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
|
||||
routeOptions,
|
||||
NullLogger<DefaultLinkGenerator>.Instance,
|
||||
serviceProvider);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
|
@ -32,10 +32,12 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
|
||||
public override Matcher Build()
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var builder = new TreeRouteBuilder(
|
||||
NullLoggerFactory.Instance,
|
||||
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
|
||||
new DefaultInlineConstraintResolver(Options.Create(new RouteOptions()), new TestServiceProvider()));
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
var selector = new DefaultEndpointSelector();
|
||||
|
||||
|
|
|
|||
|
|
@ -658,6 +658,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
var expected = "/Home/Index?name=" + UrlEncoder.Default.Encode(nameRouteValue);
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
|
||||
services.AddOptions();
|
||||
services.AddRouting();
|
||||
// This test encoder should not be used by Routing and should always use the default one.
|
||||
services.AddSingleton<UrlEncoder>(new UrlTestEncoder());
|
||||
|
|
@ -1520,6 +1521,7 @@ namespace Microsoft.AspNetCore.Routing
|
|||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
|
||||
services.AddOptions();
|
||||
services.AddRouting();
|
||||
|
||||
var context = new DefaultHttpContext
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNetCore.Routing.Template.Tests
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
public class TemplateBinderTests
|
||||
{
|
||||
private readonly IInlineConstraintResolver _inlineConstraintResolver = GetInlineConstraintResolver();
|
||||
|
|
@ -1480,4 +1481,5 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests
|
|||
public Dictionary<string, string> Parameters { get; private set; }
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text.Encodings.Web;
|
||||
|
|
@ -248,10 +248,12 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
var objectPool = objectPoolProvider.Create(objectPolicy);
|
||||
|
||||
var constraintResolver = GetInlineConstraintResolver();
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var builder = new TreeRouteBuilder(
|
||||
NullLoggerFactory.Instance,
|
||||
objectPool,
|
||||
constraintResolver);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
{
|
||||
private static readonly RequestDelegate NullHandler = (c) => Task.CompletedTask;
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
private static ObjectPool<UriBuildingContext> Pool = new DefaultObjectPoolProvider().Create(
|
||||
new UriBuilderContextPooledObjectPolicy());
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
[Theory]
|
||||
[InlineData("template/5", "template/{parameter:int}")]
|
||||
|
|
@ -2073,6 +2075,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
return new DefaultInlineConstraintResolver(optionsMock.Object, new TestServiceProvider());
|
||||
}
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
private static TreeRouteBuilder CreateBuilder()
|
||||
{
|
||||
var objectPoolProvider = new DefaultObjectPoolProvider();
|
||||
|
|
@ -2086,6 +2089,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
constraintResolver);
|
||||
return builder;
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
private static TreeRouter CreateTreeRouter(
|
||||
string firstTemplate,
|
||||
|
|
|
|||
Loading…
Reference in New Issue