Merge 2.2 to master
This commit is contained in:
commit
06ce57da55
23
Routing.sln
23
Routing.sln
|
|
@ -19,7 +19,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Routin
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Routing.Tests", "test\Microsoft.AspNetCore.Routing.Tests\Microsoft.AspNetCore.Routing.Tests.csproj", "{636D79ED-7B32-487C-BDA5-D2A1AAA97371}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoutingSample.Web", "samples\RoutingSample.Web\RoutingSample.Web.csproj", "{DB94E647-C73A-4F52-A126-AA7544CCF33B}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoutingSandbox", "samples\RoutingSample.Web\RoutingSandbox.csproj", "{DB94E647-C73A-4F52-A126-AA7544CCF33B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C430C499-382D-47BD-B351-CF8F89C08CD2}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
|
@ -55,6 +55,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{6824486A
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swaggatherer", "tools\Swaggatherer\Swaggatherer.csproj", "{B8516771-E850-4724-BEC3-63FC00C2AE57}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSites", "WebSites", "{8E5E51D4-6B03-4FC6-9F34-6E9FA24702BD}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
test\WebSites\Directory.Build.props = test\WebSites\Directory.Build.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoutingWebSite", "test\WebSites\RoutingWebSite\RoutingWebSite.csproj", "{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -179,6 +186,18 @@ Global
|
|||
{B8516771-E850-4724-BEC3-63FC00C2AE57}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{B8516771-E850-4724-BEC3-63FC00C2AE57}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B8516771-E850-4724-BEC3-63FC00C2AE57}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -194,6 +213,8 @@ Global
|
|||
{F3D86714-4E64-41A6-9B36-A47B3683CF5D} = {D5F39F59-5725-4127-82E7-67028D006185}
|
||||
{91F47A60-9A78-4968-B10D-157D9BFAC37F} = {7F5914E2-C63F-4759-898E-462804357C90}
|
||||
{B8516771-E850-4724-BEC3-63FC00C2AE57} = {6824486A-3EFF-45D1-BEE8-8B137639C890}
|
||||
{8E5E51D4-6B03-4FC6-9F34-6E9FA24702BD} = {95359B4B-4C85-4B44-A75B-0621905C4CF6}
|
||||
{E91EC5EC-30A8-45EC-9B2F-67E2D6C39D74} = {8E5E51D4-6B03-4FC6-9F34-6E9FA24702BD}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {36C8D815-B7F1-479D-894B-E606FB8DECDA}
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
|
||||
namespace RoutingSample.Web
|
||||
{
|
||||
public class PrefixRoute : IRouter
|
||||
{
|
||||
private readonly IRouteHandler _target;
|
||||
private readonly string _prefix;
|
||||
|
||||
public PrefixRoute(IRouteHandler target, string prefix)
|
||||
{
|
||||
_target = target;
|
||||
|
||||
if (prefix == null)
|
||||
{
|
||||
prefix = "/";
|
||||
}
|
||||
else if (prefix.Length > 0 && prefix[0] != '/')
|
||||
{
|
||||
// owin.RequestPath starts with a /
|
||||
prefix = "/" + prefix;
|
||||
}
|
||||
|
||||
if (prefix.Length > 1 && prefix[prefix.Length - 1] == '/')
|
||||
{
|
||||
prefix = prefix.Substring(0, prefix.Length - 1);
|
||||
}
|
||||
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
public Task RouteAsync(RouteContext context)
|
||||
{
|
||||
var requestPath = context.HttpContext.Request.Path.Value ?? string.Empty;
|
||||
if (requestPath.StartsWith(_prefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (requestPath.Length > _prefix.Length)
|
||||
{
|
||||
var lastCharacter = requestPath[_prefix.Length];
|
||||
if (lastCharacter != '/' && lastCharacter != '#' && lastCharacter != '?')
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
context.Handler = _target.GetRequestHandler(context.HttpContext, context.RouteData);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public VirtualPathData GetVirtualPath(VirtualPathContext context)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Builder;
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace RoutingSample.Web
|
||||
namespace RoutingSandbox
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace RoutingSample.Web
|
||||
{
|
||||
public static class RouteBuilderExtensions
|
||||
{
|
||||
public static IRouteBuilder AddPrefixRoute(
|
||||
this IRouteBuilder routeBuilder,
|
||||
string prefix,
|
||||
IRouteHandler handler)
|
||||
{
|
||||
routeBuilder.Routes.Add(new PrefixRoute(handler, prefix));
|
||||
return routeBuilder;
|
||||
}
|
||||
|
||||
public static IRouteBuilder MapLocaleRoute(
|
||||
this IRouteBuilder routeBuilder,
|
||||
string locale,
|
||||
string routeTemplate,
|
||||
object defaults)
|
||||
{
|
||||
var defaultsDictionary = new RouteValueDictionary(defaults);
|
||||
defaultsDictionary.Add("locale", locale);
|
||||
|
||||
var constraintResolver = routeBuilder.ServiceProvider.GetService<IInlineConstraintResolver>();
|
||||
|
||||
var route = new Route(
|
||||
target: routeBuilder.DefaultHandler,
|
||||
routeTemplate: routeTemplate,
|
||||
defaults: defaultsDictionary,
|
||||
constraints: null,
|
||||
dataTokens: null,
|
||||
inlineConstraintResolver: constraintResolver);
|
||||
routeBuilder.Routes.Add(route);
|
||||
|
||||
return routeBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Routing.Patterns;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace RoutingSample.Web
|
||||
namespace RoutingSandbox
|
||||
{
|
||||
public class UseEndpointRoutingStartup
|
||||
{
|
||||
|
|
@ -23,12 +23,7 @@ namespace RoutingSample.Web
|
|||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<EndsWithStringRouteConstraint>();
|
||||
|
||||
services.AddRouting(options =>
|
||||
{
|
||||
options.ConstraintMap.Add("endsWith", typeof(EndsWithStringRouteConstraint));
|
||||
});
|
||||
services.AddRouting();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
|
|
@ -69,24 +64,6 @@ namespace RoutingSample.Web
|
|||
response.ContentLength = payloadLength;
|
||||
return response.Body.WriteAsync(_plainTextPayload, 0, payloadLength);
|
||||
});
|
||||
builder.MapGet(
|
||||
"/withconstraints/{id:endsWith(_001)}",
|
||||
(httpContext) =>
|
||||
{
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync("WithConstraints");
|
||||
});
|
||||
builder.MapGet(
|
||||
"/withoptionalconstraints/{id:endsWith(_001)?}",
|
||||
(httpContext) =>
|
||||
{
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync("withoptionalconstraints");
|
||||
});
|
||||
builder.MapGet(
|
||||
"/graph",
|
||||
"DFA Graph",
|
||||
|
|
@ -101,32 +78,6 @@ namespace RoutingSample.Web
|
|||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
builder.MapGet(
|
||||
"/WithSingleAsteriskCatchAll/{*path}",
|
||||
(httpContext) =>
|
||||
{
|
||||
var linkGenerator = httpContext.RequestServices.GetRequiredService<LinkGenerator>();
|
||||
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync(
|
||||
"Link: " + linkGenerator.GetPathByRouteValues(httpContext, "WithSingleAsteriskCatchAll", new { }));
|
||||
},
|
||||
new RouteValuesAddressMetadata(routeName: "WithSingleAsteriskCatchAll", requiredValues: new RouteValueDictionary()));
|
||||
builder.MapGet(
|
||||
"/WithDoubleAsteriskCatchAll/{**path}",
|
||||
(httpContext) =>
|
||||
{
|
||||
var linkGenerator = httpContext.RequestServices.GetRequiredService<LinkGenerator>();
|
||||
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync(
|
||||
"Link: " + linkGenerator.GetPathByRouteValues(httpContext, "WithDoubleAsteriskCatchAll", new { }));
|
||||
},
|
||||
new RouteValuesAddressMetadata(routeName: "WithDoubleAsteriskCatchAll", requiredValues: new RouteValueDictionary()));
|
||||
});
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ using Microsoft.AspNetCore.Routing;
|
|||
using Microsoft.AspNetCore.Routing.Constraints;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace RoutingSample.Web
|
||||
namespace RoutingSandbox
|
||||
{
|
||||
public class UseRouterStartup
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@
|
|||
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestTfms);net461</StandardTestTfms>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
|
||||
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
|
||||
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
|
|
@ -8,4 +8,8 @@
|
|||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Routing.Abstractions\Microsoft.AspNetCore.Routing.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using System.Net;
|
|||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using RoutingSample.Web;
|
||||
using RoutingWebSite;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.FunctionalTests
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Routing\Microsoft.AspNetCore.Routing.csproj" />
|
||||
<ProjectReference Include="..\..\samples\RoutingSample.Web\RoutingSample.Web.csproj" />
|
||||
<ProjectReference Include="..\WebSites\RoutingWebSite\RoutingWebSite.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -17,4 +17,4 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="$(MicrosoftAspNetCoreTestHostPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -6,7 +6,7 @@ using System.Net;
|
|||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using RoutingSample.Web;
|
||||
using RoutingWebSite;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.FunctionalTests
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<Project>
|
||||
<!-- Skip the parent folder to prevent getting test package references. -->
|
||||
<Import Project="..\..\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<DeveloperBuildTestWebsiteTfms>netcoreapp2.2</DeveloperBuildTestWebsiteTfms>
|
||||
<StandardTestWebsiteTfms>$(DeveloperBuildTestWebsiteTfms)</StandardTestWebsiteTfms>
|
||||
<StandardTestWebsiteTfms Condition=" '$(DeveloperBuild)' != 'true' ">netcoreapp2.2</StandardTestWebsiteTfms>
|
||||
<StandardTestWebsiteTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestWebsiteTfms);net461</StandardTestWebsiteTfms>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -6,7 +6,7 @@ using System.Globalization;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
|
||||
namespace RoutingSample.Web
|
||||
namespace RoutingWebSite
|
||||
{
|
||||
internal class EndsWithStringRouteConstraint : IRouteConstraint
|
||||
{
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Routing.Matching;
|
||||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
public static class EndpointRouteBuilderExtensions
|
||||
{
|
||||
public static IEndpointConventionBuilder MapHello(this IEndpointRouteBuilder builder, string template, string greeter)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
var pipeline = builder.CreateApplicationBuilder()
|
||||
.UseHello(greeter)
|
||||
.Build();
|
||||
|
||||
return builder.Map(
|
||||
template,
|
||||
"Hello " + greeter,
|
||||
pipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Options;
|
||||
using RoutingWebSite.HelloExtension;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
public static class HelloAppBuilderExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseHello(this IApplicationBuilder app, string greeter)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
return app.UseMiddleware<HelloMiddleware>(Options.Create(new HelloOptions
|
||||
{
|
||||
Greeter = greeter
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace RoutingWebSite.HelloExtension
|
||||
{
|
||||
public class HelloMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly HelloOptions _helloOptions;
|
||||
private readonly byte[] _helloPayload;
|
||||
|
||||
public HelloMiddleware(RequestDelegate next, IOptions<HelloOptions> helloOptions)
|
||||
{
|
||||
_next = next;
|
||||
_helloOptions = helloOptions.Value;
|
||||
|
||||
var payload = new List<byte>();
|
||||
payload.AddRange(Encoding.UTF8.GetBytes("Hello"));
|
||||
if (!string.IsNullOrEmpty(_helloOptions.Greeter))
|
||||
{
|
||||
payload.Add((byte)' ');
|
||||
payload.AddRange(Encoding.UTF8.GetBytes(_helloOptions.Greeter));
|
||||
}
|
||||
_helloPayload = payload.ToArray();
|
||||
}
|
||||
|
||||
public Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
var response = context.Response;
|
||||
var payloadLength = _helloPayload.Length;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
response.ContentLength = payloadLength;
|
||||
return response.Body.WriteAsync(_helloPayload, 0, payloadLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace RoutingWebSite.HelloExtension
|
||||
{
|
||||
public class HelloOptions
|
||||
{
|
||||
public string Greeter { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// 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;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace RoutingWebSite
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public const string EndpointRoutingScenario = "endpointrouting";
|
||||
public const string RouterScenario = "router";
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var webHost = GetWebHostBuilder(args).Build();
|
||||
webHost.Run();
|
||||
}
|
||||
|
||||
// For unit testing
|
||||
public static IWebHostBuilder GetWebHostBuilder(string[] args)
|
||||
{
|
||||
string scenario;
|
||||
if (args.Length == 0)
|
||||
{
|
||||
Console.WriteLine("Choose a sample to run:");
|
||||
Console.WriteLine($"1. {EndpointRoutingScenario}");
|
||||
Console.WriteLine($"2. {RouterScenario}");
|
||||
Console.WriteLine();
|
||||
|
||||
scenario = Console.ReadLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
scenario = args[0];
|
||||
}
|
||||
|
||||
Type startupType;
|
||||
switch (scenario)
|
||||
{
|
||||
case "1":
|
||||
case EndpointRoutingScenario:
|
||||
startupType = typeof(UseEndpointRoutingStartup);
|
||||
break;
|
||||
|
||||
case "2":
|
||||
case RouterScenario:
|
||||
startupType = typeof(UseRouterStartup);
|
||||
break;
|
||||
|
||||
default:
|
||||
Console.WriteLine($"unknown scenario {scenario}");
|
||||
Console.WriteLine($"usage: dotnet run -- ({EndpointRoutingScenario}|{RouterScenario})");
|
||||
throw new InvalidOperationException();
|
||||
|
||||
}
|
||||
|
||||
return new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
.ConfigureLogging(b =>
|
||||
{
|
||||
b.AddConsole();
|
||||
b.SetMinimumLevel(LogLevel.Critical);
|
||||
})
|
||||
.UseContentRoot(Environment.CurrentDirectory)
|
||||
.UseStartup(startupType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<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.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Routing.Internal;
|
||||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace RoutingWebSite
|
||||
{
|
||||
public class UseEndpointRoutingStartup
|
||||
{
|
||||
private static readonly byte[] _homePayload = Encoding.UTF8.GetBytes("Endpoint Routing sample endpoints:" + Environment.NewLine + "/plaintext");
|
||||
private static readonly byte[] _plainTextPayload = Encoding.UTF8.GetBytes("Plain text!");
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<EndsWithStringRouteConstraint>();
|
||||
|
||||
services.AddRouting(options =>
|
||||
{
|
||||
options.ConstraintMap.Add("endsWith", typeof(EndsWithStringRouteConstraint));
|
||||
});
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseEndpointRouting(builder =>
|
||||
{
|
||||
builder.MapHello("/helloworld", "World");
|
||||
|
||||
builder.MapGet(
|
||||
"/",
|
||||
(httpContext) =>
|
||||
{
|
||||
var dataSource = httpContext.RequestServices.GetRequiredService<EndpointDataSource>();
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("Endpoints:");
|
||||
foreach (var endpoint in dataSource.Endpoints.OfType<RouteEndpoint>().OrderBy(e => e.RoutePattern.RawText, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.AppendLine($"- {endpoint.RoutePattern.RawText}");
|
||||
}
|
||||
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync(sb.ToString());
|
||||
});
|
||||
builder.MapGet(
|
||||
"/plaintext",
|
||||
(httpContext) =>
|
||||
{
|
||||
var response = httpContext.Response;
|
||||
var payloadLength = _plainTextPayload.Length;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
response.ContentLength = payloadLength;
|
||||
return response.Body.WriteAsync(_plainTextPayload, 0, payloadLength);
|
||||
});
|
||||
builder.MapGet(
|
||||
"/withconstraints/{id:endsWith(_001)}",
|
||||
(httpContext) =>
|
||||
{
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync("WithConstraints");
|
||||
});
|
||||
builder.MapGet(
|
||||
"/withoptionalconstraints/{id:endsWith(_001)?}",
|
||||
(httpContext) =>
|
||||
{
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync("withoptionalconstraints");
|
||||
});
|
||||
builder.MapGet(
|
||||
"/WithSingleAsteriskCatchAll/{*path}",
|
||||
(httpContext) =>
|
||||
{
|
||||
var linkGenerator = httpContext.RequestServices.GetRequiredService<LinkGenerator>();
|
||||
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync(
|
||||
"Link: " + linkGenerator.GetPathByRouteValues(httpContext, "WithSingleAsteriskCatchAll", new { }));
|
||||
},
|
||||
new RouteValuesAddressMetadata(routeName: "WithSingleAsteriskCatchAll", requiredValues: new RouteValueDictionary()));
|
||||
builder.MapGet(
|
||||
"/WithDoubleAsteriskCatchAll/{**path}",
|
||||
(httpContext) =>
|
||||
{
|
||||
var linkGenerator = httpContext.RequestServices.GetRequiredService<LinkGenerator>();
|
||||
|
||||
var response = httpContext.Response;
|
||||
response.StatusCode = 200;
|
||||
response.ContentType = "text/plain";
|
||||
return response.WriteAsync(
|
||||
"Link: " + linkGenerator.GetPathByRouteValues(httpContext, "WithDoubleAsteriskCatchAll", new { }));
|
||||
},
|
||||
new RouteValuesAddressMetadata(routeName: "WithDoubleAsteriskCatchAll", requiredValues: new RouteValueDictionary()));
|
||||
});
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
// Imagine some more stuff here...
|
||||
|
||||
app.UseEndpoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Routing.Constraints;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace RoutingWebSite
|
||||
{
|
||||
public class UseRouterStartup
|
||||
{
|
||||
private static readonly TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(10);
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddRouting();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseRouter(routes =>
|
||||
{
|
||||
routes.DefaultHandler = new RouteHandler((httpContext) =>
|
||||
{
|
||||
var request = httpContext.Request;
|
||||
return httpContext.Response.WriteAsync($"Verb = {request.Method.ToUpperInvariant()} - Path = {request.Path} - Route values - {string.Join(", ", httpContext.GetRouteData().Values)}");
|
||||
});
|
||||
|
||||
routes.MapGet("api/get/{id}", (request, response, routeData) => response.WriteAsync($"API Get {routeData.Values["id"]}"))
|
||||
.MapMiddlewareRoute("api/middleware", (appBuilder) => appBuilder.Use((httpContext, next) => httpContext.Response.WriteAsync("Middleware!")))
|
||||
.MapRoute(
|
||||
name: "AllVerbs",
|
||||
template: "api/all/{name}/{lastName?}",
|
||||
defaults: new { lastName = "Doe" },
|
||||
constraints: new { lastName = new RegexRouteConstraint(new Regex("[a-zA-Z]{3}", RegexOptions.CultureInvariant, RegexMatchTimeout)) });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue