diff --git a/Routing.sln b/Routing.sln index 408a81c353..6b34e4f0b0 100644 --- a/Routing.sln +++ b/Routing.sln @@ -1,4 +1,5 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27106.3000 MinimumVisualStudioVersion = 15.0.26730.03 @@ -44,15 +45,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{6DC6B416 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Routing.Performance", "benchmarks\Microsoft.AspNetCore.Routing.Performance\Microsoft.AspNetCore.Routing.Performance.csproj", "{F3D86714-4E64-41A6-9B36-A47B3683CF5D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DispatcherSample.Web", "samples\DispatcherSample.Web\DispatcherSample.Web.csproj", "{4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{D5F39F59-5725-4127-82E7-67028D006185}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarkapps", "benchmarkapps", "{7F5914E2-C63F-4759-898E-462804357C90}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "benchmarkapps\Benchmarks\Benchmarks.csproj", "{91F47A60-9A78-4968-B10D-157D9BFAC37F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swaggatherer", "benchmarks\Swaggatherer\Swaggatherer.csproj", "{990ECDEE-49DE-45E3-B0D9-DDEB9CFF6A9D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swaggatherer", "benchmarks\Swaggatherer\Swaggatherer.csproj", "{990ECDEE-49DE-45E3-B0D9-DDEB9CFF6A9D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -154,18 +153,6 @@ Global {F3D86714-4E64-41A6-9B36-A47B3683CF5D}.Release|Mixed Platforms.Build.0 = Release|Any CPU {F3D86714-4E64-41A6-9B36-A47B3683CF5D}.Release|x86.ActiveCfg = Release|Any CPU {F3D86714-4E64-41A6-9B36-A47B3683CF5D}.Release|x86.Build.0 = Release|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Debug|x86.ActiveCfg = Debug|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Debug|x86.Build.0 = Debug|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Release|Any CPU.Build.0 = Release|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Release|x86.ActiveCfg = Release|Any CPU - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5}.Release|x86.Build.0 = Release|Any CPU {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|Any CPU.Build.0 = Debug|Any CPU {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -203,7 +190,6 @@ Global {741B0B05-CE96-473B-B962-6B0A347DF79A} = {95359B4B-4C85-4B44-A75B-0621905C4CF6} {5C73140B-41F3-466F-A07B-3614E4D80DF9} = {95359B4B-4C85-4B44-A75B-0621905C4CF6} {F3D86714-4E64-41A6-9B36-A47B3683CF5D} = {D5F39F59-5725-4127-82E7-67028D006185} - {4EBE7A6F-3183-4A7D-B3D7-A6A9EC3867A5} = {C3ADD55B-B9C7-4061-8AD4-6A70D1AE3B2E} {91F47A60-9A78-4968-B10D-157D9BFAC37F} = {7F5914E2-C63F-4759-898E-462804357C90} {990ECDEE-49DE-45E3-B0D9-DDEB9CFF6A9D} = {D5F39F59-5725-4127-82E7-67028D006185} EndGlobalSection diff --git a/benchmarkapps/Benchmarks/Program.cs b/benchmarkapps/Benchmarks/Program.cs index a37a131d9c..0bed5e0b3c 100644 --- a/benchmarkapps/Benchmarks/Program.cs +++ b/benchmarkapps/Benchmarks/Program.cs @@ -29,22 +29,22 @@ namespace Benchmarks .UseKestrel(); var scenario = config["scenarios"]?.ToLower(); - if (scenario == "plaintextdispatcher") + if (scenario == "plaintextdispatcher" || scenario == "plaintextglobalrouting") { - webHostBuilder.UseStartup(); + webHostBuilder.UseStartup(); // for testing - webHostBuilder.UseSetting("Startup", nameof(StartupUsingDispatcher)); + webHostBuilder.UseSetting("Startup", nameof(StartupUsingGlobalRouting)); } - else if (scenario == "plaintextrouting") + else if (scenario == "plaintextrouting" || scenario == "plaintextrouter") { - webHostBuilder.UseStartup(); + webHostBuilder.UseStartup(); // for testing - webHostBuilder.UseSetting("Startup", nameof(StartupUsingRouting)); + webHostBuilder.UseSetting("Startup", nameof(StartupUsingRouter)); } else { throw new InvalidOperationException( - $"Invalid scenario '{scenario}'. Allowed scenarios are PlaintextDispatcher and PlaintextRouting"); + $"Invalid scenario '{scenario}'. Allowed scenarios are PlaintextGlobalRouting and PlaintextRouter"); } return webHostBuilder; diff --git a/benchmarkapps/Benchmarks/StartupUsingDispatcher.cs b/benchmarkapps/Benchmarks/StartupUsingGlobalRouting.cs similarity index 92% rename from benchmarkapps/Benchmarks/StartupUsingDispatcher.cs rename to benchmarkapps/Benchmarks/StartupUsingGlobalRouting.cs index f8c739eab1..f05d1b905b 100644 --- a/benchmarkapps/Benchmarks/StartupUsingDispatcher.cs +++ b/benchmarkapps/Benchmarks/StartupUsingGlobalRouting.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Benchmarks { - public class StartupUsingDispatcher + public class StartupUsingGlobalRouting { private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); @@ -18,7 +18,7 @@ namespace Benchmarks { services.AddRouting(); - services.AddDispatcher(options => + services.Configure(options => { options.DataSources.Add(new DefaultEndpointDataSource(new[] { @@ -43,7 +43,7 @@ namespace Benchmarks public void Configure(IApplicationBuilder app) { - app.UseDispatcher(); + app.UseGlobalRouting(); app.UseEndpoint(); } diff --git a/benchmarkapps/Benchmarks/StartupUsingRouting.cs b/benchmarkapps/Benchmarks/StartupUsingRouter.cs similarity index 96% rename from benchmarkapps/Benchmarks/StartupUsingRouting.cs rename to benchmarkapps/Benchmarks/StartupUsingRouter.cs index d9e2999af3..ef1528bf1b 100644 --- a/benchmarkapps/Benchmarks/StartupUsingRouting.cs +++ b/benchmarkapps/Benchmarks/StartupUsingRouter.cs @@ -8,7 +8,7 @@ using System.Text; namespace Benchmarks { - public class StartupUsingRouting + public class StartupUsingRouter { private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); diff --git a/benchmarkapps/Benchmarks/benchmarks.json b/benchmarkapps/Benchmarks/benchmarks.json index d93213fff2..794ea8c770 100644 --- a/benchmarkapps/Benchmarks/benchmarks.json +++ b/benchmarkapps/Benchmarks/benchmarks.json @@ -16,7 +16,13 @@ "PlaintextRouting": { "Path": "/plaintext" }, + "PlaintextRouter": { + "Path": "/plaintext" + }, "PlaintextDispatcher": { "Path": "/plaintext" + }, + "PlaintextGlobalRouting": { + "Path": "/plaintext" } } diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherAzureBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherAzureBenchmark.cs index 8e2a114137..8a97e2a9b2 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherAzureBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherAzureBenchmark.cs @@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers var sample = _samples[i]; var httpContext = Requests[sample]; - // This is required to make the legacy router implementation work with dispatcher. + // This is required to make the legacy router implementation work with global routing. httpContext.Features.Set(feature); await _tree.MatchAsync(httpContext, feature); diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherBenchmarkBase.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherBenchmarkBase.cs index ada2c02857..3cb9649887 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherBenchmarkBase.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherBenchmarkBase.cs @@ -25,7 +25,6 @@ namespace Microsoft.AspNetCore.Routing.Matchers services.AddLogging(); services.AddOptions(); services.AddRouting(); - services.AddDispatcher(); return services.BuildServiceProvider(); } diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherGithubBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherGithubBenchmark.cs index 4aeb9a3a02..b47aa4a592 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherGithubBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherGithubBenchmark.cs @@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers { var httpContext = Requests[i]; - // This is required to make the legacy router implementation work with dispatcher. + // This is required to make the legacy router implementation work with global routing. httpContext.Features.Set(feature); await _tree.MatchAsync(httpContext, feature); diff --git a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherSingleEntryBenchmark.cs b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherSingleEntryBenchmark.cs index c13f0a9abf..5125ffb169 100644 --- a/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherSingleEntryBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.Routing.Performance/Matchers/MatcherSingleEntryBenchmark.cs @@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers var httpContext = Requests[0]; - // This is required to make the legacy router implementation work with dispatcher. + // This is required to make the legacy router implementation work with global routing. httpContext.Features.Set(feature); await _tree.MatchAsync(httpContext, feature); @@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers var feature = _feature; var httpContext = Requests[0]; - // This is required to make the legacy router implementation work with dispatcher. + // This is required to make the legacy router implementation work with global routing. httpContext.Features.Set(feature); await _route.MatchAsync(httpContext, feature); diff --git a/samples/DispatcherSample.Web/DispatcherSample.Web.csproj b/samples/DispatcherSample.Web/DispatcherSample.Web.csproj deleted file mode 100644 index 52b1699c7b..0000000000 --- a/samples/DispatcherSample.Web/DispatcherSample.Web.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - netcoreapp2.2 - $(TargetFrameworks);net461 - - - - - - - - - - - - diff --git a/samples/DispatcherSample.Web/Program.cs b/samples/DispatcherSample.Web/Program.cs deleted file mode 100644 index 45c4e82afa..0000000000 --- a/samples/DispatcherSample.Web/Program.cs +++ /dev/null @@ -1,26 +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.Builder; -using Microsoft.AspNetCore.Hosting; - -namespace DispatcherSample.Web -{ - public class Program - { - public static void Main(string[] args) - { - var webHost = GetWebHostBuilder().Build(); - webHost.Run(); - } - - // For unit testing - public static IWebHostBuilder GetWebHostBuilder() - { - return new WebHostBuilder() - .UseKestrel() - .UseIISIntegration() - .UseStartup(); - } - } -} diff --git a/samples/DispatcherSample.Web/EndsWithStringMatchProcessor.cs b/samples/RoutingSample.Web/EndsWithStringMatchProcessor.cs similarity index 97% rename from samples/DispatcherSample.Web/EndsWithStringMatchProcessor.cs rename to samples/RoutingSample.Web/EndsWithStringMatchProcessor.cs index 7284dc6d66..17fcb1f990 100644 --- a/samples/DispatcherSample.Web/EndsWithStringMatchProcessor.cs +++ b/samples/RoutingSample.Web/EndsWithStringMatchProcessor.cs @@ -6,7 +6,7 @@ using System.Globalization; using Microsoft.AspNetCore.Routing.Matchers; using Microsoft.Extensions.Logging; -namespace DispatcherSample.Web +namespace RoutingSample.Web { internal class EndsWithStringMatchProcessor : MatchProcessorBase { diff --git a/samples/RoutingSample.Web/PrefixRoute.cs b/samples/RoutingSample.Web/PrefixRoute.cs index 908e8a5462..2a68abb183 100644 --- a/samples/RoutingSample.Web/PrefixRoute.cs +++ b/samples/RoutingSample.Web/PrefixRoute.cs @@ -44,14 +44,14 @@ namespace RoutingSample.Web var lastCharacter = requestPath[_prefix.Length]; if (lastCharacter != '/' && lastCharacter != '#' && lastCharacter != '?') { - return Task.FromResult(0); + return Task.CompletedTask; } } context.Handler = _target.GetRequestHandler(context.HttpContext, context.RouteData); } - return Task.FromResult(0); + return Task.CompletedTask; } public VirtualPathData GetVirtualPath(VirtualPathContext context) diff --git a/samples/RoutingSample.Web/Program.cs b/samples/RoutingSample.Web/Program.cs index c8449236ba..206e4bb0bf 100644 --- a/samples/RoutingSample.Web/Program.cs +++ b/samples/RoutingSample.Web/Program.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -8,19 +9,57 @@ namespace RoutingSample.Web { public class Program { + public static readonly string GlobalRoutingScenario = "globalrouting"; + public static readonly string RouterScenario = "router"; + public static void Main(string[] args) { - var webHost = GetWebHostBuilder().Build(); + var webHost = GetWebHostBuilder(args).Build(); webHost.Run(); } // For unit testing - public static IWebHostBuilder GetWebHostBuilder() + public static IWebHostBuilder GetWebHostBuilder(string[] args) { + string scenario; + if (args.Length == 0) + { + Console.WriteLine("Choose a sample to run:"); + Console.WriteLine($"1. {GlobalRoutingScenario}"); + Console.WriteLine($"2. {RouterScenario}"); + Console.WriteLine(); + + scenario = Console.ReadLine(); + } + else + { + scenario = args[0]; + } + + Type startupType; + switch (scenario) + { + case "1": + case "globalrouting": + startupType = typeof(UseGlobalRoutingStartup); + break; + + case "2": + case "router": + startupType = typeof(UseRouterStartup); + break; + + default: + Console.WriteLine($"unknown scenario {scenario}"); + Console.WriteLine($"usage: dotnet run -- ({GlobalRoutingScenario}|{RouterScenario})"); + throw new InvalidOperationException(); + + } + return new WebHostBuilder() .UseKestrel() .UseIISIntegration() - .UseStartup(); + .UseStartup(startupType); } } } diff --git a/samples/DispatcherSample.Web/Startup.cs b/samples/RoutingSample.Web/UseGlobalRoutingStartup.cs similarity index 91% rename from samples/DispatcherSample.Web/Startup.cs rename to samples/RoutingSample.Web/UseGlobalRoutingStartup.cs index 4cbebd1e89..12cfd28640 100644 --- a/samples/DispatcherSample.Web/Startup.cs +++ b/samples/RoutingSample.Web/UseGlobalRoutingStartup.cs @@ -2,7 +2,6 @@ // 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.Builder; using Microsoft.AspNetCore.Http; @@ -11,11 +10,11 @@ using Microsoft.AspNetCore.Routing.Matchers; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.Extensions.DependencyInjection; -namespace DispatcherSample.Web +namespace RoutingSample.Web { - public class Startup + public class UseGlobalRoutingStartup { - private static readonly byte[] _homePayload = Encoding.UTF8.GetBytes("Dispatcher sample endpoints:" + Environment.NewLine + "/plaintext"); + private static readonly byte[] _homePayload = Encoding.UTF8.GetBytes("Global Routing sample endpoints:" + Environment.NewLine + "/plaintext"); private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); public void ConfigureServices(IServiceCollection services) @@ -26,11 +25,11 @@ namespace DispatcherSample.Web { options.ConstraintMap.Add("endsWith", typeof(EndsWithStringMatchProcessor)); }); - - services.AddDispatcher(options => + + services.Configure(options => { - options.DataSources.Add(new DefaultEndpointDataSource(new[] - { + options.DataSources.Add(new DefaultEndpointDataSource(new[] + { new MatcherEndpoint((next) => (httpContext) => { var response = httpContext.Response; @@ -83,13 +82,13 @@ namespace DispatcherSample.Web 0, EndpointMetadataCollection.Empty, "withoptionalconstraints"), - })); - }); + })); + }); } public void Configure(IApplicationBuilder app) { - app.UseDispatcher(); + app.UseGlobalRouting(); // Imagine some more stuff here... diff --git a/samples/RoutingSample.Web/Startup.cs b/samples/RoutingSample.Web/UseRouterStartup.cs similarity index 98% rename from samples/RoutingSample.Web/Startup.cs rename to samples/RoutingSample.Web/UseRouterStartup.cs index 3205b4f42d..2d267ef18f 100644 --- a/samples/RoutingSample.Web/Startup.cs +++ b/samples/RoutingSample.Web/UseRouterStartup.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.DependencyInjection; namespace RoutingSample.Web { - public class Startup + public class UseRouterStartup { private static readonly TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(10); diff --git a/src/Microsoft.AspNetCore.Routing/Builder/DispatcherApplicationBuilderExtensions.cs b/src/Microsoft.AspNetCore.Routing/Builder/DispatcherApplicationBuilderExtensions.cs deleted file mode 100644 index 90ac0ce3fb..0000000000 --- a/src/Microsoft.AspNetCore.Routing/Builder/DispatcherApplicationBuilderExtensions.cs +++ /dev/null @@ -1,52 +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 Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.Routing.Internal; -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Builder -{ - public static class DispatcherApplicationBuilderExtensions - { - private const string DispatcherRegisteredKey = "__DispatcherMiddlewareRegistered"; - - public static IApplicationBuilder UseDispatcher(this IApplicationBuilder builder) - { - VerifyDispatcherIsRegistered(builder); - - builder.Properties[DispatcherRegisteredKey] = true; - - return builder.UseMiddleware(); - } - - public static IApplicationBuilder UseEndpoint(this IApplicationBuilder builder) - { - VerifyDispatcherIsRegistered(builder); - - if (!builder.Properties.TryGetValue(DispatcherRegisteredKey, out _)) - { - var message = $"{nameof(DispatcherMiddleware)} must be added to the request execution pipeline before {nameof(EndpointMiddleware)}. " + - $"Please add {nameof(DispatcherMiddleware)} by calling '{nameof(IApplicationBuilder)}.{nameof(UseDispatcher)}' inside the call to 'Configure(...)' in the application startup code."; - - throw new InvalidOperationException(message); - } - - return builder.UseMiddleware(); - } - - private static void VerifyDispatcherIsRegistered(IApplicationBuilder app) - { - // Verify if AddDispatcher was done before calling UseDispatcher/UseEndpoint - // We use the DispatcherMarkerService to make sure if all the services were added. - if (app.ApplicationServices.GetService(typeof(DispatcherMarkerService)) == null) - { - throw new InvalidOperationException(Resources.FormatUnableToFindServices( - nameof(IServiceCollection), - nameof(DispatcherServiceCollectionExtensions.AddDispatcher), - "ConfigureServices(...)")); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Routing/Builder/GlobalRoutingApplicationBuilderExtensions.cs b/src/Microsoft.AspNetCore.Routing/Builder/GlobalRoutingApplicationBuilderExtensions.cs new file mode 100644 index 0000000000..e240a75211 --- /dev/null +++ b/src/Microsoft.AspNetCore.Routing/Builder/GlobalRoutingApplicationBuilderExtensions.cs @@ -0,0 +1,58 @@ +// 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.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Internal; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Builder +{ + public static class GlobalRoutingApplicationBuilderExtensions + { + private const string GlobalRoutingRegisteredKey = "__GlobalRoutingMiddlewareRegistered"; + + // This is provided temporarily until we can remove usages of it from MVC. + public static IApplicationBuilder UseDispatcher(this IApplicationBuilder builder) + { + return UseGlobalRouting(builder); + } + + public static IApplicationBuilder UseGlobalRouting(this IApplicationBuilder builder) + { + VerifyRoutingIsRegistered(builder); + + builder.Properties[GlobalRoutingRegisteredKey] = true; + + return builder.UseMiddleware(); + } + + public static IApplicationBuilder UseEndpoint(this IApplicationBuilder builder) + { + VerifyRoutingIsRegistered(builder); + + if (!builder.Properties.TryGetValue(GlobalRoutingRegisteredKey, out _)) + { + var message = $"{nameof(GlobalRoutingMiddleware)} must be added to the request execution pipeline before {nameof(EndpointMiddleware)}. " + + $"Please add {nameof(GlobalRoutingMiddleware)} by calling '{nameof(IApplicationBuilder)}.{nameof(UseGlobalRouting)}' inside the call to 'Configure(...)' in the application startup code."; + + throw new InvalidOperationException(message); + } + + return builder.UseMiddleware(); + } + + private static void VerifyRoutingIsRegistered(IApplicationBuilder app) + { + // Verify if AddRouting was done before calling UseGlobalRouting/UseEndpoint + // We use the RoutingMarkerService to make sure if all the services were added. + if (app.ApplicationServices.GetService(typeof(RoutingMarkerService)) == null) + { + throw new InvalidOperationException(Resources.FormatUnableToFindServices( + nameof(IServiceCollection), + nameof(RoutingServiceCollectionExtensions.AddRouting), + "ConfigureServices(...)")); + } + } + } +} diff --git a/src/Microsoft.AspNetCore.Routing/RoutingBuilderExtensions.cs b/src/Microsoft.AspNetCore.Routing/Builder/RoutingBuilderExtensions.cs similarity index 100% rename from src/Microsoft.AspNetCore.Routing/RoutingBuilderExtensions.cs rename to src/Microsoft.AspNetCore.Routing/Builder/RoutingBuilderExtensions.cs diff --git a/src/Microsoft.AspNetCore.Routing/DependencyInjection/ConfigureDispatcherOptions.cs b/src/Microsoft.AspNetCore.Routing/DependencyInjection/ConfigureEndpointOptions.cs similarity index 79% rename from src/Microsoft.AspNetCore.Routing/DependencyInjection/ConfigureDispatcherOptions.cs rename to src/Microsoft.AspNetCore.Routing/DependencyInjection/ConfigureEndpointOptions.cs index e916dd0e18..ce6c069a22 100644 --- a/src/Microsoft.AspNetCore.Routing/DependencyInjection/ConfigureDispatcherOptions.cs +++ b/src/Microsoft.AspNetCore.Routing/DependencyInjection/ConfigureEndpointOptions.cs @@ -8,11 +8,11 @@ using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection { - internal class ConfigureDispatcherOptions : IConfigureOptions + internal class ConfigureEndpointOptions : IConfigureOptions { private readonly IEnumerable _dataSources; - public ConfigureDispatcherOptions(IEnumerable dataSources) + public ConfigureEndpointOptions(IEnumerable dataSources) { if (dataSources == null) { @@ -22,7 +22,7 @@ namespace Microsoft.Extensions.DependencyInjection _dataSources = dataSources; } - public void Configure(DispatcherOptions options) + public void Configure(EndpointOptions options) { if (options == null) { diff --git a/src/Microsoft.AspNetCore.Routing/DependencyInjection/DispatcherServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Routing/DependencyInjection/DispatcherServiceCollectionExtensions.cs index 8fb75c8351..6500f02986 100644 --- a/src/Microsoft.AspNetCore.Routing/DependencyInjection/DispatcherServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Routing/DependencyInjection/DispatcherServiceCollectionExtensions.cs @@ -2,19 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Reflection; using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.Routing.EndpointConstraints; -using Microsoft.AspNetCore.Routing.EndpointFinders; -using Microsoft.AspNetCore.Routing.Internal; -using Microsoft.AspNetCore.Routing.Matchers; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection { + // This whole class is temporary until we can remove its usage from MVC public static class DispatcherServiceCollectionExtensions { + // This whole class is temporary until we can remove its usage from MVC public static IServiceCollection AddDispatcher(this IServiceCollection services) { if (services == null) @@ -22,53 +17,21 @@ namespace Microsoft.Extensions.DependencyInjection throw new ArgumentNullException(nameof(services)); } - // Collect all data sources from DI. - services.TryAddEnumerable(ServiceDescriptor.Transient, ConfigureDispatcherOptions>()); - - // Allow global access to the list of endpoints. - services.TryAddSingleton(s => - { - var options = s.GetRequiredService>(); - return new CompositeEndpointDataSource(options.Value.DataSources); - }); - - // - // Default matcher implementation - // - services.TryAddSingleton(); - services.TryAddSingleton(); - services.TryAddTransient(); - - // Link generation related services - services.TryAddSingleton, NameBasedEndpointFinder>(); - services.TryAddSingleton, RouteValuesBasedEndpointFinder>(); - services.TryAddSingleton(); - // - // Endpoint Selection - // - services.TryAddSingleton(); - services.TryAddSingleton(); - - // Will be cached by the EndpointSelector - services.TryAddEnumerable( - ServiceDescriptor.Transient()); - - services.TryAddSingleton(typeof(DispatcherMarkerService)); - - return services; + return services.AddRouting(); } - public static IServiceCollection AddDispatcher(this IServiceCollection services, Action configuration) + // This whole class is temporary until we can remove its usage from MVC + public static IServiceCollection AddDispatcher(this IServiceCollection services, Action configuration) { if (services == null) { throw new ArgumentNullException(nameof(services)); } - services.AddDispatcher(); + services.AddRouting(); if (configuration != null) { - services.Configure(configuration); + services.Configure(configuration); } return services; diff --git a/src/Microsoft.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs index 675ef797ac..1474d6e76d 100644 --- a/src/Microsoft.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Routing/DependencyInjection/RoutingServiceCollectionExtensions.cs @@ -4,12 +4,15 @@ using System; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Constraints; +using Microsoft.AspNetCore.Routing.EndpointConstraints; +using Microsoft.AspNetCore.Routing.EndpointFinders; using Microsoft.AspNetCore.Routing.Internal; using Microsoft.AspNetCore.Routing.Matchers; using Microsoft.AspNetCore.Routing.Tree; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.ObjectPool; +using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection { @@ -49,6 +52,37 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddSingleton(typeof(RoutingMarkerService)); + // Collect all data sources from DI. + services.TryAddEnumerable(ServiceDescriptor.Transient, ConfigureEndpointOptions>()); + + // Allow global access to the list of endpoints. + services.TryAddSingleton(s => + { + var options = s.GetRequiredService>(); + return new CompositeEndpointDataSource(options.Value.DataSources); + }); + + // + // Default matcher implementation + // + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddTransient(); + + // Link generation related services + services.TryAddSingleton, NameBasedEndpointFinder>(); + services.TryAddSingleton, RouteValuesBasedEndpointFinder>(); + services.TryAddSingleton(); + // + // Endpoint Selection + // + services.TryAddSingleton(); + services.TryAddSingleton(); + + // Will be cached by the EndpointSelector + services.TryAddEnumerable( + ServiceDescriptor.Transient()); + return services; } diff --git a/src/Microsoft.AspNetCore.Routing/EndpointMiddleware.cs b/src/Microsoft.AspNetCore.Routing/EndpointMiddleware.cs index 36e888ccb1..243c97d262 100644 --- a/src/Microsoft.AspNetCore.Routing/EndpointMiddleware.cs +++ b/src/Microsoft.AspNetCore.Routing/EndpointMiddleware.cs @@ -34,8 +34,8 @@ namespace Microsoft.AspNetCore.Routing var feature = httpContext.Features.Get(); if (feature == null) { - var message = $"Unable to execute an endpoint because the {nameof(DispatcherMiddleware)} was not run for this request. " + - $"Ensure {nameof(DispatcherMiddleware)} is added to the request execution pipeline before {nameof(EndpointMiddleware)} in application startup code."; + var message = $"Unable to execute an endpoint because the {nameof(GlobalRoutingMiddleware)} was not run for this request. " + + $"Ensure {nameof(GlobalRoutingMiddleware)} is added to the request execution pipeline before {nameof(EndpointMiddleware)} in application startup code."; throw new InvalidOperationException(message); } diff --git a/src/Microsoft.AspNetCore.Routing/DispatcherOptions.cs b/src/Microsoft.AspNetCore.Routing/EndpointOptions.cs similarity index 91% rename from src/Microsoft.AspNetCore.Routing/DispatcherOptions.cs rename to src/Microsoft.AspNetCore.Routing/EndpointOptions.cs index 1ec4c2f397..bd03d3c7a2 100644 --- a/src/Microsoft.AspNetCore.Routing/DispatcherOptions.cs +++ b/src/Microsoft.AspNetCore.Routing/EndpointOptions.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; namespace Microsoft.AspNetCore.Routing { - public class DispatcherOptions + public class EndpointOptions { public IList DataSources { get; } = new List(); } diff --git a/src/Microsoft.AspNetCore.Routing/DispatcherMiddleware.cs b/src/Microsoft.AspNetCore.Routing/GlobalRoutingMiddleware.cs similarity index 96% rename from src/Microsoft.AspNetCore.Routing/DispatcherMiddleware.cs rename to src/Microsoft.AspNetCore.Routing/GlobalRoutingMiddleware.cs index 6dd9cbed16..994b2e6295 100644 --- a/src/Microsoft.AspNetCore.Routing/DispatcherMiddleware.cs +++ b/src/Microsoft.AspNetCore.Routing/GlobalRoutingMiddleware.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Routing { - internal sealed class DispatcherMiddleware + internal sealed class GlobalRoutingMiddleware { private readonly MatcherFactory _matcherFactory; private readonly ILogger _logger; @@ -20,10 +20,10 @@ namespace Microsoft.AspNetCore.Routing private Task _initializationTask; - public DispatcherMiddleware( + public GlobalRoutingMiddleware( MatcherFactory matcherFactory, CompositeEndpointDataSource endpointDataSource, - ILogger logger, + ILogger logger, RequestDelegate next) { if (matcherFactory == null) diff --git a/src/Microsoft.AspNetCore.Routing/Internal/DispatcherMarkerService.cs b/src/Microsoft.AspNetCore.Routing/Internal/DispatcherMarkerService.cs deleted file mode 100644 index f4e742b654..0000000000 --- a/src/Microsoft.AspNetCore.Routing/Internal/DispatcherMarkerService.cs +++ /dev/null @@ -1,15 +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.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Routing.Internal -{ - /// - /// A marker class used to determine if all the dispatcher services were added - /// to the before dispatcher is configured. - /// - internal class DispatcherMarkerService - { - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing/Matchers/Matcher.cs b/src/Microsoft.AspNetCore.Routing/Matchers/Matcher.cs index 9cb5921e6a..d62f8546e1 100644 --- a/src/Microsoft.AspNetCore.Routing/Matchers/Matcher.cs +++ b/src/Microsoft.AspNetCore.Routing/Matchers/Matcher.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers { /// /// An interface for components that can select an given the current request, as part - /// of the execution of . + /// of the execution of . /// internal abstract class Matcher { diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/DispatcherTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/GlobalRoutingBenchmarkTest.cs similarity index 87% rename from test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/DispatcherTest.cs rename to test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/GlobalRoutingBenchmarkTest.cs index 3b963b56a5..54b8d75073 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/DispatcherTest.cs +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/GlobalRoutingBenchmarkTest.cs @@ -11,20 +11,20 @@ using Xunit; namespace Microsoft.AspNetCore.Routing.FunctionalTests { - public class DispatcherTest : IDisposable + public class GlobalRoutingBenchmarkTest : IDisposable { private readonly HttpClient _client; private readonly TestServer _testServer; - public DispatcherTest() + public GlobalRoutingBenchmarkTest() { // This switch and value are set by benchmark server when running the app for profiling. - var args = new[] { "--scenarios", "PlaintextDispatcher" }; + var args = new[] { "--scenarios", "PlaintextGlobalRouting" }; var webHostBuilder = Benchmarks.Program.GetWebHostBuilder(args); // Make sure we are using the right startup var startupName = webHostBuilder.GetSetting("Startup"); - Assert.Equal(nameof(Benchmarks.StartupUsingDispatcher), startupName); + Assert.Equal(nameof(Benchmarks.StartupUsingGlobalRouting), startupName); _testServer = new TestServer(webHostBuilder); _client = _testServer.CreateClient(); diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RoutingTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RouterBenchmarkTest.cs similarity index 91% rename from test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RoutingTest.cs rename to test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RouterBenchmarkTest.cs index ae4ef90f06..bb7300388b 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RoutingTest.cs +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RouterBenchmarkTest.cs @@ -11,12 +11,12 @@ using Xunit; namespace Microsoft.AspNetCore.Routing.FunctionalTests { - public class RoutingTest : IDisposable + public class RouterBenchmarkTest : IDisposable { private readonly HttpClient _client; private readonly TestServer _testServer; - public RoutingTest() + public RouterBenchmarkTest() { // This switch and value are set by benchmark server when running the app for profiling. var args = new[] { "--scenarios", "PlaintextRouting" }; @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Routing.FunctionalTests // Make sure we are using the right startup var startupName = webHostBuilder.GetSetting("Startup"); - Assert.Equal(nameof(Benchmarks.StartupUsingRouting), startupName); + Assert.Equal(nameof(Benchmarks.StartupUsingRouter), startupName); _testServer = new TestServer(webHostBuilder); _client = _testServer.CreateClient(); diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/DispatcherSampleTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/GlobalRoutingSampleTest.cs similarity index 93% rename from test/Microsoft.AspNetCore.Routing.FunctionalTests/DispatcherSampleTest.cs rename to test/Microsoft.AspNetCore.Routing.FunctionalTests/GlobalRoutingSampleTest.cs index 79925e8bf0..1ea832e806 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/DispatcherSampleTest.cs +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/GlobalRoutingSampleTest.cs @@ -6,18 +6,19 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.TestHost; +using RoutingSample.Web; using Xunit; namespace Microsoft.AspNetCore.Routing.FunctionalTests { - public class DispatcherSampleTest : IDisposable + public class GlobalRoutingSampleTest : IDisposable { private readonly HttpClient _client; private readonly TestServer _testServer; - public DispatcherSampleTest() + public GlobalRoutingSampleTest() { - var webHostBuilder = DispatcherSample.Web.Program.GetWebHostBuilder(); + var webHostBuilder = Program.GetWebHostBuilder(new[] { Program.GlobalRoutingScenario, }); _testServer = new TestServer(webHostBuilder); _client = _testServer.CreateClient(); _client.BaseAddress = new Uri("http://localhost"); @@ -28,7 +29,7 @@ namespace Microsoft.AspNetCore.Routing.FunctionalTests { // Arrange var expectedContentType = "text/plain"; - var expectedContent = "Dispatcher sample endpoints:" + Environment.NewLine + "/plaintext"; + var expectedContent = "Global Routing sample endpoints:" + Environment.NewLine + "/plaintext"; // Act var response = await _client.GetAsync("/"); 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 cbbb6f11e1..9520c32ff5 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj @@ -7,7 +7,6 @@ - diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingSampleTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/RouterSampleTest.cs similarity index 92% rename from test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingSampleTest.cs rename to test/Microsoft.AspNetCore.Routing.FunctionalTests/RouterSampleTest.cs index 8869103f40..a925035bc4 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingSampleTest.cs +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/RouterSampleTest.cs @@ -6,18 +6,19 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.TestHost; +using RoutingSample.Web; using Xunit; namespace Microsoft.AspNetCore.Routing.FunctionalTests { - public class RoutingSampleTest : IDisposable + public class RouterSampleTest : IDisposable { private readonly HttpClient _client; private readonly TestServer _testServer; - public RoutingSampleTest() + public RouterSampleTest() { - var webHostBuilder = RoutingSample.Web.Program.GetWebHostBuilder(); + var webHostBuilder = Program.GetWebHostBuilder(new[] { Program.RouterScenario, }); _testServer = new TestServer(webHostBuilder); _client = _testServer.CreateClient(); _client.BaseAddress = new Uri("http://localhost"); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/DispatcherApplicationBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Builder/GlobalRoutingBuilderExtensionsTest.cs similarity index 79% rename from test/Microsoft.AspNetCore.Routing.Tests/DispatcherApplicationBuilderExtensionsTest.cs rename to test/Microsoft.AspNetCore.Routing.Tests/Builder/GlobalRoutingBuilderExtensionsTest.cs index a748f57557..410be22666 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/DispatcherApplicationBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Builder/GlobalRoutingBuilderExtensionsTest.cs @@ -12,21 +12,21 @@ using Xunit; namespace Microsoft.AspNetCore.Builder { - public class DispatcherApplicationBuilderExtensionsTest + public class GlobalRoutingBuilderExtensionsTest { [Fact] - public void UseDispatcher_ServicesNotRegistered_Throws() + public void UseGlobalRouting_ServicesNotRegistered_Throws() { // Arrange var app = new ApplicationBuilder(Mock.Of()); // Act - var ex = Assert.Throws(() => app.UseDispatcher()); + var ex = Assert.Throws(() => app.UseGlobalRouting()); // Assert Assert.Equal( "Unable to find the required services. " + - "Please add all the required services by calling 'IServiceCollection.AddDispatcher' " + + "Please add all the required services by calling 'IServiceCollection.AddRouting' " + "inside the call to 'ConfigureServices(...)' in the application startup code.", ex.Message); } @@ -43,20 +43,20 @@ namespace Microsoft.AspNetCore.Builder // Assert Assert.Equal( "Unable to find the required services. " + - "Please add all the required services by calling 'IServiceCollection.AddDispatcher' " + + "Please add all the required services by calling 'IServiceCollection.AddRouting' " + "inside the call to 'ConfigureServices(...)' in the application startup code.", ex.Message); } [Fact] - public async Task UseDispatcher_ServicesRegistered_SetsFeature() + public async Task UseGlobalRouting_ServicesRegistered_SetsFeature() { // Arrange var services = CreateServices(); var app = new ApplicationBuilder(services); - app.UseDispatcher(); + app.UseGlobalRouting(); var appFunc = app.Build(); var httpContext = new DefaultHttpContext(); @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Builder } [Fact] - public void UseEndpoint_ServicesRegisteredAndNoDispatcherRegistered_Throws() + public void UseEndpoint_WithoutRoutingServicesRegistered_Throws() { // Arrange var services = CreateServices(); @@ -81,21 +81,21 @@ namespace Microsoft.AspNetCore.Builder // Assert Assert.Equal( - "DispatcherMiddleware must be added to the request execution pipeline before EndpointMiddleware. " + - "Please add DispatcherMiddleware by calling 'IApplicationBuilder.UseDispatcher' " + + "GlobalRoutingMiddleware must be added to the request execution pipeline before EndpointMiddleware. " + + "Please add GlobalRoutingMiddleware by calling 'IApplicationBuilder.UseGlobalRouting' " + "inside the call to 'Configure(...)' in the application startup code.", ex.Message); } [Fact] - public async Task UseEndpoint_ServicesRegisteredAndDispatcherRegistered_SetsFeature() + public async Task UseEndpoint_ServicesRegisteredAndGlobalRoutingRegistered_SetsFeature() { // Arrange var services = CreateServices(); var app = new ApplicationBuilder(services); - app.UseDispatcher(); + app.UseGlobalRouting(); app.UseEndpoint(); var appFunc = app.Build(); @@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Builder services.AddLogging(); services.AddOptions(); - services.AddDispatcher(); + services.AddRouting(); return services.BuildServiceProvider(); } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/RoutingBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Builder/RoutingBuilderExtensionsTest.cs similarity index 75% rename from test/Microsoft.AspNetCore.Routing.Tests/RoutingBuilderExtensionsTest.cs rename to test/Microsoft.AspNetCore.Routing.Tests/Builder/RoutingBuilderExtensionsTest.cs index 9499a6cdeb..136950cfce 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/RoutingBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Builder/RoutingBuilderExtensionsTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -14,6 +14,28 @@ namespace Microsoft.AspNetCore.Builder { public class RoutingBuilderExtensionsTest { + [Fact] + public void UseRouter_ThrowsInvalidOperationException_IfRoutingMarkerServiceIsNotRegistered() + { + // Arrange + var applicationBuilderMock = new Mock(); + applicationBuilderMock + .Setup(s => s.ApplicationServices) + .Returns(Mock.Of()); + + var router = Mock.Of(); + + // Act & Assert + var exception = Assert.Throws( + () => applicationBuilderMock.Object.UseRouter(router)); + + Assert.Equal( + "Unable to find the required services. Please add all the required services by calling " + + "'IServiceCollection.AddRouting' inside the call to 'ConfigureServices(...)'" + + " in the application startup code.", + exception.Message); + } + [Fact] public void UseRouter_IRouter_ThrowsWithoutCallingAddRouting() { @@ -59,7 +81,7 @@ namespace Microsoft.AspNetCore.Builder var router = new Mock(MockBehavior.Strict); router .Setup(r => r.RouteAsync(It.IsAny())) - .Returns(Task.FromResult(0)) + .Returns(Task.CompletedTask) .Verifiable(); app.UseRouter(router.Object); @@ -84,7 +106,7 @@ namespace Microsoft.AspNetCore.Builder var router = new Mock(MockBehavior.Strict); router .Setup(r => r.RouteAsync(It.IsAny())) - .Returns(Task.FromResult(0)) + .Returns(Task.CompletedTask) .Verifiable(); app.UseRouter(b => diff --git a/test/Microsoft.AspNetCore.Routing.Tests/BuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/BuilderExtensionsTest.cs deleted file mode 100644 index ca297f89d2..0000000000 --- a/test/Microsoft.AspNetCore.Routing.Tests/BuilderExtensionsTest.cs +++ /dev/null @@ -1,35 +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 Microsoft.AspNetCore.Routing; -using Moq; -using Xunit; - -namespace Microsoft.AspNetCore.Builder -{ - public class BuilderExtensionsTest - { - [Fact] - public void UseRouter_ThrowsInvalidOperationException_IfRoutingMarkerServiceIsNotRegistered() - { - // Arrange - var applicationBuilderMock = new Mock(); - applicationBuilderMock - .Setup(s => s.ApplicationServices) - .Returns(Mock.Of()); - - var router = Mock.Of(); - - // Act & Assert - var exception = Assert.Throws( - () => applicationBuilderMock.Object.UseRouter(router)); - - Assert.Equal( - "Unable to find the required services. Please add all the required services by calling " + - "'IServiceCollection.AddRouting' inside the call to 'ConfigureServices(...)'" + - " in the application startup code.", - exception.Message); - } - } -} diff --git a/test/Microsoft.AspNetCore.Routing.Tests/EndpointMiddlewareTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/EndpointMiddlewareTest.cs index 1a2829a42f..0d861dd218 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/EndpointMiddlewareTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/EndpointMiddlewareTest.cs @@ -35,8 +35,9 @@ namespace Microsoft.AspNetCore.Routing var ex = await Assert.ThrowsAsync(async () => await invokeTask); Assert.Equal( - "Unable to execute an endpoint because the DispatcherMiddleware was not run for this request. " + - "Ensure DispatcherMiddleware is added to the request execution pipeline before EndpointMiddleware in application startup code.", + "Unable to execute an endpoint because the GlobalRoutingMiddleware was not run for this request. " + + "Ensure GlobalRoutingMiddleware is added to the request execution pipeline before EndpointMiddleware " + + "in application startup code.", ex.Message); } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/DispatcherMiddlewareTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/GlobalRoutingMiddlewareTest.cs similarity index 83% rename from test/Microsoft.AspNetCore.Routing.Tests/DispatcherMiddlewareTest.cs rename to test/Microsoft.AspNetCore.Routing.Tests/GlobalRoutingMiddlewareTest.cs index 26fb753c38..bc34547aff 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/DispatcherMiddlewareTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/GlobalRoutingMiddlewareTest.cs @@ -13,7 +13,7 @@ using Xunit; namespace Microsoft.AspNetCore.Routing { - public class DispatcherMiddlewareTest + public class GlobalRoutingMiddlewareTest { [Fact] public async Task Invoke_OnCall_SetsEndpointFeature() @@ -39,14 +39,14 @@ namespace Microsoft.AspNetCore.Routing var expectedMessage = "Request matched endpoint 'Test endpoint'."; var sink = new TestSink( - TestSink.EnableWithTypeName, - TestSink.EnableWithTypeName); + TestSink.EnableWithTypeName, + TestSink.EnableWithTypeName); var loggerFactory = new TestLoggerFactory(sink, enabled: true); var httpContext = new DefaultHttpContext(); httpContext.RequestServices = new TestServiceProvider(); - var logger = new Logger(loggerFactory); + var logger = new Logger(loggerFactory); var middleware = CreateMiddleware(logger); // Act @@ -82,15 +82,15 @@ namespace Microsoft.AspNetCore.Routing Assert.Equal("testValue", endpointFeature.Values["testKey"]); } - private DispatcherMiddleware CreateMiddleware(Logger logger = null) + private GlobalRoutingMiddleware CreateMiddleware(Logger logger = null) { RequestDelegate next = (c) => Task.FromResult(null); - logger = logger ?? new Logger(NullLoggerFactory.Instance); + logger = logger ?? new Logger(NullLoggerFactory.Instance); - var options = Options.Create(new DispatcherOptions()); + var options = Options.Create(new EndpointOptions()); var matcherFactory = new TestMatcherFactory(true); - var middleware = new DispatcherMiddleware( + var middleware = new GlobalRoutingMiddleware( matcherFactory, new CompositeEndpointDataSource(Array.Empty()), logger, diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DfaMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DfaMatcherConformanceTest.cs index 5d3893c653..de5815f7c7 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DfaMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DfaMatcherConformanceTest.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, endpoint, keys, values); } internal override Matcher CreateMatcher(params MatcherEndpoint[] endpoints) @@ -29,7 +29,6 @@ namespace Microsoft.AspNetCore.Routing.Matchers .AddLogging() .AddOptions() .AddRouting() - .AddDispatcher() .BuildServiceProvider(); var builder = services.GetRequiredService(); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DfaMatcherTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DfaMatcherTest.cs index 51a9d74b75..821a0d0806 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DfaMatcherTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DfaMatcherTest.cs @@ -36,7 +36,6 @@ namespace Microsoft.AspNetCore.Routing.Matchers .AddLogging() .AddOptions() .AddRouting() - .AddDispatcher() .BuildServiceProvider(); var factory = services.GetRequiredService(); diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/FullFeaturedMatcherConformanceTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/FullFeaturedMatcherConformanceTest.cs index 0bed93f541..61a8f3f9bf 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/FullFeaturedMatcherConformanceTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/FullFeaturedMatcherConformanceTest.cs @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, endpoint, keys, values); } [Fact] @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, new { b = "17", c = "18", }); + MatcherAssert.AssertMatch(feature, endpoint, new { b = "17", c = "18", }); } [Fact] @@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, new { b = "17", c = "18", d = "19" }); + MatcherAssert.AssertMatch(feature, endpoint, new { b = "17", c = "18", d = "19" }); } [Theory] @@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); } [Theory] @@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, endpoint, keys, values); } [Theory] @@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); } [Theory] @@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, endpoint, keys, values); } // Historically catchall segments don't match an empty segment, but only if it's @@ -188,7 +188,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); // Need to access these to prevent a warning from the xUnit analyzer. // Some of these tests will match (and process the values) and some will not. @@ -223,7 +223,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, endpoint, keys, values); } [Theory] @@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); } [Theory] @@ -272,7 +272,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, endpoint, keys, values); } [Theory] @@ -298,7 +298,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); } // Most of are copied from old routing tests that date back to the VS 2010 era. Enjoy! @@ -323,7 +323,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, endpoint, keys, values); } [Theory] @@ -353,7 +353,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, expected, ignoreValues: true); + MatcherAssert.AssertMatch(feature, expected, ignoreValues: true); } [Theory] @@ -387,7 +387,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, expected, ignoreValues: true); + MatcherAssert.AssertMatch(feature, expected, ignoreValues: true); } [Theory] @@ -440,7 +440,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, expected, ignoreValues: true); + MatcherAssert.AssertMatch(feature, expected, ignoreValues: true); } } } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DispatcherAssert.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherAssert.cs similarity index 98% rename from test/Microsoft.AspNetCore.Routing.Tests/Matchers/DispatcherAssert.cs rename to test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherAssert.cs index 58a5e05ded..0f9364c8db 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/DispatcherAssert.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherAssert.cs @@ -8,7 +8,7 @@ using Xunit.Sdk; namespace Microsoft.AspNetCore.Routing.Matchers { - internal static class DispatcherAssert + internal static class MatcherAssert { public static void AssertMatch(IEndpointFeature feature, Endpoint expected) { diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherConformanceTest.SingleEndpoint.cs b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherConformanceTest.SingleEndpoint.cs index 529dfdacb6..caeaf1a7e8 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherConformanceTest.SingleEndpoint.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Matchers/MatcherConformanceTest.SingleEndpoint.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, endpoint); } [Fact] @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, endpoint); } [Fact] @@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, endpoint); } [Theory] @@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, endpoint); } // Some matchers will optimize for the ASCII case @@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, endpoint); } // Matchers should operate on the decoded representation - a matcher that calls @@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, endpoint); } [Theory] @@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); } [Theory] @@ -136,7 +136,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, endpoint); } // Matchers do their own 'splitting' of the path into segments, so including @@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint); + MatcherAssert.AssertMatch(feature, endpoint); } // Matchers do their own 'splitting' of the path into segments, so including @@ -190,7 +190,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); } [Fact] @@ -205,7 +205,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, values); + MatcherAssert.AssertMatch(feature, endpoint, values); } [Fact] @@ -220,7 +220,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, values); + MatcherAssert.AssertMatch(feature, endpoint, values); } [Fact] @@ -235,7 +235,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, values); + MatcherAssert.AssertMatch(feature, endpoint, values); } [Fact] @@ -255,7 +255,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, values); + MatcherAssert.AssertMatch(feature, endpoint, values); } [Theory] @@ -273,7 +273,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); } [Theory] @@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertMatch(feature, endpoint, keys, values); + MatcherAssert.AssertMatch(feature, endpoint, keys, values); } [Theory] @@ -323,7 +323,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers await matcher.MatchAsync(httpContext, feature); // Assert - DispatcherAssert.AssertNotMatch(feature); + MatcherAssert.AssertNotMatch(feature); } } } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/RequestDelegateRouteBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/RequestDelegateRouteBuilderExtensionsTest.cs index 534c193a93..825204db5d 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/RequestDelegateRouteBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/RequestDelegateRouteBuilderExtensionsTest.cs @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Routing // add routes that behave as advertised. public class RequestDelegateRouteBuilderExtensionsTest { - private static readonly RequestDelegate NullHandler = (c) => Task.FromResult(0); + private static readonly RequestDelegate NullHandler = (c) => Task.CompletedTask; public static TheoryData, Action> MatchingActions { diff --git a/test/Microsoft.AspNetCore.Routing.Tests/RouteCollectionTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/RouteCollectionTest.cs index b7eab2f10b..c7e33f2754 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/RouteCollectionTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/RouteCollectionTest.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Routing { public class RouteCollectionTest { - private static readonly RequestDelegate NullHandler = (c) => Task.FromResult(0); + private static readonly RequestDelegate NullHandler = (c) => Task.CompletedTask; [Theory] [InlineData(@"Home/Index/23", "/home/index/23", true, false)] diff --git a/test/Microsoft.AspNetCore.Routing.Tests/RouteTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/RouteTest.cs index 805fed68bc..1a52c9dec6 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/RouteTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/RouteTest.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Routing { public class RouteTest { - private static readonly RequestDelegate NullHandler = (c) => Task.FromResult(0); + private static readonly RequestDelegate NullHandler = (c) => Task.CompletedTask; private static IInlineConstraintResolver _inlineConstraintResolver = GetInlineConstraintResolver(); [Fact] diff --git a/test/Microsoft.AspNetCore.Routing.Tests/RouterMiddlewareTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/RouterMiddlewareTest.cs index 8159c294e3..7f6bd73963 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/RouterMiddlewareTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/RouterMiddlewareTest.cs @@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Routing public Task RouteAsync(RouteContext context) { - context.Handler = _isHandled ? (RequestDelegate)((c) => Task.FromResult(0)) : null; + context.Handler = _isHandled ? (RequestDelegate)((c) => Task.CompletedTask) : null; return Task.FromResult(null); } } diff --git a/test/Microsoft.AspNetCore.Routing.Tests/Tree/TreeRouterTest.cs b/test/Microsoft.AspNetCore.Routing.Tests/Tree/TreeRouterTest.cs index 8538c10e06..6a1fb47e0d 100644 --- a/test/Microsoft.AspNetCore.Routing.Tests/Tree/TreeRouterTest.cs +++ b/test/Microsoft.AspNetCore.Routing.Tests/Tree/TreeRouterTest.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Routing.Tree { public class TreeRouterTest { - private static readonly RequestDelegate NullHandler = (c) => Task.FromResult(0); + private static readonly RequestDelegate NullHandler = (c) => Task.CompletedTask; private static ObjectPool Pool = new DefaultObjectPoolProvider().Create( new UriBuilderContextPooledObjectPolicy()); @@ -1820,7 +1820,7 @@ namespace Microsoft.AspNetCore.Routing.Tree nestedRouters = new List(c.RouteData.Routers); c.Handler = null; // Not a match }) - .Returns(Task.FromResult(0)); + .Returns(Task.CompletedTask); var builder = CreateBuilder(); MapInboundEntry(builder, "api/Store", handler: next.Object); @@ -1857,7 +1857,7 @@ namespace Microsoft.AspNetCore.Routing.Tree nestedRouters = new List(c.RouteData.Routers); c.Handler = null; // Not a match }) - .Returns(Task.FromResult(0)); + .Returns(Task.CompletedTask); var builder = CreateBuilder(); MapInboundEntry(builder, "api/Store", handler: next.Object); @@ -1901,7 +1901,7 @@ namespace Microsoft.AspNetCore.Routing.Tree nestedRouters = new List(c.RouteData.Routers); throw new Exception(); }) - .Returns(Task.FromResult(0)); + .Returns(Task.CompletedTask); var builder = CreateBuilder(); MapInboundEntry(builder, "api/Store", handler: next.Object);