From 10f175123f5dab30fe934e2c91193770801b39e3 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Wed, 25 Jul 2018 06:33:34 -0700 Subject: [PATCH 01/17] Upgraded dependencies.props --- build/dependencies.props | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index a2fec6e267..a8dfaafdbc 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,32 +5,32 @@ 0.10.13 3.0.0-alpha1-10011 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 + 3.0.0-alpha1-10143 2.0.9 2.1.2 2.2.0-preview1-26618-02 From ca74ccf541ded882c2e0f5b9bf19afa034f9a35b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 20:09:00 +0000 Subject: [PATCH 02/17] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 59 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index a8dfaafdbc..5e8dbc800d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,33 +4,33 @@ 0.10.13 - 3.0.0-alpha1-10011 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 - 3.0.0-alpha1-10143 + 3.0.0-alpha1-10015 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 2.0.9 2.1.2 2.2.0-preview1-26618-02 @@ -38,9 +38,10 @@ 4.7.49 2.0.3 11.0.2 - 0.9.0 + 0.10.0 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 9a67ee9c28..1e75dc3a23 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10011 -commithash:717c2eb1f91dafd2580c1a9b8e5064d12dd8c054 +version:3.0.0-alpha1-10015 +commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 From ce6953de0273be066a7be4466b3caf31276ad6c8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 5 Aug 2018 20:03:33 +0000 Subject: [PATCH 03/17] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 54 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 5e8dbc800d..6b937df71f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,33 +4,33 @@ 0.10.13 - 3.0.0-alpha1-10015 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 + 3.0.0-alpha1-20180731.2 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 1e75dc3a23..8f9f6066ef 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10015 -commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 +version:3.0.0-alpha1-20180731.2 +commithash:1179f1083695ac9213c8a70a4d1d6c45a52caf41 From 95267a32e25324ff3c32c5a91d1ca61690f8aa4b Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Thu, 9 Aug 2018 13:06:27 +1200 Subject: [PATCH 04/17] Add EndpointBuilder (#701) --- .../Benchmarks/StartupUsingEndpointRouting.cs | 2 +- .../EndpointDataSourceBuilderExtensions.cs | 33 ++++++ .../HelloAppBuilderExtensions.cs | 25 ++++ .../HelloExtension/HelloMiddleware.cs | 45 +++++++ .../HelloExtension/HelloOptions.cs | 10 ++ .../UseEndpointRoutingStartup.cs | 112 ++++++++---------- ...ointRoutingApplicationBuilderExtensions.cs | 16 ++- ...ointEndpointDataSourceBuilderExtensions.cs | 69 +++++++++++ .../BuilderEndpointDataSource.cs | 33 ++++++ .../DefaultEndpointDataSourceBuilder.cs | 17 +++ .../RoutingServiceCollectionExtensions.cs | 6 + .../EndpointBuilder.cs | 16 +++ .../EndpointDataSourceBuilder.cs | 15 +++ .../Matching/MatcherEndpointBuilder.cs | 41 +++++++ .../EndpointRoutingSampleTest.cs | 21 +++- ...outingApplicationBuilderExtensionsTest.cs} | 23 +++- ...EndpointDataSourceBuilderExtensionsTest.cs | 89 ++++++++++++++ .../Matching/MatcherEndpointBuilderTest.cs | 36 ++++++ 18 files changed, 542 insertions(+), 67 deletions(-) create mode 100644 samples/RoutingSample.Web/HelloExtension/EndpointDataSourceBuilderExtensions.cs create mode 100644 samples/RoutingSample.Web/HelloExtension/HelloAppBuilderExtensions.cs create mode 100644 samples/RoutingSample.Web/HelloExtension/HelloMiddleware.cs create mode 100644 samples/RoutingSample.Web/HelloExtension/HelloOptions.cs rename src/Microsoft.AspNetCore.Routing/{Internal => Builder}/EndpointRoutingApplicationBuilderExtensions.cs (79%) create mode 100644 src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs create mode 100644 src/Microsoft.AspNetCore.Routing/BuilderEndpointDataSource.cs create mode 100644 src/Microsoft.AspNetCore.Routing/DefaultEndpointDataSourceBuilder.cs create mode 100644 src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs create mode 100644 src/Microsoft.AspNetCore.Routing/EndpointDataSourceBuilder.cs create mode 100644 src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs rename test/Microsoft.AspNetCore.Routing.Tests/Builder/{EndpointRoutingBuilderExtensionsTest.cs => EndpointRoutingApplicationBuilderExtensionsTest.cs} (83%) create mode 100644 test/Microsoft.AspNetCore.Routing.Tests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs create mode 100644 test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs diff --git a/benchmarkapps/Benchmarks/StartupUsingEndpointRouting.cs b/benchmarkapps/Benchmarks/StartupUsingEndpointRouting.cs index 2c5fa5a7d9..2a14f9d36d 100644 --- a/benchmarkapps/Benchmarks/StartupUsingEndpointRouting.cs +++ b/benchmarkapps/Benchmarks/StartupUsingEndpointRouting.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Text; -using Microsoft.AspNetCore.Internal; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Patterns; diff --git a/samples/RoutingSample.Web/HelloExtension/EndpointDataSourceBuilderExtensions.cs b/samples/RoutingSample.Web/HelloExtension/EndpointDataSourceBuilderExtensions.cs new file mode 100644 index 0000000000..6c2a4639a5 --- /dev/null +++ b/samples/RoutingSample.Web/HelloExtension/EndpointDataSourceBuilderExtensions.cs @@ -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.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Matching; +using Microsoft.AspNetCore.Routing.Patterns; + +namespace Microsoft.AspNetCore.Builder +{ + public static class EndpointDataSourceBuilderExtensions + { + public static EndpointBuilder MapHello(this EndpointDataSourceBuilder builder, string template, string greeter) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + var pipeline = builder.CreateApplicationBuilder() + .UseHello(greeter) + .Build(); + + return builder.MapEndpoint( + (next) => pipeline, + template, + "Hello"); + } + } +} diff --git a/samples/RoutingSample.Web/HelloExtension/HelloAppBuilderExtensions.cs b/samples/RoutingSample.Web/HelloExtension/HelloAppBuilderExtensions.cs new file mode 100644 index 0000000000..e1a587d5ca --- /dev/null +++ b/samples/RoutingSample.Web/HelloExtension/HelloAppBuilderExtensions.cs @@ -0,0 +1,25 @@ +// 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 Microsoft.Extensions.Options; +using RoutingSample.Web.HelloExtension; + +namespace Microsoft.AspNetCore.Builder +{ + public static class HelloAppBuilderExtensions + { + public static IApplicationBuilder UseHello(this IApplicationBuilder app, string greeter) + { + if (app == null) + { + throw new ArgumentNullException(nameof(app)); + } + + return app.UseMiddleware(Options.Create(new HelloOptions + { + Greeter = greeter + })); + } + } +} diff --git a/samples/RoutingSample.Web/HelloExtension/HelloMiddleware.cs b/samples/RoutingSample.Web/HelloExtension/HelloMiddleware.cs new file mode 100644 index 0000000000..6a4587e50c --- /dev/null +++ b/samples/RoutingSample.Web/HelloExtension/HelloMiddleware.cs @@ -0,0 +1,45 @@ +// 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.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; + +namespace RoutingSample.Web.HelloExtension +{ + public class HelloMiddleware + { + private readonly RequestDelegate _next; + private readonly HelloOptions _helloOptions; + private readonly byte[] _helloPayload; + + public HelloMiddleware(RequestDelegate next, IOptions helloOptions) + { + _next = next; + _helloOptions = helloOptions.Value; + + var payload = new List(); + payload.AddRange(Encoding.UTF8.GetBytes("Hello")); + if (!string.IsNullOrEmpty(_helloOptions.Greeter)) + { + payload.Add((byte)' '); + payload.AddRange(Encoding.UTF8.GetBytes(_helloOptions.Greeter)); + } + _helloPayload = payload.ToArray(); + } + + public Task InvokeAsync(HttpContext context) + { + var response = context.Response; + var payloadLength = _helloPayload.Length; + response.StatusCode = 200; + response.ContentType = "text/plain"; + response.ContentLength = payloadLength; + return response.Body.WriteAsync(_helloPayload, 0, payloadLength); + } + } +} diff --git a/samples/RoutingSample.Web/HelloExtension/HelloOptions.cs b/samples/RoutingSample.Web/HelloExtension/HelloOptions.cs new file mode 100644 index 0000000000..49f8b5c5df --- /dev/null +++ b/samples/RoutingSample.Web/HelloExtension/HelloOptions.cs @@ -0,0 +1,10 @@ +// 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 RoutingSample.Web.HelloExtension +{ + public class HelloOptions + { + public string Greeter { get; set; } + } +} diff --git a/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs b/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs index 77b41e87a8..c909990ba6 100644 --- a/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs +++ b/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs @@ -3,20 +3,16 @@ using System; using System.Text; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Internal; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.Routing.Matching; -using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; namespace RoutingSample.Web { public class UseEndpointRoutingStartup { private static readonly byte[] _homePayload = Encoding.UTF8.GetBytes("Endpoint Routing sample endpoints:" + Environment.NewLine + "/plaintext"); - private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); + private static readonly byte[] _plainTextPayload = Encoding.UTF8.GetBytes("Plain text!"); public void ConfigureServices(IServiceCollection services) { @@ -26,65 +22,59 @@ namespace RoutingSample.Web { options.ConstraintMap.Add("endsWith", typeof(EndsWithStringMatchProcessor)); }); - - var endpointDataSource = new DefaultEndpointDataSource(new[] - { - new MatcherEndpoint((next) => (httpContext) => - { - var response = httpContext.Response; - var payloadLength = _homePayload.Length; - response.StatusCode = 200; - response.ContentType = "text/plain"; - response.ContentLength = payloadLength; - return response.Body.WriteAsync(_homePayload, 0, payloadLength); - }, - RoutePatternFactory.Parse("/"), - 0, - EndpointMetadataCollection.Empty, - "Home"), - new MatcherEndpoint((next) => (httpContext) => - { - var response = httpContext.Response; - var payloadLength = _helloWorldPayload.Length; - response.StatusCode = 200; - response.ContentType = "text/plain"; - response.ContentLength = payloadLength; - return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength); - }, - RoutePatternFactory.Parse("/plaintext"), - 0, - EndpointMetadataCollection.Empty, - "Plaintext"), - new MatcherEndpoint((next) => (httpContext) => - { - var response = httpContext.Response; - response.StatusCode = 200; - response.ContentType = "text/plain"; - return response.WriteAsync("WithConstraints"); - }, - RoutePatternFactory.Parse("/withconstraints/{id:endsWith(_001)}"), - 0, - EndpointMetadataCollection.Empty, - "withconstraints"), - new MatcherEndpoint((next) => (httpContext) => - { - var response = httpContext.Response; - response.StatusCode = 200; - response.ContentType = "text/plain"; - return response.WriteAsync("withoptionalconstraints"); - }, - RoutePatternFactory.Parse("/withoptionalconstraints/{id:endsWith(_001)?}"), - 0, - EndpointMetadataCollection.Empty, - "withoptionalconstraints"), - }); - - services.TryAddEnumerable(ServiceDescriptor.Singleton(endpointDataSource)); } public void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app) { - app.UseEndpointRouting(); + app.UseEndpointRouting(builder => + { + builder.MapHello("/helloworld", "World"); + + builder.MapEndpoint( + (next) => (httpContext) => + { + var response = httpContext.Response; + var payloadLength = _homePayload.Length; + response.StatusCode = 200; + response.ContentType = "text/plain"; + response.ContentLength = payloadLength; + return response.Body.WriteAsync(_homePayload, 0, payloadLength); + }, + "/", + "Home"); + builder.MapEndpoint( + (next) => (httpContext) => + { + var response = httpContext.Response; + var payloadLength = _plainTextPayload.Length; + response.StatusCode = 200; + response.ContentType = "text/plain"; + response.ContentLength = payloadLength; + return response.Body.WriteAsync(_plainTextPayload, 0, payloadLength); + }, + "/plaintext", + "Plaintext"); + builder.MapEndpoint( + (next) => (httpContext) => + { + var response = httpContext.Response; + response.StatusCode = 200; + response.ContentType = "text/plain"; + return response.WriteAsync("WithConstraints"); + }, + "/withconstraints/{id:endsWith(_001)}", + "withconstraints"); + builder.MapEndpoint( + (next) => (httpContext) => + { + var response = httpContext.Response; + response.StatusCode = 200; + response.ContentType = "text/plain"; + return response.WriteAsync("withoptionalconstraints"); + }, + "/withoptionalconstraints/{id:endsWith(_001)?}", + "withoptionalconstraints"); + }); // Imagine some more stuff here... diff --git a/src/Microsoft.AspNetCore.Routing/Internal/EndpointRoutingApplicationBuilderExtensions.cs b/src/Microsoft.AspNetCore.Routing/Builder/EndpointRoutingApplicationBuilderExtensions.cs similarity index 79% rename from src/Microsoft.AspNetCore.Routing/Internal/EndpointRoutingApplicationBuilderExtensions.cs rename to src/Microsoft.AspNetCore.Routing/Builder/EndpointRoutingApplicationBuilderExtensions.cs index 281607cfba..f7c14801f3 100644 --- a/src/Microsoft.AspNetCore.Routing/Internal/EndpointRoutingApplicationBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Routing/Builder/EndpointRoutingApplicationBuilderExtensions.cs @@ -7,16 +7,28 @@ using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Internal; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.AspNetCore.Internal +namespace Microsoft.AspNetCore.Builder { public static class EndpointRoutingApplicationBuilderExtensions { private const string EndpointRoutingRegisteredKey = "__EndpointRoutingMiddlewareRegistered"; public static IApplicationBuilder UseEndpointRouting(this IApplicationBuilder builder) + { + return builder.UseEndpointRouting(null); + } + + public static IApplicationBuilder UseEndpointRouting(this IApplicationBuilder builder, Action configure) { VerifyRoutingIsRegistered(builder); + if (configure != null) + { + var dataSourceBuilder = (DefaultEndpointDataSourceBuilder)builder.ApplicationServices.GetRequiredService(); + dataSourceBuilder.ApplicationBuilder = builder; + configure(dataSourceBuilder); + } + builder.Properties[EndpointRoutingRegisteredKey] = true; return builder.UseMiddleware(); @@ -50,4 +62,4 @@ namespace Microsoft.AspNetCore.Internal } } } -} +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs b/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs new file mode 100644 index 0000000000..2a47a1b87b --- /dev/null +++ b/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs @@ -0,0 +1,69 @@ +// 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 Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Matching; +using Microsoft.AspNetCore.Routing.Patterns; + +namespace Microsoft.AspNetCore.Builder +{ + public static class MapEndpointEndpointDataSourceBuilderExtensions + { + public static MatcherEndpointBuilder MapEndpoint( + this EndpointDataSourceBuilder builder, + Func invoker, + string pattern, + string displayName) + { + return MapEndpoint(builder, invoker, pattern, displayName, metadata: null); + } + + public static MatcherEndpointBuilder MapEndpoint( + this EndpointDataSourceBuilder builder, + Func invoker, + RoutePattern pattern, + string displayName) + { + return MapEndpoint(builder, invoker, pattern, displayName, metadata: null); + } + + public static MatcherEndpointBuilder MapEndpoint( + this EndpointDataSourceBuilder builder, + Func invoker, + string pattern, + string displayName, + IList metadata) + { + return MapEndpoint(builder, invoker, RoutePatternFactory.Parse(pattern), displayName, metadata); + } + + public static MatcherEndpointBuilder MapEndpoint( + this EndpointDataSourceBuilder builder, + Func invoker, + RoutePattern pattern, + string displayName, + IList metadata) + { + const int defaultOrder = 0; + + var endpointBuilder = new MatcherEndpointBuilder( + invoker, + pattern, + defaultOrder); + endpointBuilder.DisplayName = displayName; + if (metadata != null) + { + foreach (var item in metadata) + { + endpointBuilder.Metadata.Add(item); + } + } + + builder.Endpoints.Add(endpointBuilder); + return endpointBuilder; + } + } +} diff --git a/src/Microsoft.AspNetCore.Routing/BuilderEndpointDataSource.cs b/src/Microsoft.AspNetCore.Routing/BuilderEndpointDataSource.cs new file mode 100644 index 0000000000..bf66ab8719 --- /dev/null +++ b/src/Microsoft.AspNetCore.Routing/BuilderEndpointDataSource.cs @@ -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.Linq; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.AspNetCore.Routing +{ + internal class BuilderEndpointDataSource : EndpointDataSource + { + private readonly EndpointDataSourceBuilder _builder; + + public BuilderEndpointDataSource(EndpointDataSourceBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + _builder = builder; + } + + public override IChangeToken GetChangeToken() + { + return NullChangeToken.Singleton; + } + + public override IReadOnlyList Endpoints => _builder.Endpoints.Select(b => b.Build()).ToArray(); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing/DefaultEndpointDataSourceBuilder.cs b/src/Microsoft.AspNetCore.Routing/DefaultEndpointDataSourceBuilder.cs new file mode 100644 index 0000000000..922a744cb7 --- /dev/null +++ b/src/Microsoft.AspNetCore.Routing/DefaultEndpointDataSourceBuilder.cs @@ -0,0 +1,17 @@ +// 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.Builder; + +namespace Microsoft.AspNetCore.Routing +{ + internal class DefaultEndpointDataSourceBuilder : EndpointDataSourceBuilder + { + public IApplicationBuilder ApplicationBuilder { get; set; } + + public override ICollection Endpoints { get; } = new List(); + + public override IApplicationBuilder CreateApplicationBuilder() => ApplicationBuilder.New(); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs index 19f3d0e77a..0c1e241a8c 100644 --- a/src/Microsoft.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs @@ -59,6 +59,12 @@ namespace Microsoft.Extensions.DependencyInjection return new CompositeEndpointDataSource(options.Value.DataSources); }); + // + // Endpoint Infrastructure + // + services.TryAddSingleton(); + services.TryAddSingleton(); + // // Default matcher implementation // diff --git a/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs b/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs new file mode 100644 index 0000000000..2187e387a3 --- /dev/null +++ b/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs @@ -0,0 +1,16 @@ +// 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 abstract class EndpointBuilder + { + public string DisplayName { get; set; } + + public IList Metadata { get; } = new List(); + + public abstract Endpoint Build(); + } +} diff --git a/src/Microsoft.AspNetCore.Routing/EndpointDataSourceBuilder.cs b/src/Microsoft.AspNetCore.Routing/EndpointDataSourceBuilder.cs new file mode 100644 index 0000000000..eea8b9afb2 --- /dev/null +++ b/src/Microsoft.AspNetCore.Routing/EndpointDataSourceBuilder.cs @@ -0,0 +1,15 @@ +// 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.Builder; + +namespace Microsoft.AspNetCore.Routing +{ + public abstract class EndpointDataSourceBuilder + { + public abstract ICollection Endpoints { get; } + + public abstract IApplicationBuilder CreateApplicationBuilder(); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs b/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs new file mode 100644 index 0000000000..c53112fea5 --- /dev/null +++ b/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs @@ -0,0 +1,41 @@ +// 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 Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing.Patterns; + +namespace Microsoft.AspNetCore.Routing.Matching +{ + public sealed class MatcherEndpointBuilder : EndpointBuilder + { + public Func Invoker { get; set; } + + public RoutePattern RoutePattern { get; set; } + + public int Order { get; set; } + + public MatcherEndpointBuilder( + Func invoker, + RoutePattern routePattern, + int order) + { + Invoker = invoker; + RoutePattern = routePattern; + Order = order; + } + + public override Endpoint Build() + { + var matcherEndpoint = new MatcherEndpoint( + Invoker, + RoutePattern, + Order, + new EndpointMetadataCollection(Metadata), + DisplayName); + + return matcherEndpoint; + } + } +} diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/EndpointRoutingSampleTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/EndpointRoutingSampleTest.cs index 5f059cae60..820841a9f4 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/EndpointRoutingSampleTest.cs +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/EndpointRoutingSampleTest.cs @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Routing.FunctionalTests { // Arrange var expectedContentType = "text/plain"; - var expectedContent = "Hello, World!"; + var expectedContent = "Plain text!"; // Act var response = await _client.GetAsync("/plaintext"); @@ -62,6 +62,25 @@ namespace Microsoft.AspNetCore.Routing.FunctionalTests Assert.Equal(expectedContent, actualContent); } + [Fact] + public async Task MatchesHelloMiddleware_AndReturnsPlaintext() + { + // Arrange + var expectedContentType = "text/plain"; + var expectedContent = "Hello World"; + + // Act + var response = await _client.GetAsync("/helloworld"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.NotNull(response.Content.Headers.ContentType); + Assert.Equal(expectedContentType, response.Content.Headers.ContentType.MediaType); + var actualContent = await response.Content.ReadAsStringAsync(); + Assert.Equal(expectedContent, actualContent); + } + [Fact] public async Task MatchesEndpoint_WithSuccessfulConstraintMatch() { diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingApplicationBuilderExtensionsTest.cs similarity index 83% rename from test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingBuilderExtensionsTest.cs rename to test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingApplicationBuilderExtensionsTest.cs index dd85fb11f6..8476676473 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Builder/EndpointRoutingApplicationBuilderExtensionsTest.cs @@ -5,7 +5,6 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder.Internal; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Moq; @@ -13,7 +12,7 @@ using Xunit; namespace Microsoft.AspNetCore.Builder { - public class EndpointRoutingBuilderExtensionsTest + public class EndpointRoutingApplicationBuilderExtensionsTest { [Fact] public void UseEndpointRouting_ServicesNotRegistered_Throws() @@ -109,6 +108,26 @@ namespace Microsoft.AspNetCore.Builder Assert.NotNull(httpContext.Features.Get()); } + [Fact] + public void UseEndpointRouting_CallWithBuilder_SetsEndpointBuilder() + { + // Arrange + var services = CreateServices(); + + var app = new ApplicationBuilder(services); + + // Act + app.UseEndpointRouting(builder => + { + builder.MapEndpoint(d => null, "/", "Test endpoint"); + }); + + // Assert + var dataSourceBuilder = (DefaultEndpointDataSourceBuilder)services.GetRequiredService(); + var endpointBuilder = Assert.Single(dataSourceBuilder.Endpoints); + Assert.Equal("Test endpoint", endpointBuilder.DisplayName); + } + private IServiceProvider CreateServices() { var services = new ServiceCollection(); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs new file mode 100644 index 0000000000..e854851fc8 --- /dev/null +++ b/test/Microsoft.AspNetCore.Routing.Tests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs @@ -0,0 +1,89 @@ +// 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 Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Matching; +using Microsoft.AspNetCore.Routing.Patterns; +using Xunit; + +namespace Microsoft.AspNetCore.Builder +{ + public class MapEndpointEndpointDataSourceBuilderExtensionsTest + { + [Fact] + public void MapEndpoint_StringPattern_BuildsEndpoint() + { + // Arrange + var builder = new DefaultEndpointDataSourceBuilder(); + Func invoker = (d) => null; + + // Act + var endpointBuilder = builder.MapEndpoint(invoker, "/", "Display name!"); + + // Assert + Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints)); + Assert.Equal(invoker, endpointBuilder.Invoker); + Assert.Equal("Display name!", endpointBuilder.DisplayName); + Assert.Equal("/", endpointBuilder.RoutePattern.RawText); + } + + [Fact] + public void MapEndpoint_TypedPattern_BuildsEndpoint() + { + // Arrange + var builder = new DefaultEndpointDataSourceBuilder(); + Func invoker = (d) => null; + + // Act + var endpointBuilder = builder.MapEndpoint(invoker, RoutePatternFactory.Parse("/"), "Display name!"); + + // Assert + Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints)); + Assert.Equal(invoker, endpointBuilder.Invoker); + Assert.Equal("Display name!", endpointBuilder.DisplayName); + Assert.Equal("/", endpointBuilder.RoutePattern.RawText); + } + + [Fact] + public void MapEndpoint_StringPatternAndMetadata_BuildsEndpoint() + { + // Arrange + var metadata = new object(); + var builder = new DefaultEndpointDataSourceBuilder(); + Func invoker = (d) => null; + + // Act + var endpointBuilder = builder.MapEndpoint(invoker, "/", "Display name!", new[] { metadata }); + + // Assert + Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints)); + Assert.Equal(invoker, endpointBuilder.Invoker); + Assert.Equal("Display name!", endpointBuilder.DisplayName); + Assert.Equal("/", endpointBuilder.RoutePattern.RawText); + Assert.Equal(metadata, Assert.Single(endpointBuilder.Metadata)); + } + + [Fact] + public void MapEndpoint_TypedPatternAndMetadata_BuildsEndpoint() + { + // Arrange + var metadata = new object(); + var builder = new DefaultEndpointDataSourceBuilder(); + Func invoker = (d) => null; + + // Act + var endpointBuilder = builder.MapEndpoint(invoker, RoutePatternFactory.Parse("/"), "Display name!", new[] { metadata }); + + // Assert + Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints)); + Assert.Equal(invoker, endpointBuilder.Invoker); + Assert.Equal("Display name!", endpointBuilder.DisplayName); + Assert.Equal("/", endpointBuilder.RoutePattern.RawText); + Assert.Equal(metadata, Assert.Single(endpointBuilder.Metadata)); + } + } +} diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs new file mode 100644 index 0000000000..acfc096914 --- /dev/null +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs @@ -0,0 +1,36 @@ +// 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 Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing.Patterns; +using Xunit; + +namespace Microsoft.AspNetCore.Routing.Matching +{ + public class MatcherEndpointBuilderTest + { + [Fact] + public void Build_AllValuesSet_EndpointCreated() + { + const int defaultOrder = 0; + object metadata = new object(); + Func invoker = (d) => null; + + var builder = new MatcherEndpointBuilder(invoker, RoutePatternFactory.Parse("/"), defaultOrder) + { + DisplayName = "Display name!", + Metadata = { metadata } + }; + + var endpoint = Assert.IsType(builder.Build()); + Assert.Equal("Display name!", endpoint.DisplayName); + Assert.Equal(defaultOrder, endpoint.Order); + Assert.Equal(invoker, endpoint.Invoker); + Assert.Equal("/", endpoint.RoutePattern.RawText); + Assert.Equal(metadata, Assert.Single(endpoint.Metadata)); + } + } +} From 8ccb8879cd839270f4815775e20a035f7118d2cb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 12 Aug 2018 20:13:10 +0000 Subject: [PATCH 05/17] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 54 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 6b937df71f..ecfcb0eadb 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,33 +4,33 @@ 0.10.13 - 3.0.0-alpha1-20180731.2 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 + 3.0.0-alpha1-20180810.1 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8f9f6066ef..e417a01b52 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180731.2 -commithash:1179f1083695ac9213c8a70a4d1d6c45a52caf41 +version:3.0.0-alpha1-20180810.1 +commithash:45c32b4f020e14a9295be31866051a18d293309d From 68dd5040a5d46dd303b701b81c949608abecc1a7 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 19 Aug 2018 19:27:46 +0000 Subject: [PATCH 06/17] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 54 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ecfcb0eadb..c6ef7197d4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,33 +4,33 @@ 0.10.13 - 3.0.0-alpha1-20180810.1 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 + 3.0.0-alpha1-20180817.3 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e417a01b52..e5330b3d33 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180810.1 -commithash:45c32b4f020e14a9295be31866051a18d293309d +version:3.0.0-alpha1-20180817.3 +commithash:134cdbee9bee29dd3ccb654c67663b27b9ffa6c8 From 5e8e490867cc5f246090281e074241ac9c6e07c8 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 22 Aug 2018 20:42:53 +1200 Subject: [PATCH 07/17] Merge fixes --- .../EndpointDataSourceBuilderExtensions.cs | 2 +- ...ointEndpointDataSourceBuilderExtensions.cs | 16 ++++++------- .../BuilderEndpointDataSource.cs | 1 + .../EndpointBuilder.cs | 1 + .../Matching/MatcherEndpointBuilder.cs | 10 ++++---- ...EndpointDataSourceBuilderExtensionsTest.cs | 24 +++++++++---------- .../Matching/MatcherEndpointBuilderTest.cs | 8 +++---- 7 files changed, 32 insertions(+), 30 deletions(-) diff --git a/samples/RoutingSample.Web/HelloExtension/EndpointDataSourceBuilderExtensions.cs b/samples/RoutingSample.Web/HelloExtension/EndpointDataSourceBuilderExtensions.cs index 6c2a4639a5..3d1f53673a 100644 --- a/samples/RoutingSample.Web/HelloExtension/EndpointDataSourceBuilderExtensions.cs +++ b/samples/RoutingSample.Web/HelloExtension/EndpointDataSourceBuilderExtensions.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Builder .Build(); return builder.MapEndpoint( - (next) => pipeline, + pipeline, template, "Hello"); } diff --git a/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs b/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs index 2a47a1b87b..f1e73ffde1 100644 --- a/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs @@ -14,35 +14,35 @@ namespace Microsoft.AspNetCore.Builder { public static MatcherEndpointBuilder MapEndpoint( this EndpointDataSourceBuilder builder, - Func invoker, + RequestDelegate requestDelegate, string pattern, string displayName) { - return MapEndpoint(builder, invoker, pattern, displayName, metadata: null); + return MapEndpoint(builder, requestDelegate, pattern, displayName, metadata: null); } public static MatcherEndpointBuilder MapEndpoint( this EndpointDataSourceBuilder builder, - Func invoker, + RequestDelegate requestDelegate, RoutePattern pattern, string displayName) { - return MapEndpoint(builder, invoker, pattern, displayName, metadata: null); + return MapEndpoint(builder, requestDelegate, pattern, displayName, metadata: null); } public static MatcherEndpointBuilder MapEndpoint( this EndpointDataSourceBuilder builder, - Func invoker, + RequestDelegate requestDelegate, string pattern, string displayName, IList metadata) { - return MapEndpoint(builder, invoker, RoutePatternFactory.Parse(pattern), displayName, metadata); + return MapEndpoint(builder, requestDelegate, RoutePatternFactory.Parse(pattern), displayName, metadata); } public static MatcherEndpointBuilder MapEndpoint( this EndpointDataSourceBuilder builder, - Func invoker, + RequestDelegate requestDelegate, RoutePattern pattern, string displayName, IList metadata) @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Builder const int defaultOrder = 0; var endpointBuilder = new MatcherEndpointBuilder( - invoker, + requestDelegate, pattern, defaultOrder); endpointBuilder.DisplayName = displayName; diff --git a/src/Microsoft.AspNetCore.Routing/BuilderEndpointDataSource.cs b/src/Microsoft.AspNetCore.Routing/BuilderEndpointDataSource.cs index bf66ab8719..d119f80ed2 100644 --- a/src/Microsoft.AspNetCore.Routing/BuilderEndpointDataSource.cs +++ b/src/Microsoft.AspNetCore.Routing/BuilderEndpointDataSource.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Primitives; diff --git a/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs b/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs index 2187e387a3..283c8a7cb6 100644 --- a/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs +++ b/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs @@ -2,6 +2,7 @@ // 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; namespace Microsoft.AspNetCore.Routing { diff --git a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs b/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs index c53112fea5..c351aeb4da 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs @@ -10,26 +10,26 @@ namespace Microsoft.AspNetCore.Routing.Matching { public sealed class MatcherEndpointBuilder : EndpointBuilder { - public Func Invoker { get; set; } + public RequestDelegate RequestDelegate { get; set; } public RoutePattern RoutePattern { get; set; } public int Order { get; set; } public MatcherEndpointBuilder( - Func invoker, + RequestDelegate requestDelegate, RoutePattern routePattern, int order) { - Invoker = invoker; + RequestDelegate = requestDelegate; RoutePattern = routePattern; Order = order; } public override Endpoint Build() { - var matcherEndpoint = new MatcherEndpoint( - Invoker, + var matcherEndpoint = new RouteEndpoint( + RequestDelegate, RoutePattern, Order, new EndpointMetadataCollection(Metadata), diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs index e854851fc8..5a425c3075 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs @@ -19,14 +19,14 @@ namespace Microsoft.AspNetCore.Builder { // Arrange var builder = new DefaultEndpointDataSourceBuilder(); - Func invoker = (d) => null; + RequestDelegate requestDelegate = (d) => null; // Act - var endpointBuilder = builder.MapEndpoint(invoker, "/", "Display name!"); + var endpointBuilder = builder.MapEndpoint(requestDelegate, "/", "Display name!"); // Assert Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints)); - Assert.Equal(invoker, endpointBuilder.Invoker); + Assert.Equal(requestDelegate, endpointBuilder.RequestDelegate); Assert.Equal("Display name!", endpointBuilder.DisplayName); Assert.Equal("/", endpointBuilder.RoutePattern.RawText); } @@ -36,14 +36,14 @@ namespace Microsoft.AspNetCore.Builder { // Arrange var builder = new DefaultEndpointDataSourceBuilder(); - Func invoker = (d) => null; + RequestDelegate requestDelegate = (d) => null; // Act - var endpointBuilder = builder.MapEndpoint(invoker, RoutePatternFactory.Parse("/"), "Display name!"); + var endpointBuilder = builder.MapEndpoint(requestDelegate, RoutePatternFactory.Parse("/"), "Display name!"); // Assert Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints)); - Assert.Equal(invoker, endpointBuilder.Invoker); + Assert.Equal(requestDelegate, endpointBuilder.RequestDelegate); Assert.Equal("Display name!", endpointBuilder.DisplayName); Assert.Equal("/", endpointBuilder.RoutePattern.RawText); } @@ -54,14 +54,14 @@ namespace Microsoft.AspNetCore.Builder // Arrange var metadata = new object(); var builder = new DefaultEndpointDataSourceBuilder(); - Func invoker = (d) => null; + RequestDelegate requestDelegate = (d) => null; // Act - var endpointBuilder = builder.MapEndpoint(invoker, "/", "Display name!", new[] { metadata }); + var endpointBuilder = builder.MapEndpoint(requestDelegate, "/", "Display name!", new[] { metadata }); // Assert Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints)); - Assert.Equal(invoker, endpointBuilder.Invoker); + Assert.Equal(requestDelegate, endpointBuilder.RequestDelegate); Assert.Equal("Display name!", endpointBuilder.DisplayName); Assert.Equal("/", endpointBuilder.RoutePattern.RawText); Assert.Equal(metadata, Assert.Single(endpointBuilder.Metadata)); @@ -73,14 +73,14 @@ namespace Microsoft.AspNetCore.Builder // Arrange var metadata = new object(); var builder = new DefaultEndpointDataSourceBuilder(); - Func invoker = (d) => null; + RequestDelegate requestDelegate = (d) => null; // Act - var endpointBuilder = builder.MapEndpoint(invoker, RoutePatternFactory.Parse("/"), "Display name!", new[] { metadata }); + var endpointBuilder = builder.MapEndpoint(requestDelegate, RoutePatternFactory.Parse("/"), "Display name!", new[] { metadata }); // Assert Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints)); - Assert.Equal(invoker, endpointBuilder.Invoker); + Assert.Equal(requestDelegate, endpointBuilder.RequestDelegate); Assert.Equal("Display name!", endpointBuilder.DisplayName); Assert.Equal("/", endpointBuilder.RoutePattern.RawText); Assert.Equal(metadata, Assert.Single(endpointBuilder.Metadata)); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs index acfc096914..3d6e44160b 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs @@ -17,18 +17,18 @@ namespace Microsoft.AspNetCore.Routing.Matching { const int defaultOrder = 0; object metadata = new object(); - Func invoker = (d) => null; + RequestDelegate requestDelegate = (d) => null; - var builder = new MatcherEndpointBuilder(invoker, RoutePatternFactory.Parse("/"), defaultOrder) + var builder = new MatcherEndpointBuilder(requestDelegate, RoutePatternFactory.Parse("/"), defaultOrder) { DisplayName = "Display name!", Metadata = { metadata } }; - var endpoint = Assert.IsType(builder.Build()); + var endpoint = Assert.IsType(builder.Build()); Assert.Equal("Display name!", endpoint.DisplayName); Assert.Equal(defaultOrder, endpoint.Order); - Assert.Equal(invoker, endpoint.Invoker); + Assert.Equal(requestDelegate, endpoint.RequestDelegate); Assert.Equal("/", endpoint.RoutePattern.RawText); Assert.Equal(metadata, Assert.Single(endpoint.Metadata)); } From 90d8f96b3fe0825ce51f88a926e94e3d1a7aa2e1 Mon Sep 17 00:00:00 2001 From: dotnet-maestro-bot Date: Thu, 23 Aug 2018 04:17:14 -0700 Subject: [PATCH 08/17] Change RoutePattern to not throw when inline and arg default value are the same (#747) (#748) --- .../Patterns/RoutePatternFactory.cs | 4 +-- .../Patterns/RoutePatternFactoryTest.cs | 25 ++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNetCore.Routing/Patterns/RoutePatternFactory.cs b/src/Microsoft.AspNetCore.Routing/Patterns/RoutePatternFactory.cs index f3309cf1b6..51b869c58c 100644 --- a/src/Microsoft.AspNetCore.Routing/Patterns/RoutePatternFactory.cs +++ b/src/Microsoft.AspNetCore.Routing/Patterns/RoutePatternFactory.cs @@ -343,7 +343,7 @@ namespace Microsoft.AspNetCore.Routing.Patterns if (updatedDefaults.TryGetValue(parameter.Name, out var newDefault)) { - if (parameter.Default != null) + if (parameter.Default != null && !Equals(newDefault, parameter.Default)) { var message = Resources.FormatTemplateRoute_CannotHaveDefaultValueSpecifiedInlineAndExplicitly(parameter.Name); throw new InvalidOperationException(message); @@ -360,7 +360,7 @@ namespace Microsoft.AspNetCore.Routing.Patterns if (parameter.Default != null) { - updatedDefaults.Add(parameter.Name, parameter.Default); + updatedDefaults[parameter.Name] = parameter.Default; } if (!updatedParameterPolicies.TryGetValue(parameter.Name, out var parameterConstraints) && diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Patterns/RoutePatternFactoryTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Patterns/RoutePatternFactoryTest.cs index 562d081d10..50d22c6a22 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Patterns/RoutePatternFactoryTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Patterns/RoutePatternFactoryTest.cs @@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Routing.Patterns } [Fact] - public void Pattern_DuplicateDefaultValue_Throws() + public void Pattern_DifferentDuplicateDefaultValue_Throws() { // Arrange var template = "{a=13}/{b}/{c}"; @@ -90,6 +90,29 @@ namespace Microsoft.AspNetCore.Routing.Patterns ex.Message); } + [Fact] + public void Pattern_SameDuplicateDefaultValue() + { + // Arrange + var template = "{a=13}/{b}/{c}"; + var defaults = new { a = "13", }; + var constraints = new { }; + + var original = RoutePatternFactory.Parse(template); + + // Act + var actual = RoutePatternFactory.Pattern( + original.RawText, + defaults, + constraints, + original.PathSegments); + + // Assert + Assert.Collection( + actual.Defaults, + kvp => { Assert.Equal("a", kvp.Key); Assert.Equal("13", kvp.Value); }); + } + [Fact] public void Pattern_OptionalParameterDefaultValue_Throws() { From 5d77bead7c55ea2ff2d71ef2fcbbbcecefb09e3b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 26 Aug 2018 19:27:28 +0000 Subject: [PATCH 09/17] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 54 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 2e29b921e1..9ec97d2b15 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,33 +4,33 @@ 0.10.13 - 3.0.0-alpha1-20180817.3 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 + 3.0.0-alpha1-20180821.3 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e5330b3d33..767a471795 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180817.3 -commithash:134cdbee9bee29dd3ccb654c67663b27b9ffa6c8 +version:3.0.0-alpha1-20180821.3 +commithash:0939a90812deb1c604eb9a4768869687495fc1dd From e73601dda962cf3d9ecae8f3fc24b9c64f637e05 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 29 Aug 2018 17:07:35 +1200 Subject: [PATCH 10/17] Move core endpoint types to HttpAbstractions (#703) --- benchmarkapps/Benchmarks/Benchmarks.csproj | 7 + ...indCandidateSetSmallEntryCountBenchmark.cs | 2 +- build/dependencies.props | 6 +- .../RoutingSample.Web.csproj | 7 +- .../Endpoint.cs | 49 - .../EndpointMetadataCollection.cs | 201 -- .../IEndpointFeature.cs | 18 - .../IRouteValuesFeature.cs | 16 - .../Properties/AssemblyInfo.cs | 9 + .../Properties/Resources.Designer.cs | 58 - .../Resources.resx | 126 -- .../RouteValueDictionary.cs | 598 ------ .../EndpointMetadataCollectionTests.cs | 142 -- .../RouteValueDictionaryTests.cs | 1621 ----------------- ....AspNetCore.Routing.FunctionalTests.csproj | 4 + .../EndpointFactory.cs | 5 +- .../Matching/MatcherConformanceTest.cs | 5 +- 17 files changed, 37 insertions(+), 2837 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.Routing.Abstractions/Endpoint.cs delete mode 100644 src/Microsoft.AspNetCore.Routing.Abstractions/EndpointMetadataCollection.cs delete mode 100644 src/Microsoft.AspNetCore.Routing.Abstractions/IEndpointFeature.cs delete mode 100644 src/Microsoft.AspNetCore.Routing.Abstractions/IRouteValuesFeature.cs delete mode 100644 src/Microsoft.AspNetCore.Routing.Abstractions/Properties/Resources.Designer.cs delete mode 100644 src/Microsoft.AspNetCore.Routing.Abstractions/Resources.resx delete mode 100644 src/Microsoft.AspNetCore.Routing.Abstractions/RouteValueDictionary.cs delete mode 100644 test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/EndpointMetadataCollectionTests.cs delete mode 100644 test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/RouteValueDictionaryTests.cs diff --git a/benchmarkapps/Benchmarks/Benchmarks.csproj b/benchmarkapps/Benchmarks/Benchmarks.csproj index 3c5753cc64..25c8132528 100644 --- a/benchmarkapps/Benchmarks/Benchmarks.csproj +++ b/benchmarkapps/Benchmarks/Benchmarks.csproj @@ -4,6 +4,7 @@ netcoreapp2.2 $(BenchmarksTargetFramework) true + NU1605 @@ -12,10 +13,16 @@ + + + + + + diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSmallEntryCountBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSmallEntryCountBenchmark.cs index 993dabc419..96b938825c 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSmallEntryCountBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matching/MatcherFindCandidateSetSmallEntryCountBenchmark.cs @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Routing.Matching private TrivialMatcher _baseline; private DfaMatcher _dfa; - private EndpointFeature _feature; + private IEndpointFeature _feature; [GlobalSetup] public void Setup() diff --git a/build/dependencies.props b/build/dependencies.props index 9ec97d2b15..8ec9ffd4c7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -9,9 +9,9 @@ 3.0.0-alpha1-10352 3.0.0-alpha1-10352 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 + 3.0.0-a-alpha1-endpoint-routing-types-16724 + 3.0.0-a-alpha1-endpoint-routing-types-16724 + 3.0.0-a-alpha1-endpoint-routing-types-16724 3.0.0-alpha1-10352 3.0.0-alpha1-10352 3.0.0-alpha1-10352 diff --git a/samples/RoutingSample.Web/RoutingSample.Web.csproj b/samples/RoutingSample.Web/RoutingSample.Web.csproj index 52b1699c7b..0597915057 100644 --- a/samples/RoutingSample.Web/RoutingSample.Web.csproj +++ b/samples/RoutingSample.Web/RoutingSample.Web.csproj @@ -1,8 +1,9 @@ - + netcoreapp2.2 $(TargetFrameworks);net461 + NU1605 @@ -10,6 +11,10 @@ + + + + diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/Endpoint.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/Endpoint.cs deleted file mode 100644 index 16202b45f5..0000000000 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/Endpoint.cs +++ /dev/null @@ -1,49 +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.Http -{ - /// - /// Respresents a logical endpoint in an application. - /// - public class Endpoint - { - /// - /// Creates a new instance of . - /// - /// The delegate used to process requests for the endpoint. - /// - /// The endpoint . May be null. - /// - /// - /// The informational display name of the endpoint. May be null. - /// - public Endpoint( - RequestDelegate requestDelegate, - EndpointMetadataCollection metadata, - string displayName) - { - // All are allowed to be null - RequestDelegate = requestDelegate; - Metadata = metadata ?? EndpointMetadataCollection.Empty; - DisplayName = displayName; - } - - /// - /// Gets the informational display name of this endpoint. - /// - public string DisplayName { get; } - - /// - /// Gets the collection of metadata associated with this endpoint. - /// - public EndpointMetadataCollection Metadata { get; } - - /// - /// Gets the delegate used to process requests for the endpoint. - /// - public RequestDelegate RequestDelegate { get; } - - public override string ToString() => DisplayName ?? base.ToString(); - } -} diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/EndpointMetadataCollection.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/EndpointMetadataCollection.cs deleted file mode 100644 index a792fff295..0000000000 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/EndpointMetadataCollection.cs +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; - -namespace Microsoft.AspNetCore.Http -{ - /// - /// A collection of arbitrary metadata associated with an endpoint. - /// - /// - /// instances contain a list of metadata items - /// of arbitrary types. The metadata items are stored as an ordered collection with - /// items arranged in ascending order of precedence. - /// - public sealed class EndpointMetadataCollection : IReadOnlyList - { - /// - /// An empty . - /// - public static readonly EndpointMetadataCollection Empty = new EndpointMetadataCollection(Array.Empty()); - - private readonly object[] _items; - private readonly ConcurrentDictionary _cache; - - /// - /// Creates a new . - /// - /// The metadata items. - public EndpointMetadataCollection(IEnumerable items) - { - if (items == null) - { - throw new ArgumentNullException(nameof(items)); - } - - _items = items.ToArray(); - _cache = new ConcurrentDictionary(); - } - - /// - /// Creates a new . - /// - /// The metadata items. - public EndpointMetadataCollection(params object[] items) - : this((IEnumerable)items) - { - } - - /// - /// Gets the item at . - /// - /// The index of the item to retrieve. - /// The item at . - public object this[int index] => _items[index]; - - /// - /// Gets the count of metadata items. - /// - public int Count => _items.Length; - - /// - /// Gets the most significant metadata item of type . - /// - /// The type of metadata to retrieve. - /// - /// The most significant metadata of type or null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public T GetMetadata() where T : class - { - if (_cache.TryGetValue(typeof(T), out var result)) - { - var length = result.Length; - return length > 0 ? (T)result[length - 1] : default; - } - - return GetMetadataSlow(); - } - - private T GetMetadataSlow() where T : class - { - var array = GetOrderedMetadataSlow(); - var length = array.Length; - return length > 0 ? array[length - 1] : default; - } - - /// - /// Gets the metadata items of type in ascending - /// order of precedence. - /// - /// The type of metadata. - /// A sequence of metadata items of . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetOrderedMetadata() where T : class - { - if (_cache.TryGetValue(typeof(T), out var result)) - { - return (T[])result; - } - - return GetOrderedMetadataSlow(); - } - - private T[] GetOrderedMetadataSlow() where T : class - { - var items = new List(); - for (var i = 0; i < _items.Length; i++) - { - if (_items[i] is T item) - { - items.Add(item); - } - } - - var array = items.ToArray(); - _cache.TryAdd(typeof(T), array); - return array; - } - - /// - /// Gets an of all metadata items. - /// - /// An of all metadata items. - public Enumerator GetEnumerator() => new Enumerator(this); - - /// - /// Gets an of all metadata items. - /// - /// An of all metadata items. - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// Gets an of all metadata items. - /// - /// An of all metadata items. - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// Enumerates the elements of an . - /// - public struct Enumerator : IEnumerator - { - // Intentionally not readonly to prevent defensive struct copies - private object[] _items; - private int _index; - - internal Enumerator(EndpointMetadataCollection collection) - { - _items = collection._items; - _index = 0; - Current = null; - } - - /// - /// Gets the element at the current position of the enumerator - /// - public object Current { get; private set; } - - /// - /// Releases all resources used by the . - /// - public void Dispose() - { - } - - /// - /// Advances the enumerator to the next element of the . - /// - /// - /// true if the enumerator was successfully advanced to the next element; - /// false if the enumerator has passed the end of the collection. - /// - public bool MoveNext() - { - if (_index < _items.Length) - { - Current = _items[_index++]; - return true; - } - - Current = null; - return false; - } - - /// - /// Sets the enumerator to its initial position, which is before the first element in the collection. - /// - public void Reset() - { - _index = 0; - Current = null; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/IEndpointFeature.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/IEndpointFeature.cs deleted file mode 100644 index ff0762bb20..0000000000 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/IEndpointFeature.cs +++ /dev/null @@ -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.Http.Features -{ - /// - /// A feature interface for endpoint routing. Use - /// to access an instance associated with the current request. - /// - public interface IEndpointFeature - { - /// - /// Gets or sets the selected for the current - /// request. - /// - Endpoint Endpoint { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/IRouteValuesFeature.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/IRouteValuesFeature.cs deleted file mode 100644 index 3ab74b6bc7..0000000000 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/IRouteValuesFeature.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Routing; - -namespace Microsoft.AspNetCore.Http.Features -{ - public interface IRouteValuesFeature - { - /// - /// Gets or sets the associated with the currrent - /// request. - /// - RouteValueDictionary RouteValues { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/AssemblyInfo.cs index fc39ed7ef2..fc9a32648f 100644 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/AssemblyInfo.cs @@ -2,6 +2,15 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Runtime.CompilerServices; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; + +[assembly: TypeForwardedTo(typeof(IEndpointFeature))] +[assembly: TypeForwardedTo(typeof(IRouteValuesFeature))] +[assembly: TypeForwardedTo(typeof(Endpoint))] +[assembly: TypeForwardedTo(typeof(EndpointMetadataCollection))] +[assembly: TypeForwardedTo(typeof(RouteValueDictionary))] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/Resources.Designer.cs deleted file mode 100644 index 8fdf6b8715..0000000000 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/Resources.Designer.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -namespace Microsoft.AspNetCore.Routing.Abstractions -{ - using System.Globalization; - using System.Reflection; - using System.Resources; - - internal static class Resources - { - private static readonly ResourceManager _resourceManager - = new ResourceManager("Microsoft.AspNetCore.Routing.Abstractions.Resources", typeof(Resources).GetTypeInfo().Assembly); - - /// - /// An element with the key '{0}' already exists in the {1}. - /// - internal static string RouteValueDictionary_DuplicateKey - { - get => GetString("RouteValueDictionary_DuplicateKey"); - } - - /// - /// An element with the key '{0}' already exists in the {1}. - /// - internal static string FormatRouteValueDictionary_DuplicateKey(object p0, object p1) - => string.Format(CultureInfo.CurrentCulture, GetString("RouteValueDictionary_DuplicateKey"), p0, p1); - - /// - /// The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. - /// - internal static string RouteValueDictionary_DuplicatePropertyName - { - get => GetString("RouteValueDictionary_DuplicatePropertyName"); - } - - /// - /// The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. - /// - internal static string FormatRouteValueDictionary_DuplicatePropertyName(object p0, object p1, object p2, object p3) - => string.Format(CultureInfo.CurrentCulture, GetString("RouteValueDictionary_DuplicatePropertyName"), p0, p1, p2, p3); - - private static string GetString(string name, params string[] formatterNames) - { - var value = _resourceManager.GetString(name); - - System.Diagnostics.Debug.Assert(value != null); - - if (formatterNames != null) - { - for (var i = 0; i < formatterNames.Length; i++) - { - value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); - } - } - - return value; - } - } -} diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/Resources.resx b/src/Microsoft.AspNetCore.Routing.Abstractions/Resources.resx deleted file mode 100644 index 40e651af14..0000000000 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/Resources.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - An element with the key '{0}' already exists in the {1}. - - - The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/RouteValueDictionary.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/RouteValueDictionary.cs deleted file mode 100644 index 2d30f6f25f..0000000000 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/RouteValueDictionary.cs +++ /dev/null @@ -1,598 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using Microsoft.AspNetCore.Routing.Abstractions; -using Microsoft.Extensions.Internal; - -namespace Microsoft.AspNetCore.Routing -{ - /// - /// An type for route values. - /// - public class RouteValueDictionary : IDictionary, IReadOnlyDictionary - { - // 4 is a good default capacity here because that leaves enough space for area/controller/action/id - private const int DefaultCapacity = 4; - - internal KeyValuePair[] _arrayStorage; - internal PropertyStorage _propertyStorage; - private int _count; - - /// - /// Creates a new from the provided array. - /// The new instance will take ownership of the array, and may mutate it. - /// - /// The items array. - /// A new . - public static RouteValueDictionary FromArray(KeyValuePair[] items) - { - if (items == null) - { - throw new ArgumentNullException(nameof(items)); - } - - // We need to compress the array by removing non-contiguous items. We - // typically have a very small number of items to process. We don't need - // to preserve order. - var start = 0; - var end = items.Length - 1; - - // We walk forwards from the beginning of the array and fill in 'null' slots. - // We walk backwards from the end of the array end move items in non-null' slots - // into whatever start is pointing to. O(n) - while (start <= end) - { - if (items[start].Key != null) - { - start++; - } - else if (items[end].Key != null) - { - // Swap this item into start and advance - items[start] = items[end]; - items[end] = default; - start++; - end--; - } - else - { - // Both null, we need to hold on 'start' since we - // still need to fill it with something. - end--; - } - } - - return new RouteValueDictionary() - { - _arrayStorage = items, - _count = start, - }; - } - - /// - /// Creates an empty . - /// - public RouteValueDictionary() - { - _arrayStorage = Array.Empty>(); - } - - /// - /// Creates a initialized with the specified . - /// - /// An object to initialize the dictionary. The value can be of type - /// or - /// or an object with public properties as key-value pairs. - /// - /// - /// If the value is a dictionary or other of , - /// then its entries are copied. Otherwise the object is interpreted as a set of key-value pairs where the - /// property names are keys, and property values are the values, and copied into the dictionary. - /// Only public instance non-index properties are considered. - /// - public RouteValueDictionary(object values) - : this() - { - if (values is RouteValueDictionary dictionary) - { - if (dictionary._propertyStorage != null) - { - // PropertyStorage is immutable so we can just copy it. - _propertyStorage = dictionary._propertyStorage; - _count = dictionary._count; - return; - } - - var other = dictionary._arrayStorage; - var storage = new KeyValuePair[other.Length]; - if (dictionary._count != 0) - { - Array.Copy(other, 0, storage, 0, dictionary._count); - } - - _arrayStorage = storage; - _count = dictionary._count; - return; - } - - if (values is IEnumerable> keyValueEnumerable) - { - foreach (var kvp in keyValueEnumerable) - { - Add(kvp.Key, kvp.Value); - } - - return; - } - - if (values is IEnumerable> stringValueEnumerable) - { - foreach (var kvp in stringValueEnumerable) - { - Add(kvp.Key, kvp.Value); - } - - return; - } - - if (values != null) - { - var storage = new PropertyStorage(values); - _propertyStorage = storage; - _count = storage.Properties.Length; - return; - } - } - - /// - public object this[string key] - { - get - { - if (string.IsNullOrEmpty(key)) - { - throw new ArgumentNullException(nameof(key)); - } - - object value; - TryGetValue(key, out value); - return value; - } - - set - { - if (string.IsNullOrEmpty(key)) - { - throw new ArgumentNullException(nameof(key)); - } - - // We're calling this here for the side-effect of converting from properties - // to array. We need to create the array even if we just set an existing value since - // property storage is immutable. - EnsureCapacity(_count); - - var index = FindInArray(key); - if (index < 0) - { - EnsureCapacity(_count + 1); - _arrayStorage[_count++] = new KeyValuePair(key, value); - } - else - { - _arrayStorage[index] = new KeyValuePair(key, value); - } - } - } - - /// - /// Gets the comparer for this dictionary. - /// - /// - /// This will always be a reference to - /// - public IEqualityComparer Comparer => StringComparer.OrdinalIgnoreCase; - - /// - public int Count => _count; - - /// - bool ICollection>.IsReadOnly => false; - - /// - public ICollection Keys - { - get - { - EnsureCapacity(_count); - - var array = _arrayStorage; - var keys = new string[_count]; - for (var i = 0; i < keys.Length; i++) - { - keys[i] = array[i].Key; - } - - return keys; - } - } - - IEnumerable IReadOnlyDictionary.Keys => Keys; - - /// - public ICollection Values - { - get - { - EnsureCapacity(_count); - - var array = _arrayStorage; - var values = new object[_count]; - for (var i = 0; i < values.Length; i++) - { - values[i] = array[i].Value; - } - - return values; - } - } - - IEnumerable IReadOnlyDictionary.Values => Values; - - /// - void ICollection>.Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - - /// - public void Add(string key, object value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - EnsureCapacity(_count + 1); - - var index = FindInArray(key); - if (index >= 0) - { - var message = Resources.FormatRouteValueDictionary_DuplicateKey(key, nameof(RouteValueDictionary)); - throw new ArgumentException(message, nameof(key)); - } - - _arrayStorage[_count] = new KeyValuePair(key, value); - _count++; - } - - /// - public void Clear() - { - if (_count == 0) - { - return; - } - - if (_propertyStorage != null) - { - _arrayStorage = Array.Empty>(); - _propertyStorage = null; - _count = 0; - return; - } - - Array.Clear(_arrayStorage, 0, _count); - _count = 0; - } - - /// - bool ICollection>.Contains(KeyValuePair item) - { - return TryGetValue(item.Key, out var value) && EqualityComparer.Default.Equals(value, item.Value); - } - - /// - public bool ContainsKey(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - return TryGetValue(key, out var _); - } - - /// - void ICollection>.CopyTo( - KeyValuePair[] array, - int arrayIndex) - { - if (array == null) - { - throw new ArgumentNullException(nameof(array)); - } - - if (arrayIndex < 0 || arrayIndex > array.Length || array.Length - arrayIndex < this.Count) - { - throw new ArgumentOutOfRangeException(nameof(arrayIndex)); - } - - if (Count == 0) - { - return; - } - - EnsureCapacity(Count); - - var storage = _arrayStorage; - Array.Copy(storage, 0, array, arrayIndex, _count); - } - - /// - public Enumerator GetEnumerator() - { - return new Enumerator(this); - } - - /// - IEnumerator> IEnumerable>.GetEnumerator() - { - return GetEnumerator(); - } - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - bool ICollection>.Remove(KeyValuePair item) - { - if (Count == 0) - { - return false; - } - - EnsureCapacity(Count); - - var index = FindInArray(item.Key); - var array = _arrayStorage; - if (index >= 0 && EqualityComparer.Default.Equals(array[index].Value, item.Value)) - { - Array.Copy(array, index + 1, array, index, _count - index); - _count--; - array[_count] = default; - return true; - } - - return false; - } - - /// - public bool Remove(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - if (Count == 0) - { - return false; - } - - EnsureCapacity(Count); - - var index = FindInArray(key); - if (index >= 0) - { - _count--; - var array = _arrayStorage; - Array.Copy(array, index + 1, array, index, _count - index); - array[_count] = default; - - return true; - } - - return false; - } - - /// - public bool TryGetValue(string key, out object value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - if (_propertyStorage != null) - { - var storage = _propertyStorage; - for (var i = 0; i < storage.Properties.Length; i++) - { - if (string.Equals(storage.Properties[i].Name, key, StringComparison.OrdinalIgnoreCase)) - { - value = storage.Properties[i].GetValue(storage.Value); - return true; - } - } - - value = default; - return false; - } - - var array = _arrayStorage; - for (var i = 0; i < _count; i++) - { - if (string.Equals(array[i].Key, key, StringComparison.OrdinalIgnoreCase)) - { - value = array[i].Value; - return true; - } - } - - value = default; - return false; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void EnsureCapacity(int capacity) - { - if (_propertyStorage != null || _arrayStorage.Length < capacity) - { - EnsureCapacitySlow(capacity); - } - } - - private void EnsureCapacitySlow(int capacity) - { - if (_propertyStorage != null) - { - var storage = _propertyStorage; - capacity = Math.Max(storage.Properties.Length, capacity); - var array = new KeyValuePair[capacity]; - - for (var i = 0; i < storage.Properties.Length; i++) - { - var property = storage.Properties[i]; - array[i] = new KeyValuePair(property.Name, property.GetValue(storage.Value)); - } - - _arrayStorage = array; - _propertyStorage = null; - return; - } - - if (_arrayStorage.Length < capacity) - { - capacity = _arrayStorage.Length == 0 ? DefaultCapacity : _arrayStorage.Length * 2; - var array = new KeyValuePair[capacity]; - if (_count > 0) - { - Array.Copy(_arrayStorage, 0, array, 0, _count); - } - - _arrayStorage = array; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int FindInArray(string key) - { - var array = _arrayStorage; - for (var i = 0; i < _count; i++) - { - if (string.Equals(array[i].Key, key, StringComparison.OrdinalIgnoreCase)) - { - return i; - } - } - - return -1; - } - - public struct Enumerator : IEnumerator> - { - private RouteValueDictionary _dictionary; - private int _index; - - public Enumerator(RouteValueDictionary dictionary) - { - if (dictionary == null) - { - throw new ArgumentNullException(); - } - - _dictionary = dictionary; - - Current = default; - _index = -1; - } - - public KeyValuePair Current { get; private set; } - - object IEnumerator.Current => Current; - - public void Dispose() - { - } - - public bool MoveNext() - { - if (++_index < _dictionary.Count) - { - if (_dictionary._propertyStorage != null) - { - var storage = _dictionary._propertyStorage; - var property = storage.Properties[_index]; - Current = new KeyValuePair(property.Name, property.GetValue(storage.Value)); - return true; - } - - Current = _dictionary._arrayStorage[_index]; - return true; - } - - Current = default; - return false; - } - - public void Reset() - { - Current = default; - _index = -1; - } - } - - internal class PropertyStorage - { - private static readonly ConcurrentDictionary _propertyCache = new ConcurrentDictionary(); - - public readonly object Value; - public readonly PropertyHelper[] Properties; - - public PropertyStorage(object value) - { - Debug.Assert(value != null); - Value = value; - - // Cache the properties so we can know if we've already validated them for duplicates. - var type = Value.GetType(); - if (!_propertyCache.TryGetValue(type, out Properties)) - { - Properties = PropertyHelper.GetVisibleProperties(type); - ValidatePropertyNames(type, Properties); - _propertyCache.TryAdd(type, Properties); - } - } - - private static void ValidatePropertyNames(Type type, PropertyHelper[] properties) - { - var names = new Dictionary(StringComparer.OrdinalIgnoreCase); - for (var i = 0; i < properties.Length; i++) - { - var property = properties[i]; - - if (names.TryGetValue(property.Name, out var duplicate)) - { - var message = Resources.FormatRouteValueDictionary_DuplicatePropertyName( - type.FullName, - property.Name, - duplicate.Name, - nameof(RouteValueDictionary)); - throw new InvalidOperationException(message); - } - - names.Add(property.Name, property); - } - } - } - } -} diff --git a/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/EndpointMetadataCollectionTests.cs b/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/EndpointMetadataCollectionTests.cs deleted file mode 100644 index 9f37f3ebec..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/EndpointMetadataCollectionTests.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.AspNetCore.Http; -using Xunit; - -namespace Microsoft.AspNetCore.Routing -{ - public class EndpointMetadataCollectionTests - { - [Fact] - public void Constructor_Enumeration_ContainsValues() - { - // Arrange & Act - var metadata = new EndpointMetadataCollection(new List - { - 1, - 2, - 3, - }); - - // Assert - Assert.Equal(3, metadata.Count); - - Assert.Collection(metadata, - value => Assert.Equal(1, value), - value => Assert.Equal(2, value), - value => Assert.Equal(3, value)); - } - - [Fact] - public void Constructor_ParamsArray_ContainsValues() - { - // Arrange & Act - var metadata = new EndpointMetadataCollection(1, 2, 3); - - // Assert - Assert.Equal(3, metadata.Count); - - Assert.Collection(metadata, - value => Assert.Equal(1, value), - value => Assert.Equal(2, value), - value => Assert.Equal(3, value)); - } - - [Fact] - public void GetMetadata_Match_ReturnsLastMatchingEntry() - { - // Arrange - var items = new object[] - { - new Metadata1(), - new Metadata2(), - new Metadata3(), - }; - - var metadata = new EndpointMetadataCollection(items); - - // Act - var result = metadata.GetMetadata(); - - // Assert - Assert.Same(items[1], result); - } - - [Fact] - public void GetMetadata_NoMatch_ReturnsNull() - { - // Arrange - var items = new object[] - { - new Metadata3(), - new Metadata3(), - new Metadata3(), - }; - - var metadata = new EndpointMetadataCollection(items); - - // Act - var result = metadata.GetMetadata(); - - // Assert - Assert.Null(result); - } - - [Fact] - public void GetOrderedMetadata_Match_ReturnsItemsInAscendingOrder() - { - // Arrange - var items = new object[] - { - new Metadata1(), - new Metadata2(), - new Metadata3(), - }; - - var metadata = new EndpointMetadataCollection(items); - - // Act - var result = metadata.GetOrderedMetadata(); - - // Assert - Assert.Collection( - result, - i => Assert.Same(items[0], i), - i => Assert.Same(items[1], i)); - } - - [Fact] - public void GetOrderedMetadata_NoMatch_ReturnsEmpty() - { - // Arrange - var items = new object[] - { - new Metadata3(), - new Metadata3(), - new Metadata3(), - }; - - var metadata = new EndpointMetadataCollection(items); - - // Act - var result = metadata.GetOrderedMetadata(); - - // Assert - Assert.Empty(result); - } - - private interface IMetadata1 { } - private interface IMetadata2 { } - private interface IMetadata3 { } - private interface IMetadata4 { } - private interface IMetadata5 { } - private class Metadata1 : IMetadata1, IMetadata4, IMetadata5 { } - private class Metadata2 : IMetadata2, IMetadata5 { } - private class Metadata3 : IMetadata3 { } - - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/RouteValueDictionaryTests.cs b/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/RouteValueDictionaryTests.cs deleted file mode 100644 index 5cb45fc14c..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/RouteValueDictionaryTests.cs +++ /dev/null @@ -1,1621 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Testing; -using Xunit; - -namespace Microsoft.AspNetCore.Routing.Tests -{ - public class RouteValueDictionaryTests - { - [Fact] - public void DefaultCtor_UsesEmptyStorage() - { - // Arrange - // Act - var dict = new RouteValueDictionary(); - - // Assert - Assert.Empty(dict); - Assert.Empty(dict._arrayStorage); - Assert.Null(dict._propertyStorage); - } - - [Fact] - public void CreateFromNull_UsesEmptyStorage() - { - // Arrange - // Act - var dict = new RouteValueDictionary(null); - - // Assert - Assert.Empty(dict); - Assert.Empty(dict._arrayStorage); - Assert.Null(dict._propertyStorage); - } - - [Fact] - public void CreateFromRouteValueDictionary_WithArrayStorage_CopiesStorage() - { - // Arrange - var other = new RouteValueDictionary() - { - { "1", 1 } - }; - - // Act - var dict = new RouteValueDictionary(other); - - // Assert - Assert.Equal(other, dict); - - var storage = Assert.IsType[]>(dict._arrayStorage); - var otherStorage = Assert.IsType[]>(other._arrayStorage); - Assert.NotSame(otherStorage, storage); - } - - [Fact] - public void CreateFromRouteValueDictionary_WithPropertyStorage_CopiesStorage() - { - // Arrange - var other = new RouteValueDictionary(new { key = "value" }); - - // Act - var dict = new RouteValueDictionary(other); - - // Assert - Assert.Equal(other, dict); - - var storage = dict._propertyStorage; - var otherStorage = other._propertyStorage; - Assert.Same(otherStorage, storage); - } - - public static IEnumerable IEnumerableKeyValuePairData - { - get - { - var routeValues = new[] - { - new KeyValuePair("Name", "James"), - new KeyValuePair("Age", 30), - new KeyValuePair("Address", new Address() { City = "Redmond", State = "WA" }) - }; - - yield return new object[] { routeValues.ToDictionary(kvp => kvp.Key, kvp => kvp.Value) }; - - yield return new object[] { routeValues.ToList() }; - - yield return new object[] { routeValues }; - } - } - - public static IEnumerable IEnumerableStringValuePairData - { - get - { - var routeValues = new[] - { - new KeyValuePair("First Name", "James"), - new KeyValuePair("Last Name", "Henrik"), - new KeyValuePair("Middle Name", "Bob") - }; - - yield return new object[] { routeValues.ToDictionary(kvp => kvp.Key, kvp => kvp.Value) }; - - yield return new object[] { routeValues.ToList() }; - - yield return new object[] { routeValues }; - } - } - - [Theory] - [MemberData(nameof(IEnumerableKeyValuePairData))] - public void CreateFromIEnumerableKeyValuePair_CopiesValues(object values) - { - // Arrange & Act - var dict = new RouteValueDictionary(values); - - // Assert - Assert.IsType[]>(dict._arrayStorage); - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => - { - Assert.Equal("Address", kvp.Key); - var address = Assert.IsType
(kvp.Value); - Assert.Equal("Redmond", address.City); - Assert.Equal("WA", address.State); - }, - kvp => { Assert.Equal("Age", kvp.Key); Assert.Equal(30, kvp.Value); }, - kvp => { Assert.Equal("Name", kvp.Key); Assert.Equal("James", kvp.Value); }); - } - - [Theory] - [MemberData(nameof(IEnumerableStringValuePairData))] - public void CreateFromIEnumerableStringValuePair_CopiesValues(object values) - { - // Arrange & Act - var dict = new RouteValueDictionary(values); - - // Assert - Assert.IsType[]>(dict._arrayStorage); - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("First Name", kvp.Key); Assert.Equal("James", kvp.Value); }, - kvp => { Assert.Equal("Last Name", kvp.Key); Assert.Equal("Henrik", kvp.Value); }, - kvp => { Assert.Equal("Middle Name", kvp.Key); Assert.Equal("Bob", kvp.Value); }); - } - - [Fact] - public void CreateFromIEnumerableKeyValuePair_ThrowsExceptionForDuplicateKey() - { - // Arrange - var values = new List>() - { - new KeyValuePair("name", "Billy"), - new KeyValuePair("Name", "Joey"), - }; - - // Act & Assert - ExceptionAssert.ThrowsArgument( - () => new RouteValueDictionary(values), - "key", - $"An element with the key 'Name' already exists in the {nameof(RouteValueDictionary)}."); - } - - [Fact] - public void CreateFromIEnumerableStringValuePair_ThrowsExceptionForDuplicateKey() - { - // Arrange - var values = new List>() - { - new KeyValuePair("name", "Billy"), - new KeyValuePair("Name", "Joey"), - }; - - // Act & Assert - ExceptionAssert.ThrowsArgument( - () => new RouteValueDictionary(values), - "key", - $"An element with the key 'Name' already exists in the {nameof(RouteValueDictionary)}."); - } - - [Fact] - public void CreateFromObject_CopiesPropertiesFromAnonymousType() - { - // Arrange - var obj = new { cool = "beans", awesome = 123 }; - - // Act - var dict = new RouteValueDictionary(obj); - - // Assert - Assert.NotNull(dict._propertyStorage); - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("awesome", kvp.Key); Assert.Equal(123, kvp.Value); }, - kvp => { Assert.Equal("cool", kvp.Key); Assert.Equal("beans", kvp.Value); }); - } - - [Fact] - public void CreateFromObject_CopiesPropertiesFromRegularType() - { - // Arrange - var obj = new RegularType() { CoolnessFactor = 73 }; - - // Act - var dict = new RouteValueDictionary(obj); - - // Assert - Assert.NotNull(dict._propertyStorage); - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => - { - Assert.Equal("CoolnessFactor", kvp.Key); - Assert.Equal(73, kvp.Value); - }, - kvp => - { - Assert.Equal("IsAwesome", kvp.Key); - var value = Assert.IsType(kvp.Value); - Assert.False(value); - }); - } - - [Fact] - public void CreateFromObject_CopiesPropertiesFromRegularType_PublicOnly() - { - // Arrange - var obj = new Visibility() { IsPublic = true, ItsInternalDealWithIt = 5 }; - - // Act - var dict = new RouteValueDictionary(obj); - - // Assert - Assert.NotNull(dict._propertyStorage); - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => - { - Assert.Equal("IsPublic", kvp.Key); - var value = Assert.IsType(kvp.Value); - Assert.True(value); - }); - } - - [Fact] - public void CreateFromObject_CopiesPropertiesFromRegularType_IgnoresStatic() - { - // Arrange - var obj = new StaticProperty(); - - // Act - var dict = new RouteValueDictionary(obj); - - // Assert - Assert.NotNull(dict._propertyStorage); - Assert.Empty(dict); - } - - [Fact] - public void CreateFromObject_CopiesPropertiesFromRegularType_IgnoresSetOnly() - { - // Arrange - var obj = new SetterOnly() { CoolSetOnly = false }; - - // Act - var dict = new RouteValueDictionary(obj); - - // Assert - Assert.NotNull(dict._propertyStorage); - Assert.Empty(dict); - } - - [Fact] - public void CreateFromObject_CopiesPropertiesFromRegularType_IncludesInherited() - { - // Arrange - var obj = new Derived() { TotallySweetProperty = true, DerivedProperty = false }; - - // Act - var dict = new RouteValueDictionary(obj); - - // Assert - Assert.NotNull(dict._propertyStorage); - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => - { - Assert.Equal("DerivedProperty", kvp.Key); - var value = Assert.IsType(kvp.Value); - Assert.False(value); - }, - kvp => - { - Assert.Equal("TotallySweetProperty", kvp.Key); - var value = Assert.IsType(kvp.Value); - Assert.True(value); - }); - } - - [Fact] - public void CreateFromObject_CopiesPropertiesFromRegularType_WithHiddenProperty() - { - // Arrange - var obj = new DerivedHiddenProperty() { DerivedProperty = 5 }; - - // Act - var dict = new RouteValueDictionary(obj); - - // Assert - Assert.NotNull(dict._propertyStorage); - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("DerivedProperty", kvp.Key); Assert.Equal(5, kvp.Value); }); - } - - [Fact] - public void CreateFromObject_CopiesPropertiesFromRegularType_WithIndexerProperty() - { - // Arrange - var obj = new IndexerProperty(); - - // Act - var dict = new RouteValueDictionary(obj); - - // Assert - Assert.NotNull(dict._propertyStorage); - Assert.Empty(dict); - } - - [Fact] - public void CreateFromObject_MixedCaseThrows() - { - // Arrange - var obj = new { controller = "Home", Controller = "Home" }; - - var message = - $"The type '{obj.GetType().FullName}' defines properties 'controller' and 'Controller' which differ " + - $"only by casing. This is not supported by {nameof(RouteValueDictionary)} which uses " + - $"case-insensitive comparisons."; - - // Act & Assert - var exception = Assert.Throws(() => - { - var dictionary = new RouteValueDictionary(obj); - }); - - // Ignoring case to make sure we're not testing reflection's ordering. - Assert.Equal(message, exception.Message, ignoreCase: true); - } - - // Our comparer is hardcoded to be OrdinalIgnoreCase no matter what. - [Fact] - public void Comparer_IsOrdinalIgnoreCase() - { - // Arrange - // Act - var dict = new RouteValueDictionary(); - - // Assert - Assert.Same(StringComparer.OrdinalIgnoreCase, dict.Comparer); - } - - // Our comparer is hardcoded to be IsReadOnly==false no matter what. - [Fact] - public void IsReadOnly_False() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - var result = ((ICollection>)dict).IsReadOnly; - - // Assert - Assert.False(result); - } - - [Fact] - public void IndexGet_EmptyStorage_ReturnsNull() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - var value = dict["key"]; - - // Assert - Assert.Null(value); - } - - [Fact] - public void IndexGet_PropertyStorage_NoMatch_ReturnsNull() - { - // Arrange - var dict = new RouteValueDictionary(new { age = 30 }); - - // Act - var value = dict["key"]; - - // Assert - Assert.Null(value); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void IndexGet_PropertyStorage_Match_ReturnsValue() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - var value = dict["key"]; - - // Assert - Assert.Equal("value", value); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void IndexGet_PropertyStorage_MatchIgnoreCase_ReturnsValue() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - var value = dict["kEy"]; - - // Assert - Assert.Equal("value", value); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void IndexGet_ArrayStorage_NoMatch_ReturnsNull() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "age", 30 }, - }; - - // Act - var value = dict["key"]; - - // Assert - Assert.Null(value); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexGet_ListStorage_Match_ReturnsValue() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var value = dict["key"]; - - // Assert - Assert.Equal("value", value); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexGet_ListStorage_MatchIgnoreCase_ReturnsValue() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var value = dict["kEy"]; - - // Assert - Assert.Equal("value", value); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexSet_EmptyStorage_UpgradesToList() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - dict["key"] = "value"; - - // Assert - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexSet_PropertyStorage_NoMatch_AddsValue() - { - // Arrange - var dict = new RouteValueDictionary(new { age = 30 }); - - // Act - dict["key"] = "value"; - - // Assert - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, - kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexSet_PropertyStorage_Match_SetsValue() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - dict["key"] = "value"; - - // Assert - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexSet_PropertyStorage_MatchIgnoreCase_SetsValue() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - dict["kEy"] = "value"; - - // Assert - Assert.Collection(dict, kvp => { Assert.Equal("kEy", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexSet_ListStorage_NoMatch_AddsValue() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "age", 30 }, - }; - - // Act - dict["key"] = "value"; - - // Assert - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, - kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexSet_ListStorage_Match_SetsValue() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - dict["key"] = "value"; - - // Assert - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void IndexSet_ListStorage_MatchIgnoreCase_SetsValue() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - dict["key"] = "value"; - - // Assert - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Count_EmptyStorage() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - var count = dict.Count; - - // Assert - Assert.Equal(0, count); - } - - [Fact] - public void Count_PropertyStorage() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value", }); - - // Act - var count = dict.Count; - - // Assert - Assert.Equal(1, count); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void Count_ListStorage() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var count = dict.Count; - - // Assert - Assert.Equal(1, count); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Keys_EmptyStorage() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - var keys = dict.Keys; - - // Assert - Assert.Empty(keys); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Keys_PropertyStorage() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value", }); - - // Act - var keys = dict.Keys; - - // Assert - Assert.Equal(new[] { "key" }, keys); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Keys_ListStorage() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var keys = dict.Keys; - - // Assert - Assert.Equal(new[] { "key" }, keys); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Values_EmptyStorage() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - var values = dict.Values; - - // Assert - Assert.Empty(values); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Values_PropertyStorage() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value", }); - - // Act - var values = dict.Values; - - // Assert - Assert.Equal(new object[] { "value" }, values); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Values_ListStorage() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var values = dict.Values; - - // Assert - Assert.Equal(new object[] { "value" }, values); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Add_EmptyStorage() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - dict.Add("key", "value"); - - // Assert - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Add_PropertyStorage() - { - // Arrange - var dict = new RouteValueDictionary(new { age = 30 }); - - // Act - dict.Add("key", "value"); - - // Assert - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, - kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Add_ListStorage() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "age", 30 }, - }; - - // Act - dict.Add("key", "value"); - - // Assert - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, - kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Add_DuplicateKey() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var message = $"An element with the key 'key' already exists in the {nameof(RouteValueDictionary)}"; - - // Act & Assert - ExceptionAssert.ThrowsArgument(() => dict.Add("key", "value2"), "key", message); - - // Assert - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Add_DuplicateKey_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var message = $"An element with the key 'kEy' already exists in the {nameof(RouteValueDictionary)}"; - - // Act & Assert - ExceptionAssert.ThrowsArgument(() => dict.Add("kEy", "value2"), "key", message); - - // Assert - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Add_KeyValuePair() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "age", 30 }, - }; - - // Act - ((ICollection>)dict).Add(new KeyValuePair("key", "value")); - - // Assert - Assert.Collection( - dict.OrderBy(kvp => kvp.Key), - kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, - kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Clear_EmptyStorage() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - dict.Clear(); - - // Assert - Assert.Empty(dict); - } - - [Fact] - public void Clear_PropertyStorage_AlreadyEmpty() - { - // Arrange - var dict = new RouteValueDictionary(new { }); - - // Act - dict.Clear(); - - // Assert - Assert.Empty(dict); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void Clear_PropertyStorage() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - dict.Clear(); - - // Assert - Assert.Empty(dict); - Assert.Null(dict._propertyStorage); - } - - [Fact] - public void Clear_ListStorage() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - dict.Clear(); - - // Assert - Assert.Empty(dict); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Contains_KeyValuePair_True() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var input = new KeyValuePair("key", "value"); - - // Act - var result = ((ICollection>)dict).Contains(input); - - // Assert - Assert.True(result); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Contains_KeyValuePair_True_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var input = new KeyValuePair("KEY", "value"); - - // Act - var result = ((ICollection>)dict).Contains(input); - - // Assert - Assert.True(result); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Contains_KeyValuePair_False() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var input = new KeyValuePair("other", "value"); - - // Act - var result = ((ICollection>)dict).Contains(input); - - // Assert - Assert.False(result); - Assert.IsType[]>(dict._arrayStorage); - } - - // Value comparisons use the default equality comparer. - [Fact] - public void Contains_KeyValuePair_False_ValueComparisonIsDefault() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var input = new KeyValuePair("key", "valUE"); - - // Act - var result = ((ICollection>)dict).Contains(input); - - // Assert - Assert.False(result); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void ContainsKey_EmptyStorage() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - var result = dict.ContainsKey("key"); - - // Assert - Assert.False(result); - } - - [Fact] - public void ContainsKey_PropertyStorage_False() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - var result = dict.ContainsKey("other"); - - // Assert - Assert.False(result); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void ContainsKey_PropertyStorage_True() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - var result = dict.ContainsKey("key"); - - // Assert - Assert.True(result); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void ContainsKey_PropertyStorage_True_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - var result = dict.ContainsKey("kEy"); - - // Assert - Assert.True(result); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void ContainsKey_ListStorage_False() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var result = dict.ContainsKey("other"); - - // Assert - Assert.False(result); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void ContainsKey_ListStorage_True() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var result = dict.ContainsKey("key"); - - // Assert - Assert.True(result); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void ContainsKey_ListStorage_True_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var result = dict.ContainsKey("kEy"); - - // Assert - Assert.True(result); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void CopyTo() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var array = new KeyValuePair[2]; - - // Act - ((ICollection>)dict).CopyTo(array, 1); - - // Assert - Assert.Equal( - new KeyValuePair[] - { - default(KeyValuePair), - new KeyValuePair("key", "value") - }, - array); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_KeyValuePair_True() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var input = new KeyValuePair("key", "value"); - - // Act - var result = ((ICollection>)dict).Remove(input); - - // Assert - Assert.True(result); - Assert.Empty(dict); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_KeyValuePair_True_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var input = new KeyValuePair("KEY", "value"); - - // Act - var result = ((ICollection>)dict).Remove(input); - - // Assert - Assert.True(result); - Assert.Empty(dict); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_KeyValuePair_False() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var input = new KeyValuePair("other", "value"); - - // Act - var result = ((ICollection>)dict).Remove(input); - - // Assert - Assert.False(result); - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - // Value comparisons use the default equality comparer. - [Fact] - public void Remove_KeyValuePair_False_ValueComparisonIsDefault() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - var input = new KeyValuePair("key", "valUE"); - - // Act - var result = ((ICollection>)dict).Remove(input); - - // Assert - Assert.False(result); - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_EmptyStorage() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - var result = dict.Remove("key"); - - // Assert - Assert.False(result); - } - - [Fact] - public void Remove_PropertyStorage_Empty() - { - // Arrange - var dict = new RouteValueDictionary(new { }); - - // Act - var result = dict.Remove("other"); - - // Assert - Assert.False(result); - Assert.Empty(dict); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void Remove_PropertyStorage_False() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - var result = dict.Remove("other"); - - // Assert - Assert.False(result); - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_PropertyStorage_True() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - var result = dict.Remove("key"); - - // Assert - Assert.True(result); - Assert.Empty(dict); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_PropertyStorage_True_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - var result = dict.Remove("kEy"); - - // Assert - Assert.True(result); - Assert.Empty(dict); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_ListStorage_False() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var result = dict.Remove("other"); - - // Assert - Assert.False(result); - Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_ListStorage_True() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var result = dict.Remove("key"); - - // Assert - Assert.True(result); - Assert.Empty(dict); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void Remove_ListStorage_True_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - var result = dict.Remove("kEy"); - - // Assert - Assert.True(result); - Assert.Empty(dict); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void TryGetValue_EmptyStorage() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act - object value; - var result = dict.TryGetValue("key", out value); - - // Assert - Assert.False(result); - Assert.Null(value); - } - - [Fact] - public void TryGetValue_PropertyStorage_False() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - object value; - var result = dict.TryGetValue("other", out value); - - // Assert - Assert.False(result); - Assert.Null(value); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void TryGetValue_PropertyStorage_True() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - object value; - var result = dict.TryGetValue("key", out value); - - // Assert - Assert.True(result); - Assert.Equal("value", value); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void TryGetValue_PropertyStorage_True_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); - - // Act - object value; - var result = dict.TryGetValue("kEy", out value); - - // Assert - Assert.True(result); - Assert.Equal("value", value); - Assert.NotNull(dict._propertyStorage); - } - - [Fact] - public void TryGetValue_ListStorage_False() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - object value; - var result = dict.TryGetValue("other", out value); - - // Assert - Assert.False(result); - Assert.Null(value); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void TryGetValue_ListStorage_True() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - object value; - var result = dict.TryGetValue("key", out value); - - // Assert - Assert.True(result); - Assert.Equal("value", value); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void TryGetValue_ListStorage_True_CaseInsensitive() - { - // Arrange - var dict = new RouteValueDictionary() - { - { "key", "value" }, - }; - - // Act - object value; - var result = dict.TryGetValue("kEy", out value); - - // Assert - Assert.True(result); - Assert.Equal("value", value); - Assert.IsType[]>(dict._arrayStorage); - } - - [Fact] - public void ListStorage_DynamicallyAdjustsCapacity() - { - // Arrange - var dict = new RouteValueDictionary(); - - // Act 1 - dict.Add("key", "value"); - - // Assert 1 - var storage = Assert.IsType[]>(dict._arrayStorage); - Assert.Equal(4, storage.Length); - - // Act 2 - dict.Add("key2", "value2"); - dict.Add("key3", "value3"); - dict.Add("key4", "value4"); - dict.Add("key5", "value5"); - - // Assert 2 - storage = Assert.IsType[]>(dict._arrayStorage); - Assert.Equal(8, storage.Length); - } - - [Fact] - public void ListStorage_RemoveAt_RearrangesInnerArray() - { - // Arrange - var dict = new RouteValueDictionary(); - dict.Add("key", "value"); - dict.Add("key2", "value2"); - dict.Add("key3", "value3"); - - // Assert 1 - var storage = Assert.IsType[]>(dict._arrayStorage); - Assert.Equal(3, dict.Count); - - // Act - dict.Remove("key2"); - - // Assert 2 - storage = Assert.IsType[]>(dict._arrayStorage); - Assert.Equal(2, dict.Count); - Assert.Equal("key", storage[0].Key); - Assert.Equal("value", storage[0].Value); - Assert.Equal("key3", storage[1].Key); - Assert.Equal("value3", storage[1].Value); - } - - [Fact] - public void FromArray_TakesOwnershipOfArray() - { - // Arrange - var array = new KeyValuePair[] - { - new KeyValuePair("a", 0), - new KeyValuePair("b", 1), - new KeyValuePair("c", 2), - }; - - var dictionary = RouteValueDictionary.FromArray(array); - - // Act - modifying the array should modify the dictionary - array[0] = new KeyValuePair("aa", 10); - - // Assert - Assert.Equal(3, dictionary.Count); - Assert.Equal(10, dictionary["aa"]); - } - - [Fact] - public void FromArray_EmptyArray() - { - // Arrange - var array = Array.Empty>(); - - // Act - var dictionary = RouteValueDictionary.FromArray(array); - - // Assert - Assert.Empty(dictionary); - } - - [Fact] - public void FromArray_RemovesGapsInArray() - { - // Arrange - var array = new KeyValuePair[] - { - new KeyValuePair(null, null), - new KeyValuePair("a", 0), - new KeyValuePair(null, null), - new KeyValuePair(null, null), - new KeyValuePair("b", 1), - new KeyValuePair("c", 2), - new KeyValuePair("d", 3), - new KeyValuePair(null, null), - }; - - // Act - calling From should modify the array - var dictionary = RouteValueDictionary.FromArray(array); - - // Assert - Assert.Equal(4, dictionary.Count); - Assert.Equal( - new KeyValuePair[] - { - new KeyValuePair("d", 3), - new KeyValuePair("a", 0), - new KeyValuePair("c", 2), - new KeyValuePair("b", 1), - new KeyValuePair(null, null), - new KeyValuePair(null, null), - new KeyValuePair(null, null), - new KeyValuePair(null, null), - }, - array); - } - - private class RegularType - { - public bool IsAwesome { get; set; } - - public int CoolnessFactor { get; set; } - } - - private class Visibility - { - private string PrivateYo { get; set; } - - internal int ItsInternalDealWithIt { get; set; } - - public bool IsPublic { get; set; } - } - - private class StaticProperty - { - public static bool IsStatic { get; set; } - } - - private class SetterOnly - { - private bool _coolSetOnly; - - public bool CoolSetOnly { set { _coolSetOnly = value; } } - } - - private class Base - { - public bool DerivedProperty { get; set; } - } - - private class Derived : Base - { - public bool TotallySweetProperty { get; set; } - } - - private class DerivedHiddenProperty : Base - { - public new int DerivedProperty { get; set; } - } - - private class IndexerProperty - { - public bool this[string key] - { - get { return false; } - set { } - } - } - - private class Address - { - public string City { get; set; } - - public string State { get; set; } - } - } -} diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj index 9520c32ff5..8305c160dc 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj @@ -2,6 +2,7 @@ $(StandardTestTfms) + NU1605 @@ -14,6 +15,9 @@ + + + diff --git a/test/Microsoft.AspNetCore.Routing.Tests/EndpointFactory.cs b/test/Microsoft.AspNetCore.Routing.Tests/EndpointFactory.cs index 3ae4b79517..43f4446479 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/EndpointFactory.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/EndpointFactory.cs @@ -1,10 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Routing.Patterns; using System; using System.Collections.Generic; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing.Matching; +using Microsoft.AspNetCore.Routing.Patterns; namespace Microsoft.AspNetCore.Routing { diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.cs index 45673bb525..06f4e14a73 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherConformanceTest.cs @@ -21,7 +21,10 @@ namespace Microsoft.AspNetCore.Routing.Matching httpContext.Request.Path = path; httpContext.RequestServices = CreateServices(); - var feature = new EndpointFeature(); + var feature = new EndpointFeature + { + RouteValues = new RouteValueDictionary() + }; httpContext.Features.Set(feature); httpContext.Features.Set(feature); From 4ab067fb37594ee41f39cbd9be6ef276325ece2f Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 5 Sep 2018 09:27:46 +1200 Subject: [PATCH 11/17] Temporarily remove obsolete attribute to unblock build (#775) --- .../DefaultInlineConstraintResolver.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.Routing/DefaultInlineConstraintResolver.cs b/src/Microsoft.AspNetCore.Routing/DefaultInlineConstraintResolver.cs index 1ed1f8e1ab..ad4570a89c 100644 --- a/src/Microsoft.AspNetCore.Routing/DefaultInlineConstraintResolver.cs +++ b/src/Microsoft.AspNetCore.Routing/DefaultInlineConstraintResolver.cs @@ -24,7 +24,8 @@ namespace Microsoft.AspNetCore.Routing /// /// Accessor for containing the constraints of interest. /// - [Obsolete("This constructor is obsolete. Use DefaultInlineConstraintResolver.ctor(IOptions, IServiceProvider) instead.")] + // TODO: Temporarily remove obsolete attribute to unblock build + //[Obsolete("This constructor is obsolete. Use DefaultInlineConstraintResolver.ctor(IOptions, IServiceProvider) instead.")] public DefaultInlineConstraintResolver(IOptions routeOptions) { _inlineConstraintMap = routeOptions.Value.ConstraintMap; From 21427fea0f27fb2e05710b7ebf5d49cbe9801e87 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 5 Sep 2018 23:59:18 +0000 Subject: [PATCH 12/17] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1bfc9c6427..ca8f3400e0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,37 +5,37 @@ 0.10.13 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-a-alpha1-endpoint-routing-types-16724 - 3.0.0-a-alpha1-endpoint-routing-types-16724 - 3.0.0-a-alpha1-endpoint-routing-types-16724 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 2.0.9 - 2.1.2 - 2.2.0-preview1-26618-02 + 2.1.3 + 2.2.0-preview2-26905-02 15.6.1 - 4.7.49 + 4.9.0 2.0.3 11.0.2 4.3.0 From 27a0951a8897a5a7c41e90d58ceb73c72d060b1c Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 7 Sep 2018 13:34:10 +1200 Subject: [PATCH 13/17] Update dependencies and re-mark obsolete constructor (#783) --- benchmarkapps/Benchmarks/Benchmarks.csproj | 7 ------- samples/RoutingSample.Web/RoutingSample.Web.csproj | 5 ----- .../DefaultInlineConstraintResolver.cs | 3 +-- .../Microsoft.AspNetCore.Routing.FunctionalTests.csproj | 4 ---- 4 files changed, 1 insertion(+), 18 deletions(-) diff --git a/benchmarkapps/Benchmarks/Benchmarks.csproj b/benchmarkapps/Benchmarks/Benchmarks.csproj index 25c8132528..3c5753cc64 100644 --- a/benchmarkapps/Benchmarks/Benchmarks.csproj +++ b/benchmarkapps/Benchmarks/Benchmarks.csproj @@ -4,7 +4,6 @@ netcoreapp2.2 $(BenchmarksTargetFramework) true - NU1605 @@ -13,16 +12,10 @@ - - - - - - diff --git a/samples/RoutingSample.Web/RoutingSample.Web.csproj b/samples/RoutingSample.Web/RoutingSample.Web.csproj index 0597915057..731de09658 100644 --- a/samples/RoutingSample.Web/RoutingSample.Web.csproj +++ b/samples/RoutingSample.Web/RoutingSample.Web.csproj @@ -3,7 +3,6 @@ netcoreapp2.2 $(TargetFrameworks);net461 - NU1605 @@ -11,10 +10,6 @@ - - - - diff --git a/src/Microsoft.AspNetCore.Routing/DefaultInlineConstraintResolver.cs b/src/Microsoft.AspNetCore.Routing/DefaultInlineConstraintResolver.cs index ad4570a89c..1ed1f8e1ab 100644 --- a/src/Microsoft.AspNetCore.Routing/DefaultInlineConstraintResolver.cs +++ b/src/Microsoft.AspNetCore.Routing/DefaultInlineConstraintResolver.cs @@ -24,8 +24,7 @@ namespace Microsoft.AspNetCore.Routing /// /// Accessor for containing the constraints of interest. /// - // TODO: Temporarily remove obsolete attribute to unblock build - //[Obsolete("This constructor is obsolete. Use DefaultInlineConstraintResolver.ctor(IOptions, IServiceProvider) instead.")] + [Obsolete("This constructor is obsolete. Use DefaultInlineConstraintResolver.ctor(IOptions, IServiceProvider) instead.")] public DefaultInlineConstraintResolver(IOptions routeOptions) { _inlineConstraintMap = routeOptions.Value.ConstraintMap; diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj index 8305c160dc..9520c32ff5 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj @@ -2,7 +2,6 @@ $(StandardTestTfms) - NU1605 @@ -15,9 +14,6 @@ - - - From e6ff157b5f6dbeddf82492bbda7fadc54c0995c5 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Thu, 6 Sep 2018 16:31:10 -0700 Subject: [PATCH 14/17] Add a test for Routing#435 This was already fixes as part of the LinkGenerator redesign. Adding a test so we can mark it as complete. --- ...DefaultLinkGeneratorProcessTemplateTest.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/Microsoft.AspNetCore.Routing.Tests/DefaultLinkGeneratorProcessTemplateTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/DefaultLinkGeneratorProcessTemplateTest.cs index ea202ff786..1e603824f2 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/DefaultLinkGeneratorProcessTemplateTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/DefaultLinkGeneratorProcessTemplateTest.cs @@ -277,6 +277,38 @@ namespace Microsoft.AspNetCore.Routing Assert.Equal(string.Empty, result.query.ToUriComponent()); } + // Regression test for aspnet/Routing#435 + // + // In this issue we used to lowercase URLs after parameters were encoded, meaning that if a character needed + // encoding (such as a cyrillic character, it would not be encoded). + [Fact] + public void TryProcessTemplate_GeneratesLowercaseUrl_SetOnRouteOptions_CanLowercaseCharactersThatNeedEncoding() + { + // Arrange + var endpoint = EndpointFactory.CreateRouteEndpoint("{controller}/{action}"); + var linkGenerator = CreateLinkGenerator(new RouteOptions() { LowercaseUrls = true }, endpoints: new[] { endpoint, }); + var httpContext = CreateHttpContext(ambientValues: new { controller = "Home" }); + + // Act + var success = linkGenerator.TryProcessTemplate( + httpContext: httpContext, + endpoint: endpoint, + ambientValues: DefaultLinkGenerator.GetAmbientValues(httpContext), + explicitValues: new RouteValueDictionary(new { action = "П" }), // Cryillic uppercase Pe + options: null, + out var result); + + // Assert + Assert.True(success); + Assert.Equal("/home/%D0%BF", result.path.ToUriComponent()); + Assert.Equal(string.Empty, result.query.ToUriComponent()); + + // Convert back to decoded. + // + // This is Cyrillic lowercase Pe (not an n). + Assert.Equal("/home/п", PathString.FromUriComponent(result.path.ToUriComponent()).Value); + } + [Fact] public void TryProcessTemplate_GeneratesLowercaseQueryString_SetOnRouteOptions() { From fc3cfac27611a2f600245ccdbacc75310917b4bd Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 9 Sep 2018 19:28:52 +0000 Subject: [PATCH 15/17] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 54 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ca8f3400e0..03a593dfc5 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,33 +4,33 @@ 0.10.13 - 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 + 3.0.0-alpha1-20180907.9 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 767a471795..b614cab6e8 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180821.3 -commithash:0939a90812deb1c604eb9a4768869687495fc1dd +version:3.0.0-alpha1-20180907.9 +commithash:f997365a8832ff0a3cbd9a98df45734ac2723fa0 From 9df59182397a1aef9c3049cac93ac7307204e208 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Thu, 13 Sep 2018 10:27:01 +1200 Subject: [PATCH 16/17] Clean up endpoint builder (#791) --- .../RoutingSample.Web/UseEndpointRoutingStartup.cs | 12 +++--------- ...pEndpointEndpointDataSourceBuilderExtensions.cs | 14 +++++++------- .../EndpointBuilder.cs | 2 ++ ...rEndpointBuilder.cs => RouteEndpointBuilder.cs} | 10 +++------- .../Matching/MatcherEndpointBuilderTest.cs | 2 +- 5 files changed, 16 insertions(+), 24 deletions(-) rename src/Microsoft.AspNetCore.Routing/{Matching/MatcherEndpointBuilder.cs => RouteEndpointBuilder.cs} (77%) diff --git a/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs b/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs index 27cf177d19..e8928b8200 100644 --- a/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs +++ b/samples/RoutingSample.Web/UseEndpointRoutingStartup.cs @@ -93,7 +93,7 @@ namespace RoutingSample.Web }, "/graph", "DFA Graph", - new object[] { new HttpMethodMetadata(new[] { "GET", }) }); + new HttpMethodMetadata(new[] { "GET", })); builder.MapEndpoint( (httpContext) => { @@ -107,10 +107,7 @@ namespace RoutingSample.Web }, "/WithSingleAsteriskCatchAll/{*path}", "WithSingleAsteriskCatchAll", - new object[] - { - new RouteValuesAddressMetadata(routeName: "WithSingleAsteriskCatchAll", requiredValues: new RouteValueDictionary()), - }); + new RouteValuesAddressMetadata(routeName: "WithSingleAsteriskCatchAll", requiredValues: new RouteValueDictionary())); builder.MapEndpoint( (httpContext) => { @@ -124,10 +121,7 @@ namespace RoutingSample.Web }, "/WithDoubleAsteriskCatchAll/{**path}", "WithDoubleAsteriskCatchAll", - new object[] - { - new RouteValuesAddressMetadata(routeName: "WithDoubleAsteriskCatchAll", requiredValues: new RouteValueDictionary()) - }); + new RouteValuesAddressMetadata(routeName: "WithDoubleAsteriskCatchAll", requiredValues: new RouteValueDictionary())); }); // Imagine some more stuff here... diff --git a/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs b/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs index f1e73ffde1..fca430da9a 100644 --- a/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Routing/Builder/MapEndpointEndpointDataSourceBuilderExtensions.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Builder { public static class MapEndpointEndpointDataSourceBuilderExtensions { - public static MatcherEndpointBuilder MapEndpoint( + public static RouteEndpointBuilder MapEndpoint( this EndpointDataSourceBuilder builder, RequestDelegate requestDelegate, string pattern, @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Builder return MapEndpoint(builder, requestDelegate, pattern, displayName, metadata: null); } - public static MatcherEndpointBuilder MapEndpoint( + public static RouteEndpointBuilder MapEndpoint( this EndpointDataSourceBuilder builder, RequestDelegate requestDelegate, RoutePattern pattern, @@ -30,26 +30,26 @@ namespace Microsoft.AspNetCore.Builder return MapEndpoint(builder, requestDelegate, pattern, displayName, metadata: null); } - public static MatcherEndpointBuilder MapEndpoint( + public static RouteEndpointBuilder MapEndpoint( this EndpointDataSourceBuilder builder, RequestDelegate requestDelegate, string pattern, string displayName, - IList metadata) + params object[] metadata) { return MapEndpoint(builder, requestDelegate, RoutePatternFactory.Parse(pattern), displayName, metadata); } - public static MatcherEndpointBuilder MapEndpoint( + public static RouteEndpointBuilder MapEndpoint( this EndpointDataSourceBuilder builder, RequestDelegate requestDelegate, RoutePattern pattern, string displayName, - IList metadata) + params object[] metadata) { const int defaultOrder = 0; - var endpointBuilder = new MatcherEndpointBuilder( + var endpointBuilder = new RouteEndpointBuilder( requestDelegate, pattern, defaultOrder); diff --git a/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs b/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs index 283c8a7cb6..27d64f1625 100644 --- a/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs +++ b/src/Microsoft.AspNetCore.Routing/EndpointBuilder.cs @@ -8,6 +8,8 @@ namespace Microsoft.AspNetCore.Routing { public abstract class EndpointBuilder { + public RequestDelegate RequestDelegate { get; set; } + public string DisplayName { get; set; } public IList Metadata { get; } = new List(); diff --git a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs b/src/Microsoft.AspNetCore.Routing/RouteEndpointBuilder.cs similarity index 77% rename from src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs rename to src/Microsoft.AspNetCore.Routing/RouteEndpointBuilder.cs index c351aeb4da..a45d71d391 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpointBuilder.cs +++ b/src/Microsoft.AspNetCore.Routing/RouteEndpointBuilder.cs @@ -1,22 +1,18 @@ // 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 Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing.Patterns; -namespace Microsoft.AspNetCore.Routing.Matching +namespace Microsoft.AspNetCore.Routing { - public sealed class MatcherEndpointBuilder : EndpointBuilder + public sealed class RouteEndpointBuilder : EndpointBuilder { - public RequestDelegate RequestDelegate { get; set; } - public RoutePattern RoutePattern { get; set; } public int Order { get; set; } - public MatcherEndpointBuilder( + public RouteEndpointBuilder( RequestDelegate requestDelegate, RoutePattern routePattern, int order) diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs index 3d6e44160b..3e93c1d3db 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matching/MatcherEndpointBuilderTest.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Routing.Matching object metadata = new object(); RequestDelegate requestDelegate = (d) => null; - var builder = new MatcherEndpointBuilder(requestDelegate, RoutePatternFactory.Parse("/"), defaultOrder) + var builder = new RouteEndpointBuilder(requestDelegate, RoutePatternFactory.Parse("/"), defaultOrder) { DisplayName = "Display name!", Metadata = { metadata } From 264e561c5baf23c75a9e169387938d33585e72ef Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 16 Sep 2018 19:28:06 +0000 Subject: [PATCH 17/17] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 54 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 03a593dfc5..f66bc953d0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,33 +4,33 @@ 0.10.13 - 3.0.0-alpha1-20180907.9 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 + 3.0.0-alpha1-20180911.2 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 5e9566c2bf..a817c10d28 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180907.9 -commithash:f997365a8832ff0a3cbd9a98df45734ac2723fa0 \ No newline at end of file +version:3.0.0-alpha1-20180911.2 +commithash:2a2b7dbea1b247930c41da497f4ea0b2bb756818