Change Branding

For preview one the branding is:

new thing = UseGlobalRouting/UseEndpoint
old thing = UseRouter

We're going to drop the name Dispatcher everywhere and make sure that we
position our new work as 'new and improved routing' instead of
introducing a new product/concept name.

We're not totally sure of the term Global yet, but it's what we're doing
for preview 1. Suggestions welcome for dicussion after we do the first
preview :)
This commit is contained in:
Ryan Nowak 2018-07-22 12:54:38 -07:00
parent c89c2c643b
commit b9df95831d
47 changed files with 297 additions and 336 deletions

View File

@ -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

View File

@ -29,22 +29,22 @@ namespace Benchmarks
.UseKestrel();
var scenario = config["scenarios"]?.ToLower();
if (scenario == "plaintextdispatcher")
if (scenario == "plaintextdispatcher" || scenario == "plaintextglobalrouting")
{
webHostBuilder.UseStartup<StartupUsingDispatcher>();
webHostBuilder.UseStartup<StartupUsingGlobalRouting>();
// for testing
webHostBuilder.UseSetting("Startup", nameof(StartupUsingDispatcher));
webHostBuilder.UseSetting("Startup", nameof(StartupUsingGlobalRouting));
}
else if (scenario == "plaintextrouting")
else if (scenario == "plaintextrouting" || scenario == "plaintextrouter")
{
webHostBuilder.UseStartup<StartupUsingRouting>();
webHostBuilder.UseStartup<StartupUsingRouter>();
// 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;

View File

@ -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<EndpointOptions>(options =>
{
options.DataSources.Add(new DefaultEndpointDataSource(new[]
{
@ -43,7 +43,7 @@ namespace Benchmarks
public void Configure(IApplicationBuilder app)
{
app.UseDispatcher();
app.UseGlobalRouting();
app.UseEndpoint();
}

View File

@ -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!");

View File

@ -16,7 +16,13 @@
"PlaintextRouting": {
"Path": "/plaintext"
},
"PlaintextRouter": {
"Path": "/plaintext"
},
"PlaintextDispatcher": {
"Path": "/plaintext"
},
"PlaintextGlobalRouting": {
"Path": "/plaintext"
}
}

View File

@ -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<IEndpointFeature>(feature);
await _tree.MatchAsync(httpContext, feature);

View File

@ -25,7 +25,6 @@ namespace Microsoft.AspNetCore.Routing.Matchers
services.AddLogging();
services.AddOptions();
services.AddRouting();
services.AddDispatcher();
return services.BuildServiceProvider();
}

View File

@ -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<IEndpointFeature>(feature);
await _tree.MatchAsync(httpContext, feature);

View File

@ -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<IEndpointFeature>(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<IEndpointFeature>(feature);
await _route.MatchAsync(httpContext, feature);

View File

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.2</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net461</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Routing\Microsoft.AspNetCore.Routing.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -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<Startup>();
}
}
}

View File

@ -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
{

View File

@ -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)

View File

@ -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<Startup>();
.UseStartup(startupType);
}
}
}

View File

@ -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<EndpointOptions>(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...

View File

@ -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);

View File

@ -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<DispatcherMiddleware>();
}
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<EndpointMiddleware>();
}
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(...)"));
}
}
}
}

View File

@ -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<GlobalRoutingMiddleware>();
}
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<EndpointMiddleware>();
}
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(...)"));
}
}
}
}

View File

@ -8,11 +8,11 @@ using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
internal class ConfigureDispatcherOptions : IConfigureOptions<DispatcherOptions>
internal class ConfigureEndpointOptions : IConfigureOptions<EndpointOptions>
{
private readonly IEnumerable<EndpointDataSource> _dataSources;
public ConfigureDispatcherOptions(IEnumerable<EndpointDataSource> dataSources)
public ConfigureEndpointOptions(IEnumerable<EndpointDataSource> 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)
{

View File

@ -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<IConfigureOptions<DispatcherOptions>, ConfigureDispatcherOptions>());
// Allow global access to the list of endpoints.
services.TryAddSingleton<CompositeEndpointDataSource>(s =>
{
var options = s.GetRequiredService<IOptions<DispatcherOptions>>();
return new CompositeEndpointDataSource(options.Value.DataSources);
});
//
// Default matcher implementation
//
services.TryAddSingleton<MatchProcessorFactory, DefaultMatchProcessorFactory>();
services.TryAddSingleton<MatcherFactory, DfaMatcherFactory>();
services.TryAddTransient<DfaMatcherBuilder>();
// Link generation related services
services.TryAddSingleton<IEndpointFinder<string>, NameBasedEndpointFinder>();
services.TryAddSingleton<IEndpointFinder<RouteValuesBasedEndpointFinderContext>, RouteValuesBasedEndpointFinder>();
services.TryAddSingleton<LinkGenerator, DefaultLinkGenerator>();
//
// Endpoint Selection
//
services.TryAddSingleton<EndpointSelector>();
services.TryAddSingleton<EndpointConstraintCache>();
// Will be cached by the EndpointSelector
services.TryAddEnumerable(
ServiceDescriptor.Transient<IEndpointConstraintProvider, DefaultEndpointConstraintProvider>());
services.TryAddSingleton(typeof(DispatcherMarkerService));
return services;
return services.AddRouting();
}
public static IServiceCollection AddDispatcher(this IServiceCollection services, Action<DispatcherOptions> configuration)
// This whole class is temporary until we can remove its usage from MVC
public static IServiceCollection AddDispatcher(this IServiceCollection services, Action<EndpointOptions> configuration)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddDispatcher();
services.AddRouting();
if (configuration != null)
{
services.Configure<DispatcherOptions>(configuration);
services.Configure<EndpointOptions>(configuration);
}
return services;

View File

@ -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<IConfigureOptions<EndpointOptions>, ConfigureEndpointOptions>());
// Allow global access to the list of endpoints.
services.TryAddSingleton<CompositeEndpointDataSource>(s =>
{
var options = s.GetRequiredService<IOptions<EndpointOptions>>();
return new CompositeEndpointDataSource(options.Value.DataSources);
});
//
// Default matcher implementation
//
services.TryAddSingleton<MatchProcessorFactory, DefaultMatchProcessorFactory>();
services.TryAddSingleton<MatcherFactory, DfaMatcherFactory>();
services.TryAddTransient<DfaMatcherBuilder>();
// Link generation related services
services.TryAddSingleton<IEndpointFinder<string>, NameBasedEndpointFinder>();
services.TryAddSingleton<IEndpointFinder<RouteValuesBasedEndpointFinderContext>, RouteValuesBasedEndpointFinder>();
services.TryAddSingleton<LinkGenerator, DefaultLinkGenerator>();
//
// Endpoint Selection
//
services.TryAddSingleton<EndpointSelector>();
services.TryAddSingleton<EndpointConstraintCache>();
// Will be cached by the EndpointSelector
services.TryAddEnumerable(
ServiceDescriptor.Transient<IEndpointConstraintProvider, DefaultEndpointConstraintProvider>());
return services;
}

View File

@ -34,8 +34,8 @@ namespace Microsoft.AspNetCore.Routing
var feature = httpContext.Features.Get<IEndpointFeature>();
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);
}

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.Routing
{
public class DispatcherOptions
public class EndpointOptions
{
public IList<EndpointDataSource> DataSources { get; } = new List<EndpointDataSource>();
}

View File

@ -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<Matcher> _initializationTask;
public DispatcherMiddleware(
public GlobalRoutingMiddleware(
MatcherFactory matcherFactory,
CompositeEndpointDataSource endpointDataSource,
ILogger<DispatcherMiddleware> logger,
ILogger<GlobalRoutingMiddleware> logger,
RequestDelegate next)
{
if (matcherFactory == null)

View File

@ -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
{
/// <summary>
/// A marker class used to determine if all the dispatcher services were added
/// to the <see cref="IServiceCollection"/> before dispatcher is configured.
/// </summary>
internal class DispatcherMarkerService
{
}
}

View File

@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
{
/// <summary>
/// An interface for components that can select an <see cref="Endpoint"/> given the current request, as part
/// of the execution of <see cref="DispatcherMiddleware"/>.
/// of the execution of <see cref="GlobalRoutingMiddleware"/>.
/// </summary>
internal abstract class Matcher
{

View File

@ -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();

View File

@ -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();

View File

@ -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("/");

View File

@ -7,7 +7,6 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Routing\Microsoft.AspNetCore.Routing.csproj" />
<ProjectReference Include="..\..\samples\RoutingSample.Web\RoutingSample.Web.csproj" />
<ProjectReference Include="..\..\samples\DispatcherSample.Web\DispatcherSample.Web.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -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");

View File

@ -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<IServiceProvider>());
// Act
var ex = Assert.Throws<InvalidOperationException>(() => app.UseDispatcher());
var ex = Assert.Throws<InvalidOperationException>(() => 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();
}

View File

@ -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<IApplicationBuilder>();
applicationBuilderMock
.Setup(s => s.ApplicationServices)
.Returns(Mock.Of<IServiceProvider>());
var router = Mock.Of<IRouter>();
// Act & Assert
var exception = Assert.Throws<InvalidOperationException>(
() => 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<IRouter>(MockBehavior.Strict);
router
.Setup(r => r.RouteAsync(It.IsAny<RouteContext>()))
.Returns(Task.FromResult(0))
.Returns(Task.CompletedTask)
.Verifiable();
app.UseRouter(router.Object);
@ -84,7 +106,7 @@ namespace Microsoft.AspNetCore.Builder
var router = new Mock<IRouter>(MockBehavior.Strict);
router
.Setup(r => r.RouteAsync(It.IsAny<RouteContext>()))
.Returns(Task.FromResult(0))
.Returns(Task.CompletedTask)
.Verifiable();
app.UseRouter(b =>

View File

@ -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<IApplicationBuilder>();
applicationBuilderMock
.Setup(s => s.ApplicationServices)
.Returns(Mock.Of<IServiceProvider>());
var router = Mock.Of<IRouter>();
// Act & Assert
var exception = Assert.Throws<InvalidOperationException>(
() => 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);
}
}
}

View File

@ -35,8 +35,9 @@ namespace Microsoft.AspNetCore.Routing
var ex = await Assert.ThrowsAsync<InvalidOperationException>(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);
}

View File

@ -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<DispatcherMiddleware>,
TestSink.EnableWithTypeName<DispatcherMiddleware>);
TestSink.EnableWithTypeName<GlobalRoutingMiddleware>,
TestSink.EnableWithTypeName<GlobalRoutingMiddleware>);
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
var httpContext = new DefaultHttpContext();
httpContext.RequestServices = new TestServiceProvider();
var logger = new Logger<DispatcherMiddleware>(loggerFactory);
var logger = new Logger<GlobalRoutingMiddleware>(loggerFactory);
var middleware = CreateMiddleware(logger);
// Act
@ -82,15 +82,15 @@ namespace Microsoft.AspNetCore.Routing
Assert.Equal("testValue", endpointFeature.Values["testKey"]);
}
private DispatcherMiddleware CreateMiddleware(Logger<DispatcherMiddleware> logger = null)
private GlobalRoutingMiddleware CreateMiddleware(Logger<GlobalRoutingMiddleware> logger = null)
{
RequestDelegate next = (c) => Task.FromResult<object>(null);
logger = logger ?? new Logger<DispatcherMiddleware>(NullLoggerFactory.Instance);
logger = logger ?? new Logger<GlobalRoutingMiddleware>(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<EndpointDataSource>()),
logger,

View File

@ -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<DfaMatcherBuilder>();

View File

@ -36,7 +36,6 @@ namespace Microsoft.AspNetCore.Routing.Matchers
.AddLogging()
.AddOptions()
.AddRouting()
.AddDispatcher()
.BuildServiceProvider();
var factory = services.GetRequiredService<MatcherFactory>();

View File

@ -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);
}
}
}

View File

@ -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)
{

View File

@ -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);
}
}
}

View File

@ -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<IRouteBuilder>, Action<HttpContext>> MatchingActions
{

View File

@ -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)]

View File

@ -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]

View File

@ -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<object>(null);
}
}

View File

@ -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<UriBuildingContext> Pool = new DefaultObjectPoolProvider().Create(
new UriBuilderContextPooledObjectPolicy());
@ -1820,7 +1820,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
nestedRouters = new List<IRouter>(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<IRouter>(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<IRouter>(c.RouteData.Routers);
throw new Exception();
})
.Returns(Task.FromResult(0));
.Returns(Task.CompletedTask);
var builder = CreateBuilder();
MapInboundEntry(builder, "api/Store", handler: next.Object);