Change metadata namespace

Change EndpointOptions visibility to internal
Add IRequiredValuesMetadata
This commit is contained in:
James Newton-King 2018-08-02 01:17:09 -07:00 committed by Kiran Challa
parent c8946a40e4
commit 091cb94094
27 changed files with 133 additions and 73 deletions

View File

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Benchmarks namespace Benchmarks
{ {
@ -18,9 +19,7 @@ namespace Benchmarks
{ {
services.AddRouting(); services.AddRouting();
services.Configure<EndpointOptions>(options => var endpointDataSource = new DefaultEndpointDataSource(new[]
{
options.DataSources.Add(new DefaultEndpointDataSource(new[]
{ {
new MatcherEndpoint( new MatcherEndpoint(
invoker: (next) => (httpContext) => invoker: (next) => (httpContext) =>
@ -33,12 +32,12 @@ namespace Benchmarks
return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength); return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength);
}, },
routePattern: RoutePatternFactory.Parse("/plaintext"), routePattern: RoutePatternFactory.Parse("/plaintext"),
requiredValues: new RouteValueDictionary(),
order: 0, order: 0,
metadata: EndpointMetadataCollection.Empty, metadata: EndpointMetadataCollection.Empty,
displayName: "Plaintext"), displayName: "Plaintext"),
})); });
});
services.TryAddEnumerable(ServiceDescriptor.Singleton<EndpointDataSource>(endpointDataSource));
} }
public void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app) public void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app)

View File

@ -7,7 +7,6 @@ using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Metadata;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -44,7 +43,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template), RoutePatternFactory.Parse(template),
new RouteValueDictionary(),
0, 0,
new EndpointMetadataCollection(metadata), new EndpointMetadataCollection(metadata),
template); template);

View File

@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace RoutingSample.Web namespace RoutingSample.Web
{ {
@ -26,9 +27,7 @@ namespace RoutingSample.Web
options.ConstraintMap.Add("endsWith", typeof(EndsWithStringMatchProcessor)); options.ConstraintMap.Add("endsWith", typeof(EndsWithStringMatchProcessor));
}); });
services.Configure<EndpointOptions>(options => var endpointDataSource = new DefaultEndpointDataSource(new[]
{
options.DataSources.Add(new DefaultEndpointDataSource(new[]
{ {
new MatcherEndpoint((next) => (httpContext) => new MatcherEndpoint((next) => (httpContext) =>
{ {
@ -40,7 +39,6 @@ namespace RoutingSample.Web
return response.Body.WriteAsync(_homePayload, 0, payloadLength); return response.Body.WriteAsync(_homePayload, 0, payloadLength);
}, },
RoutePatternFactory.Parse("/"), RoutePatternFactory.Parse("/"),
new RouteValueDictionary(),
0, 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
"Home"), "Home"),
@ -54,7 +52,6 @@ namespace RoutingSample.Web
return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength); return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength);
}, },
RoutePatternFactory.Parse("/plaintext"), RoutePatternFactory.Parse("/plaintext"),
new RouteValueDictionary(),
0, 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
"Plaintext"), "Plaintext"),
@ -66,7 +63,6 @@ namespace RoutingSample.Web
return response.WriteAsync("WithConstraints"); return response.WriteAsync("WithConstraints");
}, },
RoutePatternFactory.Parse("/withconstraints/{id:endsWith(_001)}"), RoutePatternFactory.Parse("/withconstraints/{id:endsWith(_001)}"),
new RouteValueDictionary(),
0, 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
"withconstraints"), "withconstraints"),
@ -78,12 +74,12 @@ namespace RoutingSample.Web
return response.WriteAsync("withoptionalconstraints"); return response.WriteAsync("withoptionalconstraints");
}, },
RoutePatternFactory.Parse("/withoptionalconstraints/{id:endsWith(_001)?}"), RoutePatternFactory.Parse("/withoptionalconstraints/{id:endsWith(_001)?}"),
new RouteValueDictionary(),
0, 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
"withoptionalconstraints"), "withoptionalconstraints"),
})); });
});
services.TryAddEnumerable(ServiceDescriptor.Singleton<EndpointDataSource>(endpointDataSource));
} }
public void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app) public void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app)

View File

@ -8,7 +8,6 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Metadata;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Routing namespace Microsoft.AspNetCore.Routing
@ -127,15 +126,18 @@ namespace Microsoft.AspNetCore.Routing
var template = matcherEndpoint.RoutePattern.RawText; var template = matcherEndpoint.RoutePattern.RawText;
template = string.IsNullOrEmpty(template) ? "\"\"" : template; template = string.IsNullOrEmpty(template) ? "\"\"" : template;
sb.Append(template); sb.Append(template);
sb.Append(", Required Values: new { ");
sb.Append(string.Join(", ", FormatValues(matcherEndpoint.RequiredValues)));
sb.Append(" }");
sb.Append(", Defaults: new { "); sb.Append(", Defaults: new { ");
sb.Append(string.Join(", ", FormatValues(matcherEndpoint.RoutePattern.Defaults))); sb.Append(string.Join(", ", FormatValues(matcherEndpoint.RoutePattern.Defaults)));
sb.Append(" }"); sb.Append(" }");
var routeNameMetadata = matcherEndpoint.Metadata.GetMetadata<IRouteNameMetadata>(); var routeValuesAddressMetadata = matcherEndpoint.Metadata.GetMetadata<IRouteValuesAddressMetadata>();
sb.Append(", Route Name: "); sb.Append(", Route Name: ");
sb.Append(routeNameMetadata?.Name); sb.Append(routeValuesAddressMetadata?.Name);
if (routeValuesAddressMetadata?.RequiredValues != null)
{
sb.Append(", Required Values: new { ");
sb.Append(string.Join(", ", FormatValues(routeValuesAddressMetadata.RequiredValues)));
sb.Append(" }");
}
sb.Append(", Order: "); sb.Append(", Order: ");
sb.Append(matcherEndpoint.Order); sb.Append(matcherEndpoint.Order);

View File

@ -5,7 +5,8 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing namespace Microsoft.AspNetCore.Routing
{ {
public class EndpointOptions // Internal for 2.2. Public API for configuring endpoints will be added in 3.0
internal class EndpointOptions
{ {
public IList<EndpointDataSource> DataSources { get; } = new List<EndpointDataSource>(); public IList<EndpointDataSource> DataSources { get; } = new List<EndpointDataSource>();
} }

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
namespace Microsoft.AspNetCore.Routing.Metadata namespace Microsoft.AspNetCore.Routing
{ {
[DebuggerDisplay("{DebuggerToString(),nq}")] [DebuggerDisplay("{DebuggerToString(),nq}")]
public sealed class HttpMethodMetadata : IHttpMethodMetadata public sealed class HttpMethodMetadata : IHttpMethodMetadata

View File

@ -3,7 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing.Metadata namespace Microsoft.AspNetCore.Routing
{ {
public interface IHttpMethodMetadata public interface IHttpMethodMetadata
{ {

View File

@ -0,0 +1,13 @@
// 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;
namespace Microsoft.AspNetCore.Routing
{
public interface IRouteValuesAddressMetadata
{
string Name { get; }
IReadOnlyDictionary<string, object> RequiredValues { get; }
}
}

View File

@ -6,4 +6,4 @@ namespace Microsoft.AspNetCore.Routing
public interface ISuppressLinkGenerationMetadata public interface ISuppressLinkGenerationMetadata
{ {
} }
} }

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Metadata;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
@ -232,7 +231,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return Task.CompletedTask; return Task.CompletedTask;
}, },
RoutePatternFactory.Parse("/"), RoutePatternFactory.Parse("/"),
new RouteValueDictionary(),
0, 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
Http405EndpointDisplayName); Http405EndpointDisplayName);

View File

@ -19,7 +19,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
public MatcherEndpoint( public MatcherEndpoint(
Func<RequestDelegate, RequestDelegate> invoker, Func<RequestDelegate, RequestDelegate> invoker,
RoutePattern routePattern, RoutePattern routePattern,
RouteValueDictionary requiredValues,
int order, int order,
EndpointMetadataCollection metadata, EndpointMetadataCollection metadata,
string displayName) string displayName)
@ -37,7 +36,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
Invoker = invoker; Invoker = invoker;
RoutePattern = routePattern; RoutePattern = routePattern;
RequiredValues = requiredValues;
Order = order; Order = order;
} }
@ -45,9 +43,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
public int Order { get; } public int Order { get; }
// Values required by an endpoint for it to be successfully matched on link generation
public IReadOnlyDictionary<string, object> RequiredValues { get; }
public RoutePattern RoutePattern { get; } public RoutePattern RoutePattern { get; }
} }
} }

View File

@ -0,0 +1,48 @@
// 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.Linq;
namespace Microsoft.AspNetCore.Routing
{
[DebuggerDisplay("{DebuggerToString(),nq}")]
public sealed class RouteValuesAddressMetadata : IRouteValuesAddressMetadata
{
public RouteValuesAddressMetadata(string name, IReadOnlyDictionary<string, object> requiredValues)
{
Name = name;
RequiredValues = requiredValues;
}
public string Name { get; }
public IReadOnlyDictionary<string, object> RequiredValues { get; }
internal string DebuggerToString()
{
return $"Name: {Name} - Required values: {string.Join(", ", FormatValues(RequiredValues))}";
IEnumerable<string> FormatValues(IEnumerable<KeyValuePair<string, object>> values)
{
if (values == null)
{
return Array.Empty<string>();
}
return values.Select(
kvp =>
{
var value = "null";
if (kvp.Value != null)
{
value = "\"" + kvp.Value.ToString() + "\"";
}
return kvp.Key + " = " + value;
});
}
}
}
}

View File

@ -137,16 +137,16 @@ namespace Microsoft.AspNetCore.Routing
private OutboundRouteEntry CreateOutboundRouteEntry(MatcherEndpoint endpoint) private OutboundRouteEntry CreateOutboundRouteEntry(MatcherEndpoint endpoint)
{ {
var routeNameMetadata = endpoint.Metadata.GetMetadata<IRouteNameMetadata>(); var routeValuesAddressMetadata = endpoint.Metadata.GetMetadata<IRouteValuesAddressMetadata>();
var entry = new OutboundRouteEntry() var entry = new OutboundRouteEntry()
{ {
Handler = NullRouter.Instance, Handler = NullRouter.Instance,
Order = endpoint.Order, Order = endpoint.Order,
Precedence = RoutePrecedence.ComputeOutbound(endpoint.RoutePattern), Precedence = RoutePrecedence.ComputeOutbound(endpoint.RoutePattern),
RequiredLinkValues = new RouteValueDictionary(endpoint.RequiredValues), RequiredLinkValues = new RouteValueDictionary(routeValuesAddressMetadata?.RequiredValues),
RouteTemplate = new RouteTemplate(endpoint.RoutePattern), RouteTemplate = new RouteTemplate(endpoint.RoutePattern),
Data = endpoint, Data = endpoint,
RouteName = routeNameMetadata?.Name, RouteName = routeValuesAddressMetadata?.Name,
}; };
entry.Defaults = new RouteValueDictionary(endpoint.RoutePattern.Defaults); entry.Defaults = new RouteValueDictionary(endpoint.RoutePattern.Defaults);
return entry; return entry;

View File

@ -3,8 +3,7 @@
namespace Microsoft.AspNetCore.Routing namespace Microsoft.AspNetCore.Routing
{ {
public interface IRouteNameMetadata public sealed class SuppressLinkGenerationMetadata : ISuppressLinkGenerationMetadata
{ {
string Name { get; }
} }
} }

View File

@ -149,14 +149,12 @@ namespace Microsoft.AspNetCore.Routing
private MatcherEndpoint CreateEndpoint( private MatcherEndpoint CreateEndpoint(
string template, string template,
object defaults = null, object defaults = null,
object requiredValues = null,
int order = 0, int order = 0,
string routeName = null) string routeName = null)
{ {
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template, defaults, constraints: null), RoutePatternFactory.Parse(template, defaults, constraints: null),
new RouteValueDictionary(requiredValues),
order, order,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
null); null);

View File

@ -3,6 +3,8 @@
using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing namespace Microsoft.AspNetCore.Routing
{ {
@ -17,18 +19,17 @@ namespace Microsoft.AspNetCore.Routing
string displayName = null, string displayName = null,
params object[] metadata) params object[] metadata)
{ {
var metadataCollection = EndpointMetadataCollection.Empty; var d = new List<object>(metadata ?? Array.Empty<object>());
if (metadata != null) if (requiredValues != null)
{ {
metadataCollection = new EndpointMetadataCollection(metadata); d.Add(new RouteValuesAddressMetadata(null, new RouteValueDictionary(requiredValues)));
} }
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template, defaults, constraints), RoutePatternFactory.Parse(template, defaults, constraints),
new RouteValueDictionary(requiredValues),
order, order,
metadataCollection, new EndpointMetadataCollection(d),
displayName); displayName);
} }
} }

View File

@ -85,7 +85,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template), RoutePatternFactory.Parse(template),
new RouteValueDictionary(),
0, 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
"test"); "test");

View File

@ -37,7 +37,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
var endpoint = new MatcherEndpoint( var endpoint = new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse("a/b/c"), RoutePatternFactory.Parse("a/b/c"),
new RouteValueDictionary(),
0, 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
"test"); "test");

View File

@ -216,7 +216,6 @@ test: /test3", ex.Message);
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template), RoutePatternFactory.Parse(template),
new RouteValueDictionary(),
0, 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
$"test: {template}"); $"test: {template}");

View File

@ -860,7 +860,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints)), RoutePatternFactory.Parse(template, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints)),
new RouteValueDictionary(),
0, 0,
new EndpointMetadataCollection(metadata), new EndpointMetadataCollection(metadata),
"test"); "test");

View File

@ -20,7 +20,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template, defaults, constraints: null), RoutePatternFactory.Parse(template, defaults, constraints: null),
new RouteValueDictionary(),
order, order,
metadata ?? EndpointMetadataCollection.Empty, metadata ?? EndpointMetadataCollection.Empty,
template); template);

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Metadata;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Xunit; using Xunit;
@ -343,7 +342,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template, defaults, constraints), RoutePatternFactory.Parse(template, defaults, constraints),
new RouteValueDictionary(),
order, order,
new EndpointMetadataCollection(metadata), new EndpointMetadataCollection(metadata),
displayName); displayName);

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.Routing.Metadata;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
using Xunit; using Xunit;
using static Microsoft.AspNetCore.Routing.Matching.HttpMethodMatcherPolicy; using static Microsoft.AspNetCore.Routing.Matching.HttpMethodMatcherPolicy;
@ -288,7 +287,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template), RoutePatternFactory.Parse(template),
new RouteValueDictionary(),
0, 0,
new EndpointMetadataCollection(metadata), new EndpointMetadataCollection(metadata),
$"test: {template}"); $"test: {template}");

View File

@ -43,7 +43,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template, defaults, constraints), RoutePatternFactory.Parse(template, defaults, constraints),
new RouteValueDictionary(),
order ?? 0, order ?? 0,
EndpointMetadataCollection.Empty, EndpointMetadataCollection.Empty,
"endpoint: " + template); "endpoint: " + template);

View File

@ -222,7 +222,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template), RoutePatternFactory.Parse(template),
new RouteValueDictionary(),
order, order,
new EndpointMetadataCollection(metadata), new EndpointMetadataCollection(metadata),
"test: " + template); "test: " + template);

View File

@ -263,37 +263,29 @@ namespace Microsoft.AspNetCore.Routing
{ {
if (metadataCollection == null) if (metadataCollection == null)
{ {
metadataCollection = EndpointMetadataCollection.Empty; var metadata = new List<object>();
if (!string.IsNullOrEmpty(routeName)) if (!string.IsNullOrEmpty(routeName) || requiredValues != null)
{ {
metadataCollection = new EndpointMetadataCollection(new[] { new RouteNameMetadata(routeName) }); metadata.Add(new RouteValuesAddressMetadata(routeName, new RouteValueDictionary(requiredValues)));
} }
metadataCollection = new EndpointMetadataCollection(metadata);
} }
return new MatcherEndpoint( return new MatcherEndpoint(
MatcherEndpoint.EmptyInvoker, MatcherEndpoint.EmptyInvoker,
RoutePatternFactory.Parse(template, defaults, constraints: null), RoutePatternFactory.Parse(template, defaults, constraints: null),
new RouteValueDictionary(requiredValues),
order, order,
metadataCollection, metadataCollection,
null); null);
} }
private class RouteNameMetadata : IRouteNameMetadata
{
public RouteNameMetadata(string name)
{
Name = name;
}
public string Name { get; }
}
private class NameMetadata : INameMetadata private class NameMetadata : INameMetadata
{ {
public NameMetadata(string name) public NameMetadata(string name)
{ {
Name = name; Name = name;
} }
public string Name { get; } public string Name { get; }
} }
@ -318,7 +310,5 @@ namespace Microsoft.AspNetCore.Routing
return matches; return matches;
} }
} }
private class SuppressLinkGenerationMetadata : ISuppressLinkGenerationMetadata { }
} }
} }

View File

@ -0,0 +1,33 @@
// 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;
using Xunit;
namespace Microsoft.AspNetCore.Routing
{
public class RouteValuesAddressMetadataTests
{
[Fact]
public void DebuggerToString_NoNameAndRequiredValues_ReturnsString()
{
var metadata = new RouteValuesAddressMetadata(null, null);
Assert.Equal("Name: - Required values: ", metadata.DebuggerToString());
}
[Fact]
public void DebuggerToString_HasNameAndRequiredValues_ReturnsString()
{
var metadata = new RouteValuesAddressMetadata("Name!", new Dictionary<string, object>
{
["requiredValue1"] = "One",
["requiredValue2"] = 2,
});
Assert.Equal("Name: Name! - Required values: requiredValue1 = \"One\", requiredValue2 = \"2\"", metadata.DebuggerToString());
}
}
}