From 658b37d2bd3b0da2c07e25b53fa5c97ce8d656d3 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Thu, 28 Mar 2019 15:41:11 -0700 Subject: [PATCH] Make UseEndpoints a thing (#8765) * Make endpoint middleware explicit This change makes the endpoint middleware explicit again, and updates all of the templates. The other change here is make UseEndpoints be the place where you register endpoints. This is vital because it puts your code visually at the point of the pipeline where it executes. Lastly, I removed support for UseMvc with endpoint routing. This is causing issues for some security features, and we're moving in the direction of trying to make the middleware heavy implementation required in 3.0. There are some issues we won't be able to fix in MVC if we can't unambiguously know if UseMvc was used or the middleware. --- .../samples/AzureADB2CSample/Startup.cs | 13 +- .../AzureAD/samples/AzureADSample/Startup.cs | 13 +- .../testassets/AzureAD.WebSite/Startup.cs | 11 +- .../BlazorHosted-CSharp.Server/Startup.cs | 6 +- ...ComponentEndpointRouteBuilderExtensions.cs | 30 +- .../src/Circuits/DefaultCircuitFactory.cs | 2 +- .../ComponentsApp.Server/Startup.cs | 9 +- .../test/testassets/TestServer/Startup.cs | 24 +- .../Http/src/Internal/ApplicationBuilder.cs | 12 +- .../test/Internal/ApplicationBuilderTests.cs | 14 +- ...rosoft.AspNetCore.Routing.netcoreapp3.0.cs | 23 +- .../Builder/EndpointRouteBuilderExtensions.cs | 48 +-- ...ointRoutingApplicationBuilderExtensions.cs | 132 ++++-- .../FallbackEndpointRouteBuilderExtensions.cs | 20 +- .../src/DefaultEndpointRouteBuilder.cs | 9 +- .../RoutingServiceCollectionExtensions.cs | 5 - .../Routing/src/EndpointRoutingMiddleware.cs | 20 +- ...RoutingApplicationBuilderExtensionsTest.cs | 154 ++++++- ...EndpointDataSourceBuilderExtensionsTest.cs | 11 +- .../EndpointRoutingMiddlewareTest.cs | 3 +- .../Benchmarks/StartupUsingEndpointRouting.cs | 10 +- ...FrameworkEndpointRouteBuilderExtensions.cs | 12 +- .../EndpointRouteBuilderExtensions.cs | 10 +- .../UseEndpointRoutingStartup.cs | 19 +- .../EndpointRouteBuilderExtensions.cs | 10 +- .../RoutingWebSite/MapFallbackStartup.cs | 11 +- .../UseEndpointRoutingStartup.cs | 59 ++- .../samples/ApiAuthSample/Startup.cs | 10 +- .../IdentitySample.DefaultUI/Startup.cs | 12 +- .../samples/IdentitySample.Mvc/Startup.cs | 12 +- .../NoIdentityStartup.cs | 10 +- .../Identity.DefaultUI.WebSite/StartupBase.cs | 16 +- .../CORS/samples/SampleDestination/Startup.cs | 18 +- ....Diagnostics.HealthChecks.netcoreapp3.0.cs | 4 +- ...althCheckEndpointRouteBuilderExtensions.cs | 28 +- ...CheckEndpointRouteBuilderExtensionsTest.cs | 15 +- .../samples/NodeServicesExamples/Startup.cs | 8 +- src/Middleware/SpaServices/README.md | 3 + .../SpaServices/samples/Webpack/Startup.cs | 7 +- ...ft.AspNetCore.StaticFiles.netcoreapp3.0.cs | 8 +- ...aticFilesEndpointRouteBuilderExtensions.cs | 44 +- .../FunctionalTests/FallbackStaticFileTest.cs | 15 +- .../StaticFileMiddlewareTests.cs | 6 +- .../UnitTests/DefaultFilesMiddlewareTests.cs | 6 +- .../DirectoryBrowserMiddlewareTests.cs | 6 +- .../Mocks/StartupOpenIdConnectTesting.cs | 24 +- .../ForTesting/Mocks/StartupSocialTesting.cs | 22 +- src/MusicStore/samples/MusicStore/Startup.cs | 22 +- .../MusicStore/StartupNtlmAuthentication.cs | 25 +- .../MusicStore/StartupOpenIdConnect.cs | 25 +- ...osoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs | 16 +- ...ontrollerEndpointRouteBuilderExtensions.cs | 114 +++--- .../MvcApplicationBuilderExtensions.cs | 63 +-- .../src/Routing/ActionEndpointDataSource.cs | 7 +- .../MvcApplicationBuilderExtensionsTest.cs | 26 +- ...AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs | 10 +- ...azorPagesEndpointRouteBuilderExtensions.cs | 80 ++-- src/Mvc/benchmarkapps/BasicApi/Startup.cs | 9 +- src/Mvc/benchmarkapps/BasicViews/Startup.cs | 11 +- .../benchmarkapps/RazorRendering/Startup.cs | 8 +- src/Mvc/samples/MvcSandbox/Startup.cs | 5 +- ...lAuthorizationFilterEndpointRoutingTest.cs | 31 ++ ...s => GlobalAuthorizationFilterTestBase.cs} | 19 +- .../GlobalAuthorizationFilterUseMvcTest.cs | 24 ++ .../Mvc.FunctionalTests/RazorPagesTest.cs | 2 +- .../RazorPagesWithBasePathTest.cs | 6 +- .../RazorPagesWithEndpointRoutingTest.cs | 4 +- .../RoutingUseMvcWithEndpointRoutingTest.cs | 386 ------------------ .../WebSites/ApiExplorerWebSite/Startup.cs | 5 +- .../ApplicationModelWebSite/Startup.cs | 9 +- src/Mvc/test/WebSites/BasicWebSite/Startup.cs | 7 +- .../BasicWebSite/StartupRequestLimitSize.cs | 7 +- ...hCookieTempDataProviderAndCookieConsent.cs | 8 +- ...artupWithCustomInvalidModelStateFactory.cs | 5 +- .../StartupWithSessionTempDataProvider.cs | 7 +- .../ControllersFromServicesWebSite/Startup.cs | 5 +- src/Mvc/test/WebSites/CorsWebSite/Startup.cs | 5 +- .../ErrorPageMiddlewareWebSite/Startup.cs | 5 +- .../test/WebSites/FSharpWebSite/Startup.fs | 3 +- src/Mvc/test/WebSites/FilesWebSite/Startup.cs | 5 +- .../test/WebSites/FormatterWebSite/Startup.cs | 5 +- .../StartupWithJsonInputFormatter.cs | 5 +- .../StartupWithRespectBrowserAcceptHeader.cs | 5 +- .../WebSites/GenericHostWebSite/Startup.cs | 9 +- .../WebSites/HtmlGenerationWebSite/Startup.cs | 11 +- .../WebSites/RazorBuildWebSite/Startup.cs | 7 +- .../WebSites/RazorPagesWebSite/Startup.cs | 13 +- .../RazorPagesWebSite/StartupWithBasePath.cs | 13 +- .../StartupWithoutEndpointRouting.cs | 2 +- src/Mvc/test/WebSites/RazorWebSite/Startup.cs | 9 +- .../RazorWebSite/StartupDataAnnotations.cs | 11 +- .../RoutingWebSite/RoutingWebSite.csproj | 2 +- .../test/WebSites/RoutingWebSite/Startup.cs | 23 +- .../RoutingWebSite/StartupForFallback.cs | 9 +- .../RoutingWebSite/StartupForLinkGenerator.cs | 7 +- .../StartupWithUseMvcAndEndpointRouting.cs | 80 ---- .../test/WebSites/SecurityWebSite/Startup.cs | 11 +- .../StartupWithGlobalDenyAnonymousFilter.cs | 9 +- ...WithGlobalDenyAnonymousFilterWithUseMvc.cs | 42 ++ .../SecurityWebSite/StartupWithUseMvc.cs | 37 ++ .../test/WebSites/SimpleWebSite/Startup.cs | 5 +- .../WebSites/TagHelpersWebSite/Startup.cs | 5 +- .../WebSites/VersioningWebSite/Startup.cs | 5 +- .../WebSites/XmlFormattersWebSite/Startup.cs | 9 +- .../content/EmptyWeb-CSharp/Startup.cs | 6 +- .../content/EmptyWeb-FSharp/Startup.fs | 8 +- .../GrpcService-CSharp.Server/Startup.cs | 6 +- .../RazorComponentsWeb-CSharp/Startup.cs | 8 +- .../content/RazorPagesWeb-CSharp/Startup.cs | 18 +- .../content/StarterWeb-CSharp/Startup.cs | 18 +- .../content/StarterWeb-FSharp/Startup.fs | 12 +- .../content/WebApi-CSharp/Startup.cs | 10 +- .../content/WebApi-FSharp/Startup.fs | 8 +- .../content/Angular-CSharp/Startup.cs | 2 +- .../content/React-CSharp/Startup.cs | 2 +- .../content/ReactRedux-CSharp/Startup.cs | 2 +- .../samples/ClaimsTransformation/Startup.cs | 12 +- src/Security/samples/Cookies/Startup.cs | 12 +- .../samples/CustomPolicyProvider/Startup.cs | 13 +- .../samples/DynamicSchemes/Startup.cs | 12 +- .../Pages/MyClaims.cshtml | 26 +- .../Identity.ExternalClaims/Startup.cs | 12 +- .../samples/PathSchemeSelection/Startup.cs | 16 +- .../samples/StaticFilesAuth/Startup.cs | 11 +- .../IdentityExternalClaimsTests.cs | 2 +- .../Client/test/FunctionalTests/Startup.cs | 25 +- .../clients/ts/FunctionalTests/Startup.cs | 40 +- ...pNetCore.Http.Connections.netcoreapp3.0.cs | 8 +- ...onnectionEndpointRouteBuilderExtensions.cs | 34 +- src/SignalR/samples/JwtSample/Startup.cs | 8 +- src/SignalR/samples/SignalRSamples/Startup.cs | 22 +- src/SignalR/samples/SocialWeather/Startup.cs | 6 +- ...rosoft.AspNetCore.SignalR.netcoreapp3.0.cs | 4 +- .../src/HubEndpointRouteBuilderExtensions.cs | 14 +- .../server/SignalR/test/MapSignalRTests.cs | 16 +- src/SignalR/server/SignalR/test/Startup.cs | 13 +- .../server/StackExchangeRedis/test/Startup.cs | 5 +- 137 files changed, 1370 insertions(+), 1303 deletions(-) create mode 100644 src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterEndpointRoutingTest.cs rename src/Mvc/test/Mvc.FunctionalTests/{GlobalAuthorizationFilterTest.cs => GlobalAuthorizationFilterTestBase.cs} (71%) create mode 100644 src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterUseMvcTest.cs delete mode 100644 src/Mvc/test/Mvc.FunctionalTests/RoutingUseMvcWithEndpointRoutingTest.cs delete mode 100644 src/Mvc/test/WebSites/RoutingWebSite/StartupWithUseMvcAndEndpointRouting.cs create mode 100644 src/Mvc/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilterWithUseMvc.cs create mode 100644 src/Mvc/test/WebSites/SecurityWebSite/StartupWithUseMvc.cs diff --git a/src/Azure/AzureAD/samples/AzureADB2CSample/Startup.cs b/src/Azure/AzureAD/samples/AzureADB2CSample/Startup.cs index 64eac40e25..258e12e41f 100644 --- a/src/Azure/AzureAD/samples/AzureADB2CSample/Startup.cs +++ b/src/Azure/AzureAD/samples/AzureADB2CSample/Startup.cs @@ -38,9 +38,18 @@ namespace AzureADB2CSample public void Configure(IApplicationBuilder app) { app.UseHttpsRedirection(); - app.UseAuthentication(); app.UseStaticFiles(); - app.UseMvcWithDefaultRoute(); + + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); + }); } } } diff --git a/src/Azure/AzureAD/samples/AzureADSample/Startup.cs b/src/Azure/AzureAD/samples/AzureADSample/Startup.cs index 98026f748a..23ccaeb069 100644 --- a/src/Azure/AzureAD/samples/AzureADSample/Startup.cs +++ b/src/Azure/AzureAD/samples/AzureADSample/Startup.cs @@ -38,9 +38,18 @@ namespace AzureADSample public void Configure(IApplicationBuilder app) { app.UseHttpsRedirection(); - app.UseAuthentication(); app.UseStaticFiles(); - app.UseMvcWithDefaultRoute(); + + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); + }); } } } diff --git a/src/Azure/AzureAD/test/testassets/AzureAD.WebSite/Startup.cs b/src/Azure/AzureAD/test/testassets/AzureAD.WebSite/Startup.cs index 4eaf1d834b..d59b400ae4 100644 --- a/src/Azure/AzureAD/test/testassets/AzureAD.WebSite/Startup.cs +++ b/src/Azure/AzureAD/test/testassets/AzureAD.WebSite/Startup.cs @@ -16,9 +16,16 @@ namespace AzureAD.WebSite public void Configure(IApplicationBuilder app) { - app.UseAuthentication(); + app.UseRouting(); - app.UseMvc(); + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); + }); } } } diff --git a/src/Components/Blazor/Templates/src/content/BlazorHosted-CSharp/BlazorHosted-CSharp.Server/Startup.cs b/src/Components/Blazor/Templates/src/content/BlazorHosted-CSharp/BlazorHosted-CSharp.Server/Startup.cs index 5dbe24ce21..964ae43d79 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorHosted-CSharp/BlazorHosted-CSharp.Server/Startup.cs +++ b/src/Components/Blazor/Templates/src/content/BlazorHosted-CSharp/BlazorHosted-CSharp.Server/Startup.cs @@ -32,9 +32,11 @@ namespace BlazorHosted_CSharp.Server app.UseBlazorDebugging(); } - app.UseMvc(routes => + app.UseRouting(); + + app.UseEndpoints(endpoints => { - routes.MapRoute(name: "default", template: "{controller}/{action}/{id?}"); + endpoints.MapDefaultControllerRoute(); }); app.UseBlazor(); diff --git a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs index 3284d3baf7..1ea661622e 100644 --- a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs +++ b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs @@ -17,16 +17,16 @@ namespace Microsoft.AspNetCore.Builder /// the component to this hub instance as the given DOM . /// /// The first associated with this . - /// The . + /// The . /// The selector for the . /// The . public static IEndpointConventionBuilder MapComponentHub( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string selector) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (selector == null) @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(selector)); } - return routes.MapComponentHub(typeof(TComponent), selector, ComponentHub.DefaultPath); + return endpoints.MapComponentHub(typeof(TComponent), selector, ComponentHub.DefaultPath); } /// @@ -42,18 +42,18 @@ namespace Microsoft.AspNetCore.Builder /// the component to this hub instance as the given DOM . /// /// The first associated with this . - /// The . + /// The . /// The selector for the . /// The path to map to which the will be mapped. /// The . public static IEndpointConventionBuilder MapComponentHub( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string selector, string path) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (path == null) @@ -66,27 +66,27 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(selector)); } - return routes.MapComponentHub(typeof(TComponent), selector, path); + return endpoints.MapComponentHub(typeof(TComponent), selector, path); } /// /// Maps the SignalR to the path and associates /// the component to this hub instance as the given DOM . /// - /// The . + /// The . /// The first associated with this . /// The selector for the . /// The path to map to which the will be mapped. /// The . public static IEndpointConventionBuilder MapComponentHub( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, Type componentType, string selector, string path) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (path == null) @@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(selector)); } - return routes.MapHub(path).AddComponent(componentType, selector); + return endpoints.MapHub(path).AddComponent(componentType, selector); } } } diff --git a/src/Components/Server/src/Circuits/DefaultCircuitFactory.cs b/src/Components/Server/src/Circuits/DefaultCircuitFactory.cs index a9c3fa9ca7..b0a493c25b 100644 --- a/src/Components/Server/src/Circuits/DefaultCircuitFactory.cs +++ b/src/Components/Server/src/Circuits/DefaultCircuitFactory.cs @@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits { throw new InvalidOperationException( $"{nameof(ComponentHub)} doesn't have an associated endpoint. " + - "Use 'app.UseRouting(routes => routes.MapComponentHub(\"app\"))' to register your hub."); + "Use 'app.UseEndpoints(endpoints => endpoints.MapComponentHub(\"app\"))' to register your hub."); } var componentsMetadata = endpoint.Metadata.OfType().ToList(); diff --git a/src/Components/test/testassets/ComponentsApp.Server/Startup.cs b/src/Components/test/testassets/ComponentsApp.Server/Startup.cs index 62479bc399..cb855dbdf2 100644 --- a/src/Components/test/testassets/ComponentsApp.Server/Startup.cs +++ b/src/Components/test/testassets/ComponentsApp.Server/Startup.cs @@ -29,10 +29,13 @@ namespace ComponentsApp.Server } app.UseStaticFiles(); - app.UseRouting(builder => + + app.UseRouting(); + + app.UseEndpoints(endpoints => { - builder.MapRazorPages(); - builder.MapComponentHub("app"); + endpoints.MapRazorPages(); + endpoints.MapComponentHub("app"); }); } } diff --git a/src/Components/test/testassets/TestServer/Startup.cs b/src/Components/test/testassets/TestServer/Startup.cs index 87a1c1c257..492aa9391a 100644 --- a/src/Components/test/testassets/TestServer/Startup.cs +++ b/src/Components/test/testassets/TestServer/Startup.cs @@ -38,24 +38,36 @@ namespace TestServer } AllowCorsForAnyLocalhostPort(app); - app.UseMvc(); + + app.UseRouting(); // Mount the server-side Blazor app on /subdir app.Map("/subdir", subdirApp => { // The following two lines are equivalent to: - // subdirApp.UseServerSideBlazor(); - // However it's expressed using UseSignalR+UseBlazor as a way of checking that - // we're not relying on any extra magic inside UseServerSideBlazor, since it's + // endpoints.MapComponentsHub(); + // + // However it's expressed using routing as a way of checking that + // we're not relying on any extra magic inside MapComponentsHub, since it's // important that people can set up these bits of middleware manually (e.g., to // swap in UseAzureSignalR instead of UseSignalR). - subdirApp.UseRouting(routes => - routes.MapHub(ComponentHub.DefaultPath).AddComponent(selector: "root")); + + subdirApp.UseRouting(); + + subdirApp.UseEndpoints(endpoints => + { + endpoints.MapHub(ComponentHub.DefaultPath).AddComponent(selector: "root"); + }); subdirApp.MapWhen( ctx => ctx.Features.Get()?.Endpoint == null, blazorBuilder => blazorBuilder.UseBlazor()); }); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); } private static void AllowCorsForAnyLocalhostPort(IApplicationBuilder app) diff --git a/src/Http/Http/src/Internal/ApplicationBuilder.cs b/src/Http/Http/src/Internal/ApplicationBuilder.cs index 8c7e5d1a50..b623dc85e9 100644 --- a/src/Http/Http/src/Internal/ApplicationBuilder.cs +++ b/src/Http/Http/src/Internal/ApplicationBuilder.cs @@ -82,11 +82,17 @@ namespace Microsoft.AspNetCore.Builder.Internal { RequestDelegate app = context => { - // Implicitly execute matched endpoint at the end of the pipeline instead of returning 404 - var endpointRequestDelegate = context.GetEndpoint()?.RequestDelegate; + // If we reach the end of the pipeline, but we have an endpoint, then something unexpected has happened. + // This could happen if user code sets an endpoint, but they forgot to add the UseEndpoint middleware. + var endpoint = context.GetEndpoint(); + var endpointRequestDelegate = endpoint?.RequestDelegate; if (endpointRequestDelegate != null) { - return endpointRequestDelegate(context); + var message = + $"The request reached the end of the pipeline without executing the endpoint: '{endpoint.DisplayName}'. " + + $"Please register the EndpointMiddleware using '{nameof(IApplicationBuilder)}.UseEndpoints(...)' if using " + + $"routing, or '{nameof(IApplicationBuilder)}.UseEndpointExecutor()' if not using routing."; + throw new InvalidOperationException(message); } context.Response.StatusCode = 404; diff --git a/src/Http/Http/test/Internal/ApplicationBuilderTests.cs b/src/Http/Http/test/Internal/ApplicationBuilderTests.cs index 2c57489f91..4e918bc79e 100644 --- a/src/Http/Http/test/Internal/ApplicationBuilderTests.cs +++ b/src/Http/Http/test/Internal/ApplicationBuilderTests.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 System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Endpoints; @@ -23,7 +24,7 @@ namespace Microsoft.AspNetCore.Builder.Internal } [Fact] - public void BuildImplicitlyCallsMatchedEndpointAsLastStep() + public async Task BuildImplicitlyThrowsForMatchedEndpointAsLastStep() { var builder = new ApplicationBuilder(null); var app = builder.Build(); @@ -41,9 +42,14 @@ namespace Microsoft.AspNetCore.Builder.Internal var httpContext = new DefaultHttpContext(); httpContext.SetEndpoint(endpoint); - app.Invoke(httpContext); + var ex = await Assert.ThrowsAsync(() => app.Invoke(httpContext)); - Assert.True(endpointCalled); + var expected = + "The request reached the end of the pipeline without executing the endpoint: 'Test endpoint'. " + + "Please register the EndpointMiddleware using 'IApplicationBuilder.UseEndpoints(...)' if " + + "using routing, or 'IApplicationBuilder.UseEndpointExecutor()' if not using routing."; + Assert.Equal(expected, ex.Message); + Assert.False(endpointCalled); } [Fact] @@ -87,4 +93,4 @@ namespace Microsoft.AspNetCore.Builder.Internal Assert.Equal("value1", builder1.Properties["test"]); } } -} \ No newline at end of file +} diff --git a/src/Http/Routing/ref/Microsoft.AspNetCore.Routing.netcoreapp3.0.cs b/src/Http/Routing/ref/Microsoft.AspNetCore.Routing.netcoreapp3.0.cs index 1da0918d91..81820c85d6 100644 --- a/src/Http/Routing/ref/Microsoft.AspNetCore.Routing.netcoreapp3.0.cs +++ b/src/Http/Routing/ref/Microsoft.AspNetCore.Routing.netcoreapp3.0.cs @@ -5,23 +5,24 @@ namespace Microsoft.AspNetCore.Builder { public static partial class EndpointRouteBuilderExtensions { - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, Microsoft.AspNetCore.Routing.Patterns.RoutePattern pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapDelete(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapGet(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapMethods(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, System.Collections.Generic.IEnumerable httpMethods, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapPost(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapPut(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, Microsoft.AspNetCore.Routing.Patterns.RoutePattern pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapDelete(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapGet(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapMethods(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Collections.Generic.IEnumerable httpMethods, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapPost(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapPut(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } } public static partial class EndpointRoutingApplicationBuilderExtensions { - public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) { throw null; } - public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRouting(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder, System.Action configure) { throw null; } + public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseEndpointExecutor(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) { throw null; } + public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseEndpoints(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder, System.Action configure) { throw null; } + public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRouting(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) { throw null; } } public static partial class FallbackEndpointRouteBuilderExtensions { - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) { throw null; } } public static partial class MapRouteRouteBuilderExtensions { diff --git a/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs b/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs index 9d8c8957bd..3e358c8cf8 100644 --- a/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs +++ b/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs @@ -26,77 +26,77 @@ namespace Microsoft.AspNetCore.Builder /// Adds a to the that matches HTTP GET requests /// for the specified pattern. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The delegate executed when the endpoint is matched. /// A that can be used to further customize the endpoint. public static IEndpointConventionBuilder MapGet( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, RequestDelegate requestDelegate) { - return MapMethods(routes, pattern, GetVerb, requestDelegate); + return MapMethods(endpoints, pattern, GetVerb, requestDelegate); } /// /// Adds a to the that matches HTTP POST requests /// for the specified pattern. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The delegate executed when the endpoint is matched. /// A that can be used to further customize the endpoint. public static IEndpointConventionBuilder MapPost( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, RequestDelegate requestDelegate) { - return MapMethods(routes, pattern, PostVerb, requestDelegate); + return MapMethods(endpoints, pattern, PostVerb, requestDelegate); } /// /// Adds a to the that matches HTTP PUT requests /// for the specified pattern. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The delegate executed when the endpoint is matched. /// A that can be used to further customize the endpoint. public static IEndpointConventionBuilder MapPut( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, RequestDelegate requestDelegate) { - return MapMethods(routes, pattern, PutVerb, requestDelegate); + return MapMethods(endpoints, pattern, PutVerb, requestDelegate); } /// /// Adds a to the that matches HTTP DELETE requests /// for the specified pattern. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The delegate executed when the endpoint is matched. /// A that can be used to further customize the endpoint. public static IEndpointConventionBuilder MapDelete( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, RequestDelegate requestDelegate) { - return MapMethods(routes, pattern, DeleteVerb, requestDelegate); + return MapMethods(endpoints, pattern, DeleteVerb, requestDelegate); } /// /// Adds a to the that matches HTTP requests /// for the specified HTTP methods and pattern. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The delegate executed when the endpoint is matched. /// HTTP methods that the endpoint will match. /// A that can be used to further customize the endpoint. public static IEndpointConventionBuilder MapMethods( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, IEnumerable httpMethods, RequestDelegate requestDelegate) @@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(httpMethods)); } - var builder = routes.Map(RoutePatternFactory.Parse(pattern), requestDelegate); + var builder = endpoints.Map(RoutePatternFactory.Parse(pattern), requestDelegate); builder.WithDisplayName($"{pattern} HTTP: {string.Join(", ", httpMethods)}"); builder.WithMetadata(new HttpMethodMetadata(httpMethods)); return builder; @@ -116,34 +116,34 @@ namespace Microsoft.AspNetCore.Builder /// Adds a to the that matches HTTP requests /// for the specified pattern. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The delegate executed when the endpoint is matched. /// A that can be used to further customize the endpoint. public static IEndpointConventionBuilder Map( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, RequestDelegate requestDelegate) { - return Map(routes, RoutePatternFactory.Parse(pattern), requestDelegate); + return Map(endpoints, RoutePatternFactory.Parse(pattern), requestDelegate); } /// /// Adds a to the that matches HTTP requests /// for the specified pattern. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The delegate executed when the endpoint is matched. /// A that can be used to further customize the endpoint. public static IEndpointConventionBuilder Map( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, RoutePattern pattern, RequestDelegate requestDelegate) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (pattern == null) @@ -178,11 +178,11 @@ namespace Microsoft.AspNetCore.Builder } } - var dataSource = routes.DataSources.OfType().FirstOrDefault(); + var dataSource = endpoints.DataSources.OfType().FirstOrDefault(); if (dataSource == null) { dataSource = new ModelEndpointDataSource(); - routes.DataSources.Add(dataSource); + endpoints.DataSources.Add(dataSource); } return dataSource.AddEndpointBuilder(builder); diff --git a/src/Http/Routing/src/Builder/EndpointRoutingApplicationBuilderExtensions.cs b/src/Http/Routing/src/Builder/EndpointRoutingApplicationBuilderExtensions.cs index 872236f22b..a253c700de 100644 --- a/src/Http/Routing/src/Builder/EndpointRoutingApplicationBuilderExtensions.cs +++ b/src/Http/Routing/src/Builder/EndpointRoutingApplicationBuilderExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Internal; using Microsoft.Extensions.DependencyInjection; @@ -11,17 +12,66 @@ namespace Microsoft.AspNetCore.Builder { public static class EndpointRoutingApplicationBuilderExtensions { - // Property key is used by MVC package to check that routing is registered - private const string EndpointRoutingRegisteredKey = "__EndpointRoutingMiddlewareRegistered"; + private const string EndpointRouteBuilder = "__EndpointRouteBuilder"; /// - /// Adds a middleware to the specified + /// Adds a middleware to the specified . + /// + /// The to add the middleware to. + /// A reference to this instance after the operation has completed. + /// + /// + /// A call to must be followed by a call to + /// for the same + /// instance. + /// + /// + /// The defines a point in the middleware pipeline where routing decisions are + /// made, and an is associated with the . The + /// defines a point in the middleware pipeline where the current is executed. Middleware between + /// the and may observe or change the + /// associated with the . + /// + /// + public static IApplicationBuilder UseRouting(this IApplicationBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + VerifyRoutingServicesAreRegistered(builder); + + var endpointRouteBuilder = new DefaultEndpointRouteBuilder(builder); + builder.Properties[EndpointRouteBuilder] = endpointRouteBuilder; + + return builder.UseMiddleware(endpointRouteBuilder); + } + + /// + /// Adds a middleware to the specified /// with the instances built from configured . + /// The will execute the associated with the current + /// request. /// /// The to add the middleware to. /// An to configure the provided . /// A reference to this instance after the operation has completed. - public static IApplicationBuilder UseRouting(this IApplicationBuilder builder, Action configure) + /// + /// + /// A call to must be preceded by a call to + /// for the same + /// instance. + /// + /// + /// The defines a point in the middleware pipeline where routing decisions are + /// made, and an is associated with the . The + /// defines a point in the middleware pipeline where the current is executed. Middleware between + /// the and may observe or change the + /// associated with the . + /// + /// + public static IApplicationBuilder UseEndpoints(this IApplicationBuilder builder, Action configure) { if (builder == null) { @@ -33,57 +83,52 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(configure)); } - VerifyRoutingIsRegistered(builder); + VerifyRoutingServicesAreRegistered(builder); - var routeOptions = builder.ApplicationServices.GetRequiredService>(); - EndpointDataSource middlewareEndpointDataSource; + VerifyEndpointRoutingMiddlewareIsRegistered(builder, out var endpointRouteBuilder); - var endpointRouteBuilder = builder.ApplicationServices.GetRequiredService(); - if (endpointRouteBuilder is DefaultEndpointRouteBuilder defaultEndpointRouteBuilder) - { - defaultEndpointRouteBuilder.ApplicationBuilder = builder; - } configure(endpointRouteBuilder); + // Yes, this mutates an IOptions. We're registering data sources in a global collection which + // can be used for discovery of endpoints or URL generation. + // + // Each middleware gets its own collection of data sources, and all of those data sources also + // get added to a global collection. + var routeOptions = builder.ApplicationServices.GetRequiredService>(); foreach (var dataSource in endpointRouteBuilder.DataSources) { routeOptions.Value.EndpointDataSources.Add(dataSource); } - // Create endpoint data source for data sources registered in configure - middlewareEndpointDataSource = new CompositeEndpointDataSource(endpointRouteBuilder.DataSources); - - builder.Properties[EndpointRoutingRegisteredKey] = true; - - return builder.UseMiddleware(middlewareEndpointDataSource); + return builder.UseMiddleware(); } /// - /// Adds a middleware to the specified . + /// Adds a middleware to the specified that will + /// execute the associated with the current request. /// /// The to add the middleware to. /// A reference to this instance after the operation has completed. - public static IApplicationBuilder UseEndpoint(this IApplicationBuilder builder) + /// + /// + /// A call to may be used to execute an endpoint with + /// using . This enables applications to use endpoints with other + /// middleware not related to routing. + /// + /// + public static IApplicationBuilder UseEndpointExecutor(this IApplicationBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } - VerifyRoutingIsRegistered(builder); - - if (!builder.Properties.TryGetValue(EndpointRoutingRegisteredKey, out _)) - { - var message = $"{nameof(EndpointRoutingMiddleware)} must be added to the request execution pipeline before {nameof(EndpointMiddleware)}. " + - $"Please add {nameof(EndpointRoutingMiddleware)} by calling '{nameof(IApplicationBuilder)}.{nameof(UseRouting)}' inside the call to 'Configure(...)' in the application startup code."; - - throw new InvalidOperationException(message); - } + // Note: we don't require routing services either. return builder.UseMiddleware(); } - private static void VerifyRoutingIsRegistered(IApplicationBuilder app) + private static void VerifyRoutingServicesAreRegistered(IApplicationBuilder app) { // Verify if AddRouting was done before calling UseEndpointRouting/UseEndpoint // We use the RoutingMarkerService to make sure if all the services were added. @@ -95,5 +140,32 @@ namespace Microsoft.AspNetCore.Builder "ConfigureServices(...)")); } } + + private static void VerifyEndpointRoutingMiddlewareIsRegistered(IApplicationBuilder app, out DefaultEndpointRouteBuilder endpointRouteBuilder) + { + if (!app.Properties.TryGetValue(EndpointRouteBuilder, out var obj)) + { + var message = + $"{nameof(EndpointRoutingMiddleware)} matches endpoints setup by {nameof(EndpointMiddleware)} and so must be added to the request " + + $"execution pipeline before {nameof(EndpointMiddleware)}. " + + $"Please add {nameof(EndpointRoutingMiddleware)} by calling '{nameof(IApplicationBuilder)}.{nameof(UseRouting)}' inside the call " + + $"to 'Configure(...)' in the application startup code."; + throw new InvalidOperationException(message); + } + + // If someone messes with this, just let it crash. + endpointRouteBuilder = (DefaultEndpointRouteBuilder)obj; + + // This check handles the case where Map or something else that forks the pipeline is called between the two + // routing middleware. + if (!object.ReferenceEquals(app, endpointRouteBuilder.ApplicationBuilder)) + { + var message = + $"The {nameof(EndpointRoutingMiddleware)} and {nameof(EndpointMiddleware)} must be added to the same {nameof(IApplicationBuilder)} instance. " + + $"To use Endpoint Routing with 'Map(...)', make sure to call '{nameof(IApplicationBuilder)}.{nameof(UseRouting)}' before " + + $"'{nameof(IApplicationBuilder)}.{nameof(UseEndpoints)}' for each branch of the middleware pipeline."; + throw new InvalidOperationException(message); + } + } } } diff --git a/src/Http/Routing/src/Builder/FallbackEndpointRouteBuilderExtensions.cs b/src/Http/Routing/src/Builder/FallbackEndpointRouteBuilderExtensions.cs index f034aeb873..354d0e400e 100644 --- a/src/Http/Routing/src/Builder/FallbackEndpointRouteBuilderExtensions.cs +++ b/src/Http/Routing/src/Builder/FallbackEndpointRouteBuilderExtensions.cs @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Builder /// Adds a specialized to the that will match /// requests for non-file-names with the lowest possible priority. /// - /// The to add the route to. + /// The to add the route to. /// The delegate executed when the endpoint is matched. /// A that can be used to further customize the endpoint. /// @@ -31,11 +31,11 @@ namespace Microsoft.AspNetCore.Builder /// {*path:nonfile}. The order of the registered endpoint will be int.MaxValue. /// /// - public static IEndpointConventionBuilder MapFallback(this IEndpointRouteBuilder routes, RequestDelegate requestDelegate) + public static IEndpointConventionBuilder MapFallback(this IEndpointRouteBuilder endpoints, RequestDelegate requestDelegate) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (requestDelegate == null) @@ -43,14 +43,14 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(requestDelegate)); } - return routes.MapFallback("{*path:nonfile}", requestDelegate); + return endpoints.MapFallback("{*path:nonfile}", requestDelegate); } /// /// Adds a specialized to the that will match /// the provided pattern with the lowest possible priority. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The delegate executed when the endpoint is matched. /// A that can be used to further customize the endpoint. @@ -68,13 +68,13 @@ namespace Microsoft.AspNetCore.Builder /// /// public static IEndpointConventionBuilder MapFallback( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, RequestDelegate requestDelegate) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (pattern == null) @@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(requestDelegate)); } - var conventionBuilder = routes.Map(pattern, requestDelegate); + var conventionBuilder = endpoints.Map(pattern, requestDelegate); conventionBuilder.WithDisplayName("Fallback " + pattern); conventionBuilder.Add(b => ((RouteEndpointBuilder)b).Order = int.MaxValue); return conventionBuilder; diff --git a/src/Http/Routing/src/DefaultEndpointRouteBuilder.cs b/src/Http/Routing/src/DefaultEndpointRouteBuilder.cs index d5b09e20eb..375bc098ac 100644 --- a/src/Http/Routing/src/DefaultEndpointRouteBuilder.cs +++ b/src/Http/Routing/src/DefaultEndpointRouteBuilder.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; @@ -9,12 +9,13 @@ namespace Microsoft.AspNetCore.Routing { internal class DefaultEndpointRouteBuilder : IEndpointRouteBuilder { - public DefaultEndpointRouteBuilder() + public DefaultEndpointRouteBuilder(IApplicationBuilder applicationBuilder) { + ApplicationBuilder = applicationBuilder ?? throw new ArgumentNullException(nameof(applicationBuilder)); DataSources = new List(); } - public IApplicationBuilder ApplicationBuilder { get; set; } + public IApplicationBuilder ApplicationBuilder { get; } public IApplicationBuilder CreateApplicationBuilder() => ApplicationBuilder.New(); @@ -22,4 +23,4 @@ namespace Microsoft.AspNetCore.Routing public IServiceProvider ServiceProvider => ApplicationBuilder.ApplicationServices; } -} \ No newline at end of file +} diff --git a/src/Http/Routing/src/DependencyInjection/RoutingServiceCollectionExtensions.cs b/src/Http/Routing/src/DependencyInjection/RoutingServiceCollectionExtensions.cs index dcb8c6349e..94c1efdd26 100644 --- a/src/Http/Routing/src/DependencyInjection/RoutingServiceCollectionExtensions.cs +++ b/src/Http/Routing/src/DependencyInjection/RoutingServiceCollectionExtensions.cs @@ -64,11 +64,6 @@ namespace Microsoft.Extensions.DependencyInjection return new CompositeEndpointDataSource(dataSources); }); - // - // Endpoint Infrastructure - // - services.TryAddTransient(); - // // Default matcher implementation // diff --git a/src/Http/Routing/src/EndpointRoutingMiddleware.cs b/src/Http/Routing/src/EndpointRoutingMiddleware.cs index 7b18916f29..162ad8a21b 100644 --- a/src/Http/Routing/src/EndpointRoutingMiddleware.cs +++ b/src/Http/Routing/src/EndpointRoutingMiddleware.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; @@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Routing { @@ -23,8 +22,8 @@ namespace Microsoft.AspNetCore.Routing public EndpointRoutingMiddleware( MatcherFactory matcherFactory, - EndpointDataSource endpointDataSource, ILogger logger, + IEndpointRouteBuilder endpointRouteBuilder, RequestDelegate next) { if (matcherFactory == null) @@ -32,25 +31,26 @@ namespace Microsoft.AspNetCore.Routing throw new ArgumentNullException(nameof(matcherFactory)); } - if (endpointDataSource == null) - { - throw new ArgumentNullException(nameof(endpointDataSource)); - } - if (logger == null) { throw new ArgumentNullException(nameof(logger)); } + if (endpointRouteBuilder == null) + { + throw new ArgumentNullException(nameof(endpointRouteBuilder)); + } + if (next == null) { throw new ArgumentNullException(nameof(next)); } _matcherFactory = matcherFactory; - _endpointDataSource = endpointDataSource; _logger = logger; _next = next; + + _endpointDataSource = new CompositeEndpointDataSource(endpointRouteBuilder.DataSources); } public async Task Invoke(HttpContext httpContext) @@ -165,4 +165,4 @@ namespace Microsoft.AspNetCore.Routing } } } -} \ No newline at end of file +} diff --git a/src/Http/Routing/test/UnitTests/Builder/EndpointRoutingApplicationBuilderExtensionsTest.cs b/src/Http/Routing/test/UnitTests/Builder/EndpointRoutingApplicationBuilderExtensionsTest.cs index 804af033a6..1941d77b98 100644 --- a/src/Http/Routing/test/UnitTests/Builder/EndpointRoutingApplicationBuilderExtensionsTest.cs +++ b/src/Http/Routing/test/UnitTests/Builder/EndpointRoutingApplicationBuilderExtensionsTest.cs @@ -6,13 +6,13 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder.Internal; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Endpoints; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Matching; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.TestObjects; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; using Moq; using Xunit; @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Builder var app = new ApplicationBuilder(Mock.Of()); // Act - var ex = Assert.Throws(() => app.UseRouting(builder => { })); + var ex = Assert.Throws(() => app.UseRouting()); // Assert Assert.Equal( @@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Builder var app = new ApplicationBuilder(Mock.Of()); // Act - var ex = Assert.Throws(() => app.UseEndpoint()); + var ex = Assert.Throws(() => app.UseEndpoints(endpoints => { })); // Assert Assert.Equal( @@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Builder var app = new ApplicationBuilder(services); - app.UseRouting(builder => { }); + app.UseRouting(); var appFunc = app.Build(); var httpContext = new DefaultHttpContext(); @@ -89,9 +89,11 @@ namespace Microsoft.AspNetCore.Builder var app = new ApplicationBuilder(services); - app.UseRouting(builder => + app.UseRouting(); + + app.UseEndpoints(endpoints => { - builder.DataSources.Add(new DefaultEndpointDataSource(endpoint)); + endpoints.DataSources.Add(new DefaultEndpointDataSource(endpoint)); }); var appFunc = app.Build(); @@ -107,7 +109,7 @@ namespace Microsoft.AspNetCore.Builder } [Fact] - public void UseEndpoint_WithoutRoutingServicesRegistered_Throws() + public void UseEndpoint_WithoutEndpointRoutingMiddleware_Throws() { // Arrange var services = CreateServices(); @@ -115,16 +117,38 @@ namespace Microsoft.AspNetCore.Builder var app = new ApplicationBuilder(services); // Act - var ex = Assert.Throws(() => app.UseEndpoint()); + var ex = Assert.Throws(() => app.UseEndpoints(endpoints => { })); // Assert Assert.Equal( - "EndpointRoutingMiddleware must be added to the request execution pipeline before EndpointMiddleware. " + + "EndpointRoutingMiddleware matches endpoints setup by EndpointMiddleware and so must be added to the request " + + "execution pipeline before EndpointMiddleware. " + "Please add EndpointRoutingMiddleware by calling 'IApplicationBuilder.UseRouting' " + "inside the call to 'Configure(...)' in the application startup code.", ex.Message); } + [Fact] + public void UseEndpoint_WithApplicationBuilderMismatch_Throws() + { + // Arrange + var services = CreateServices(); + + var app = new ApplicationBuilder(services); + + app.UseRouting(); + + // Act + var ex = Assert.Throws(() => app.Map("/Test", b => b.UseEndpoints(endpoints => { }))); + + // Assert + Assert.Equal( + "The EndpointRoutingMiddleware and EndpointMiddleware must be added to the same IApplicationBuilder instance. " + + "To use Endpoint Routing with 'Map(...)', make sure to call 'IApplicationBuilder.UseRouting' before " + + "'IApplicationBuilder.UseEndpoints' for each branch of the middleware pipeline.", + ex.Message); + } + [Fact] public async Task UseEndpoint_ServicesRegisteredAndEndpointRoutingRegistered_NoMatch_DoesNotSetFeature() { @@ -133,8 +157,8 @@ namespace Microsoft.AspNetCore.Builder var app = new ApplicationBuilder(services); - app.UseRouting(builder => { }); - app.UseEndpoint(); + app.UseRouting(); + app.UseEndpoints(endpoints => { }); var appFunc = app.Build(); var httpContext = new DefaultHttpContext(); @@ -147,7 +171,7 @@ namespace Microsoft.AspNetCore.Builder } [Fact] - public void UseRouting_CallWithBuilder_SetsEndpointDataSource() + public void UseEndpoints_CallWithBuilder_SetsEndpointDataSource() { // Arrange var matcherEndpointDataSources = new List(); @@ -165,13 +189,15 @@ namespace Microsoft.AspNetCore.Builder var app = new ApplicationBuilder(services); // Act - app.UseRouting(builder => + app.UseRouting(); + app.UseEndpoints(builder => { builder.Map("/1", d => null).WithDisplayName("Test endpoint 1"); builder.Map("/2", d => null).WithDisplayName("Test endpoint 2"); }); - app.UseRouting(builder => + app.UseRouting(); + app.UseEndpoints(builder => { builder.Map("/3", d => null).WithDisplayName("Test endpoint 3"); builder.Map("/4", d => null).WithDisplayName("Test endpoint 4"); @@ -185,16 +211,83 @@ namespace Microsoft.AspNetCore.Builder // Assert Assert.Equal(2, matcherEndpointDataSources.Count); - // Each middleware has its own endpoints + // each UseRouter has its own data source collection Assert.Collection(matcherEndpointDataSources[0].Endpoints, e => Assert.Equal("Test endpoint 1", e.DisplayName), e => Assert.Equal("Test endpoint 2", e.DisplayName)); + Assert.Collection(matcherEndpointDataSources[1].Endpoints, e => Assert.Equal("Test endpoint 3", e.DisplayName), e => Assert.Equal("Test endpoint 4", e.DisplayName)); var compositeEndpointBuilder = services.GetRequiredService(); + // Global collection has all endpoints + Assert.Collection(compositeEndpointBuilder.Endpoints, + e => Assert.Equal("Test endpoint 1", e.DisplayName), + e => Assert.Equal("Test endpoint 2", e.DisplayName), + e => Assert.Equal("Test endpoint 3", e.DisplayName), + e => Assert.Equal("Test endpoint 4", e.DisplayName)); + } + + // Verifies that it's possible to use endpoints and map together. + [Fact] + public void UseEndpoints_CallWithBuilder_SetsEndpointDataSource_WithMap() + { + // Arrange + var matcherEndpointDataSources = new List(); + var matcherFactoryMock = new Mock(); + matcherFactoryMock + .Setup(m => m.CreateMatcher(It.IsAny())) + .Callback((EndpointDataSource arg) => + { + matcherEndpointDataSources.Add(arg); + }) + .Returns(new TestMatcher(false)); + + var services = CreateServices(matcherFactoryMock.Object); + + var app = new ApplicationBuilder(services); + + // Act + app.UseRouting(); + + app.Map("/foo", b => + { + b.UseRouting(); + b.UseEndpoints(builder => + { + builder.Map("/1", d => null).WithDisplayName("Test endpoint 1"); + builder.Map("/2", d => null).WithDisplayName("Test endpoint 2"); + }); + }); + + app.UseEndpoints(builder => + { + builder.Map("/3", d => null).WithDisplayName("Test endpoint 3"); + builder.Map("/4", d => null).WithDisplayName("Test endpoint 4"); + }); + + // This triggers the middleware to be created and the matcher factory to be called + // with the datasource we want to test + var requestDelegate = app.Build(); + requestDelegate(new DefaultHttpContext()); + requestDelegate(new DefaultHttpContext() { Request = { Path = "/Foo", }, }); + + // Assert + Assert.Equal(2, matcherEndpointDataSources.Count); + + // Each UseRouter has its own data source + Assert.Collection(matcherEndpointDataSources[1].Endpoints, // app.UseRouter + e => Assert.Equal("Test endpoint 1", e.DisplayName), + e => Assert.Equal("Test endpoint 2", e.DisplayName)); + + Assert.Collection(matcherEndpointDataSources[0].Endpoints, // b.UseRouter + e => Assert.Equal("Test endpoint 3", e.DisplayName), + e => Assert.Equal("Test endpoint 4", e.DisplayName)); + + var compositeEndpointBuilder = services.GetRequiredService(); + // Global middleware has all endpoints Assert.Collection(compositeEndpointBuilder.Endpoints, e => Assert.Equal("Test endpoint 1", e.DisplayName), @@ -203,6 +296,37 @@ namespace Microsoft.AspNetCore.Builder e => Assert.Equal("Test endpoint 4", e.DisplayName)); } + [Fact] + public async Task UseEndpointExecutor_RunsEndpoint() + { + // Arrange + var services = CreateServices(); + + var endpointRan = false; + var app = new ApplicationBuilder(services); + + app.Use(next => context => + { + context.SetEndpoint(new Endpoint(c => + { + endpointRan = true; + return Task.CompletedTask; + }, new EndpointMetadataCollection(), "Test")); + return next(context); + }); + + app.UseEndpointExecutor(); // No services required, no UseRouting required + + var appFunc = app.Build(); + var httpContext = new DefaultHttpContext(); + + // Act + await appFunc(httpContext); + + // Assert + Assert.True(endpointRan); + } + private IServiceProvider CreateServices() { return CreateServices(matcherFactory: null); diff --git a/src/Http/Routing/test/UnitTests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs b/src/Http/Routing/test/UnitTests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs index e68d1a0bfc..deff542b1f 100644 --- a/src/Http/Routing/test/UnitTests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs +++ b/src/Http/Routing/test/UnitTests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Patterns; +using Moq; using Xunit; namespace Microsoft.AspNetCore.Builder @@ -29,7 +30,7 @@ namespace Microsoft.AspNetCore.Builder public void MapEndpoint_StringPattern_BuildsEndpoint() { // Arrange - var builder = new DefaultEndpointRouteBuilder(); + var builder = new DefaultEndpointRouteBuilder(Mock.Of()); RequestDelegate requestDelegate = (d) => null; // Act @@ -47,7 +48,7 @@ namespace Microsoft.AspNetCore.Builder public void MapEndpoint_TypedPattern_BuildsEndpoint() { // Arrange - var builder = new DefaultEndpointRouteBuilder(); + var builder = new DefaultEndpointRouteBuilder(Mock.Of()); RequestDelegate requestDelegate = (d) => null; // Act @@ -65,7 +66,7 @@ namespace Microsoft.AspNetCore.Builder public void MapEndpoint_AttributesCollectedAsMetadata() { // Arrange - var builder = new DefaultEndpointRouteBuilder(); + var builder = new DefaultEndpointRouteBuilder(Mock.Of()); // Act var endpointBuilder = builder.Map(RoutePatternFactory.Parse("/"), Handle); @@ -82,7 +83,7 @@ namespace Microsoft.AspNetCore.Builder public void MapEndpoint_GeneratedDelegateWorks() { // Arrange - var builder = new DefaultEndpointRouteBuilder(); + var builder = new DefaultEndpointRouteBuilder(Mock.Of()); Expression handler = context => Task.CompletedTask; @@ -98,7 +99,7 @@ namespace Microsoft.AspNetCore.Builder public void MapEndpoint_PrecedenceOfMetadata_BuilderMetadataReturned() { // Arrange - var builder = new DefaultEndpointRouteBuilder(); + var builder = new DefaultEndpointRouteBuilder(Mock.Of()); // Act var endpointBuilder = builder.MapMethods("/", new[] { "METHOD" }, HandleHttpMetdata); diff --git a/src/Http/Routing/test/UnitTests/EndpointRoutingMiddlewareTest.cs b/src/Http/Routing/test/UnitTests/EndpointRoutingMiddlewareTest.cs index df5c703fb2..97f33a2fbe 100644 --- a/src/Http/Routing/test/UnitTests/EndpointRoutingMiddlewareTest.cs +++ b/src/Http/Routing/test/UnitTests/EndpointRoutingMiddlewareTest.cs @@ -4,6 +4,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing.Matching; @@ -153,8 +154,8 @@ namespace Microsoft.AspNetCore.Routing var middleware = new EndpointRoutingMiddleware( matcherFactory, - new DefaultEndpointDataSource(), logger, + new DefaultEndpointRouteBuilder(Mock.Of()), next); return middleware; diff --git a/src/Http/Routing/test/testassets/Benchmarks/StartupUsingEndpointRouting.cs b/src/Http/Routing/test/testassets/Benchmarks/StartupUsingEndpointRouting.cs index beeef2bbad..0b7db66f14 100644 --- a/src/Http/Routing/test/testassets/Benchmarks/StartupUsingEndpointRouting.cs +++ b/src/Http/Routing/test/testassets/Benchmarks/StartupUsingEndpointRouting.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.Text; @@ -21,7 +21,9 @@ namespace Benchmarks public void Configure(IApplicationBuilder app) { - app.UseRouting(builder => + app.UseRouting(); + + app.UseEndpoints(endpoints => { var endpointDataSource = new DefaultEndpointDataSource(new[] { @@ -41,10 +43,8 @@ namespace Benchmarks displayName: "Plaintext"), }); - builder.DataSources.Add(endpointDataSource); + endpoints.DataSources.Add(endpointDataSource); }); - - app.UseEndpoint(); } } } diff --git a/src/Http/Routing/test/testassets/RoutingSandbox/Framework/FrameworkEndpointRouteBuilderExtensions.cs b/src/Http/Routing/test/testassets/RoutingSandbox/Framework/FrameworkEndpointRouteBuilderExtensions.cs index 1bfcc445e8..2a430a28ce 100644 --- a/src/Http/Routing/test/testassets/RoutingSandbox/Framework/FrameworkEndpointRouteBuilderExtensions.cs +++ b/src/Http/Routing/test/testassets/RoutingSandbox/Framework/FrameworkEndpointRouteBuilderExtensions.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; @@ -15,23 +15,23 @@ namespace RoutingSandbox.Framework { public static class FrameworkEndpointRouteBuilderExtensions { - public static IEndpointConventionBuilder MapFramework(this IEndpointRouteBuilder routes, Action configure) + public static IEndpointConventionBuilder MapFramework(this IEndpointRouteBuilder endpoints, Action configure) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (configure == null) { throw new ArgumentNullException(nameof(configure)); } - var dataSource = routes.ServiceProvider.GetRequiredService(); + var dataSource = endpoints.ServiceProvider.GetRequiredService(); var configurationBuilder = new FrameworkConfigurationBuilder(dataSource); configure(configurationBuilder); - routes.DataSources.Add(dataSource); + endpoints.DataSources.Add(dataSource); return dataSource; } diff --git a/src/Http/Routing/test/testassets/RoutingSandbox/HelloExtension/EndpointRouteBuilderExtensions.cs b/src/Http/Routing/test/testassets/RoutingSandbox/HelloExtension/EndpointRouteBuilderExtensions.cs index d08ac2d3a5..03bc1f1125 100644 --- a/src/Http/Routing/test/testassets/RoutingSandbox/HelloExtension/EndpointRouteBuilderExtensions.cs +++ b/src/Http/Routing/test/testassets/RoutingSandbox/HelloExtension/EndpointRouteBuilderExtensions.cs @@ -13,18 +13,18 @@ namespace Microsoft.AspNetCore.Builder { public static class EndpointRouteBuilderExtensions { - public static IEndpointConventionBuilder MapHello(this IEndpointRouteBuilder routes, string pattern, string greeter) + public static IEndpointConventionBuilder MapHello(this IEndpointRouteBuilder endpoints, string pattern, string greeter) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } - var pipeline = routes.CreateApplicationBuilder() + var pipeline = endpoints.CreateApplicationBuilder() .UseHello(greeter) .Build(); - return routes.Map(pattern, pipeline); + return endpoints.Map(pattern, pipeline); } } } diff --git a/src/Http/Routing/test/testassets/RoutingSandbox/UseEndpointRoutingStartup.cs b/src/Http/Routing/test/testassets/RoutingSandbox/UseEndpointRoutingStartup.cs index 8a7740f4f1..116f743ad4 100644 --- a/src/Http/Routing/test/testassets/RoutingSandbox/UseEndpointRoutingStartup.cs +++ b/src/Http/Routing/test/testassets/RoutingSandbox/UseEndpointRoutingStartup.cs @@ -32,11 +32,13 @@ namespace RoutingSandbox public void Configure(IApplicationBuilder app) { - app.UseRouting(builder => + app.UseStaticFiles(); + app.UseRouting(); + app.UseEndpoints(endpoints => { - builder.MapHello("/helloworld", "World"); + endpoints.MapHello("/helloworld", "World"); - builder.MapGet( + endpoints.MapGet( "/", (httpContext) => { @@ -58,7 +60,7 @@ namespace RoutingSandbox response.ContentType = "text/plain"; return response.WriteAsync(sb.ToString()); }); - builder.MapGet( + endpoints.MapGet( "/plaintext", (httpContext) => { @@ -69,7 +71,7 @@ namespace RoutingSandbox response.ContentLength = payloadLength; return response.Body.WriteAsync(_plainTextPayload, 0, payloadLength); }); - builder.MapGet( + endpoints.MapGet( "/graph", (httpContext) => { @@ -83,11 +85,11 @@ namespace RoutingSandbox return Task.CompletedTask; }).WithDisplayName("DFA Graph"); - builder.MapGet("/attributes", HandlerWithAttributes); + endpoints.MapGet("/attributes", HandlerWithAttributes); - builder.Map("/getwithattributes", Handler); + endpoints.Map("/getwithattributes", Handler); - builder.MapFramework(frameworkBuilder => + endpoints.MapFramework(frameworkBuilder => { frameworkBuilder.AddPattern("/transform/{hub:slugify=TestHub}/{method:slugify=TestMethod}"); frameworkBuilder.AddPattern("/{hub}/{method=TestMethod}"); @@ -98,7 +100,6 @@ namespace RoutingSandbox }); }); - app.UseStaticFiles(); } [Authorize] diff --git a/src/Http/Routing/test/testassets/RoutingWebSite/HelloExtension/EndpointRouteBuilderExtensions.cs b/src/Http/Routing/test/testassets/RoutingWebSite/HelloExtension/EndpointRouteBuilderExtensions.cs index 8d146cd4b1..f04c1648a0 100644 --- a/src/Http/Routing/test/testassets/RoutingWebSite/HelloExtension/EndpointRouteBuilderExtensions.cs +++ b/src/Http/Routing/test/testassets/RoutingWebSite/HelloExtension/EndpointRouteBuilderExtensions.cs @@ -13,18 +13,18 @@ namespace Microsoft.AspNetCore.Builder { public static class EndpointRouteBuilderExtensions { - public static IEndpointConventionBuilder MapHello(this IEndpointRouteBuilder routes, string template, string greeter) + public static IEndpointConventionBuilder MapHello(this IEndpointRouteBuilder endpoints, string template, string greeter) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } - var pipeline = routes.CreateApplicationBuilder() + var pipeline = endpoints.CreateApplicationBuilder() .UseHello(greeter) .Build(); - return routes.Map(template, pipeline).WithDisplayName("Hello " + greeter); + return endpoints.Map(template, pipeline).WithDisplayName("Hello " + greeter); } } } diff --git a/src/Http/Routing/test/testassets/RoutingWebSite/MapFallbackStartup.cs b/src/Http/Routing/test/testassets/RoutingWebSite/MapFallbackStartup.cs index 4e9662b55b..747e20b437 100644 --- a/src/Http/Routing/test/testassets/RoutingWebSite/MapFallbackStartup.cs +++ b/src/Http/Routing/test/testassets/RoutingWebSite/MapFallbackStartup.cs @@ -16,22 +16,21 @@ namespace RoutingWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapFallback("/prefix/{*path:nonfile}", (context) => + endpoints.MapFallback("/prefix/{*path:nonfile}", (context) => { return context.Response.WriteAsync("FallbackCustomPattern"); }); - routes.MapFallback((context) => + endpoints.MapFallback((context) => { return context.Response.WriteAsync("FallbackDefaultPattern"); }); - routes.MapHello("/helloworld", "World"); + endpoints.MapHello("/helloworld", "World"); }); - - app.UseEndpoint(); } } } diff --git a/src/Http/Routing/test/testassets/RoutingWebSite/UseEndpointRoutingStartup.cs b/src/Http/Routing/test/testassets/RoutingWebSite/UseEndpointRoutingStartup.cs index 904a49fa1f..1e866ea27e 100644 --- a/src/Http/Routing/test/testassets/RoutingWebSite/UseEndpointRoutingStartup.cs +++ b/src/Http/Routing/test/testassets/RoutingWebSite/UseEndpointRoutingStartup.cs @@ -36,11 +36,20 @@ namespace RoutingWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => - { - routes.MapHello("/helloworld", "World"); + app.UseStaticFiles(); - routes.MapGet( + app.UseRouting(); + + app.Map("/Branch1", branch => SetupBranch(branch, "Branch1")); + app.Map("/Branch2", branch => SetupBranch(branch, "Branch2")); + + // Imagine some more stuff here... + + app.UseEndpoints(endpoints => + { + endpoints.MapHello("/helloworld", "World"); + + endpoints.MapGet( "/", (httpContext) => { @@ -58,7 +67,7 @@ namespace RoutingWebSite response.ContentType = "text/plain"; return response.WriteAsync(sb.ToString()); }); - routes.MapGet( + endpoints.MapGet( "/plaintext", (httpContext) => { @@ -69,7 +78,7 @@ namespace RoutingWebSite response.ContentLength = payloadLength; return response.Body.WriteAsync(_plainTextPayload, 0, payloadLength); }); - routes.MapGet( + endpoints.MapGet( "/convention", (httpContext) => { @@ -79,7 +88,7 @@ namespace RoutingWebSite { b.Metadata.Add(new CustomMetadata()); }); - routes.MapGet( + endpoints.MapGet( "/withconstraints/{id:endsWith(_001)}", (httpContext) => { @@ -88,7 +97,7 @@ namespace RoutingWebSite response.ContentType = "text/plain"; return response.WriteAsync("WithConstraints"); }); - routes.MapGet( + endpoints.MapGet( "/withoptionalconstraints/{id:endsWith(_001)?}", (httpContext) => { @@ -97,7 +106,7 @@ namespace RoutingWebSite response.ContentType = "text/plain"; return response.WriteAsync("withoptionalconstraints"); }); - routes.MapGet( + endpoints.MapGet( "/WithSingleAsteriskCatchAll/{*path}", (httpContext) => { @@ -109,7 +118,7 @@ namespace RoutingWebSite return response.WriteAsync( "Link: " + linkGenerator.GetPathByRouteValues(httpContext, "WithSingleAsteriskCatchAll", new { })); }).WithMetadata(new RouteNameMetadata(routeName: "WithSingleAsteriskCatchAll")); - routes.MapGet( + endpoints.MapGet( "/WithDoubleAsteriskCatchAll/{**path}", (httpContext) => { @@ -122,34 +131,25 @@ namespace RoutingWebSite "Link: " + linkGenerator.GetPathByRouteValues(httpContext, "WithDoubleAsteriskCatchAll", new { })); }).WithMetadata(new RouteNameMetadata(routeName: "WithDoubleAsteriskCatchAll")); - MapHostEndpoint(routes); - MapHostEndpoint(routes, "*.0.0.1"); - MapHostEndpoint(routes, "127.0.0.1"); - MapHostEndpoint(routes, "*.0.0.1:5000", "*.0.0.1:5001"); - MapHostEndpoint(routes, "contoso.com:*", "*.contoso.com:*"); + MapHostEndpoint(endpoints); + MapHostEndpoint(endpoints, "*.0.0.1"); + MapHostEndpoint(endpoints, "127.0.0.1"); + MapHostEndpoint(endpoints, "*.0.0.1:5000", "*.0.0.1:5001"); + MapHostEndpoint(endpoints, "contoso.com:*", "*.contoso.com:*"); }); - - app.Map("/Branch1", branch => SetupBranch(branch, "Branch1")); - app.Map("/Branch2", branch => SetupBranch(branch, "Branch2")); - - app.UseStaticFiles(); - - // Imagine some more stuff here... - - app.UseEndpoint(); } private class CustomMetadata { } - private IEndpointConventionBuilder MapHostEndpoint(IEndpointRouteBuilder routes, params string[] hosts) + private IEndpointConventionBuilder MapHostEndpoint(IEndpointRouteBuilder endpoints, params string[] hosts) { var hostsDisplay = (hosts == null || hosts.Length == 0) ? "*:*" : string.Join(",", hosts.Select(h => h.Contains(':') ? h : h + ":*")); - var conventionBuilder = routes.MapGet( + var conventionBuilder = endpoints.MapGet( "api/DomainWildcard", httpContext => { @@ -170,12 +170,11 @@ namespace RoutingWebSite private void SetupBranch(IApplicationBuilder app, string name) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapGet("api/get/{id}", (context) => context.Response.WriteAsync($"{name} - API Get {context.GetRouteData().Values["id"]}")); + endpoints.MapGet("api/get/{id}", (context) => context.Response.WriteAsync($"{name} - API Get {context.GetRouteData().Values["id"]}")); }); - - app.UseEndpoint(); } } } diff --git a/src/Identity/ApiAuthorization.IdentityServer/samples/ApiAuthSample/Startup.cs b/src/Identity/ApiAuthorization.IdentityServer/samples/ApiAuthSample/Startup.cs index 2e346e9c21..0a365c742e 100644 --- a/src/Identity/ApiAuthorization.IdentityServer/samples/ApiAuthSample/Startup.cs +++ b/src/Identity/ApiAuthorization.IdentityServer/samples/ApiAuthSample/Startup.cs @@ -59,7 +59,15 @@ namespace ApiAuthSample app.UseStaticFiles(); app.UseIdentityServer(); - app.UseMvc(); + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); } } } diff --git a/src/Identity/samples/IdentitySample.DefaultUI/Startup.cs b/src/Identity/samples/IdentitySample.DefaultUI/Startup.cs index 6549d0416a..b47b20a526 100644 --- a/src/Identity/samples/IdentitySample.DefaultUI/Startup.cs +++ b/src/Identity/samples/IdentitySample.DefaultUI/Startup.cs @@ -58,13 +58,15 @@ namespace IdentitySample.DefaultUI app.UseStaticFiles(); - app.UseAuthentication(); + app.UseRouting(); - app.UseMvc(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } } diff --git a/src/Identity/samples/IdentitySample.Mvc/Startup.cs b/src/Identity/samples/IdentitySample.Mvc/Startup.cs index 117e996e66..bd822c7ed8 100644 --- a/src/Identity/samples/IdentitySample.Mvc/Startup.cs +++ b/src/Identity/samples/IdentitySample.Mvc/Startup.cs @@ -70,13 +70,15 @@ namespace IdentitySample app.UseStaticFiles(); - app.UseAuthentication(); + app.UseRouting(); - app.UseMvc(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } } diff --git a/src/Identity/testassets/Identity.DefaultUI.WebSite/NoIdentityStartup.cs b/src/Identity/testassets/Identity.DefaultUI.WebSite/NoIdentityStartup.cs index cfe2e87fce..76872ade91 100644 --- a/src/Identity/testassets/Identity.DefaultUI.WebSite/NoIdentityStartup.cs +++ b/src/Identity/testassets/Identity.DefaultUI.WebSite/NoIdentityStartup.cs @@ -57,9 +57,15 @@ namespace Identity.DefaultUI.WebSite app.UseStaticFiles(); app.UseCookiePolicy(); - app.UseAuthentication(); + app.UseRouting(); - app.UseMvc(); + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + }); } } } diff --git a/src/Identity/testassets/Identity.DefaultUI.WebSite/StartupBase.cs b/src/Identity/testassets/Identity.DefaultUI.WebSite/StartupBase.cs index fde7473faf..69658e0a3c 100644 --- a/src/Identity/testassets/Identity.DefaultUI.WebSite/StartupBase.cs +++ b/src/Identity/testassets/Identity.DefaultUI.WebSite/StartupBase.cs @@ -77,9 +77,23 @@ namespace Identity.DefaultUI.WebSite app.UseStaticFiles(); app.UseCookiePolicy(); + app.UseRouting(); + app.UseAuthentication(); - app.UseMvc(); + // This has to be disabled due to https://github.com/aspnet/AspNetCore/issues/8387 + // + // UseAuthorization does not currently work with Razor pages, and it impacts + // many of the tests here. Uncomment when this is fixed so that we test what is recommended + // for users. + // + //app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + endpoints.MapRazorPages(); + }); } } } diff --git a/src/Middleware/CORS/samples/SampleDestination/Startup.cs b/src/Middleware/CORS/samples/SampleDestination/Startup.cs index 52e19629cb..d2daaaa13c 100644 --- a/src/Middleware/CORS/samples/SampleDestination/Startup.cs +++ b/src/Middleware/CORS/samples/SampleDestination/Startup.cs @@ -57,18 +57,18 @@ namespace SampleDestination public void Configure(IApplicationBuilder app) { - app.UseRouting(routing => - { - routing.Map("/allow-origin", HandleRequest).WithCorsPolicy("AllowOrigin"); - routing.Map("/allow-header-method", HandleRequest).WithCorsPolicy("AllowHeaderMethod"); - routing.Map("/allow-credentials", HandleRequest).WithCorsPolicy("AllowCredentials"); - routing.Map("/exposed-header", HandleRequest).WithCorsPolicy("ExposedHeader"); - routing.Map("/allow-all", HandleRequest).WithCorsPolicy("AllowAll"); - }); + app.UseRouting(); app.UseCors(); - app.UseEndpoint(); + app.UseEndpoints(endpoints => + { + endpoints.Map("/allow-origin", HandleRequest).WithCorsPolicy("AllowOrigin"); + endpoints.Map("/allow-header-method", HandleRequest).WithCorsPolicy("AllowHeaderMethod"); + endpoints.Map("/allow-credentials", HandleRequest).WithCorsPolicy("AllowCredentials"); + endpoints.Map("/exposed-header", HandleRequest).WithCorsPolicy("ExposedHeader"); + endpoints.Map("/allow-all", HandleRequest).WithCorsPolicy("AllowAll"); + }); app.Run(async (context) => { diff --git a/src/Middleware/HealthChecks/ref/Microsoft.AspNetCore.Diagnostics.HealthChecks.netcoreapp3.0.cs b/src/Middleware/HealthChecks/ref/Microsoft.AspNetCore.Diagnostics.HealthChecks.netcoreapp3.0.cs index 7ddfe4645e..8433e54f12 100644 --- a/src/Middleware/HealthChecks/ref/Microsoft.AspNetCore.Diagnostics.HealthChecks.netcoreapp3.0.cs +++ b/src/Middleware/HealthChecks/ref/Microsoft.AspNetCore.Diagnostics.HealthChecks.netcoreapp3.0.cs @@ -14,8 +14,8 @@ namespace Microsoft.AspNetCore.Builder } public static partial class HealthCheckEndpointRouteBuilderExtensions { - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHealthChecks(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHealthChecks(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions options) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHealthChecks(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHealthChecks(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions options) { throw null; } } } namespace Microsoft.AspNetCore.Diagnostics.HealthChecks diff --git a/src/Middleware/HealthChecks/src/Builder/HealthCheckEndpointRouteBuilderExtensions.cs b/src/Middleware/HealthChecks/src/Builder/HealthCheckEndpointRouteBuilderExtensions.cs index 4fd2da5ba7..64c91bc339 100644 --- a/src/Middleware/HealthChecks/src/Builder/HealthCheckEndpointRouteBuilderExtensions.cs +++ b/src/Middleware/HealthChecks/src/Builder/HealthCheckEndpointRouteBuilderExtensions.cs @@ -20,36 +20,36 @@ namespace Microsoft.AspNetCore.Builder /// /// Adds a health checks endpoint to the with the specified template. /// - /// The to add the health checks endpoint to. + /// The to add the health checks endpoint to. /// The URL pattern of the health checks endpoint. /// A convention routes for the health checks endpoint. public static IEndpointConventionBuilder MapHealthChecks( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } - return MapHealthChecksCore(routes, pattern, null); + return MapHealthChecksCore(endpoints, pattern, null); } /// /// Adds a health checks endpoint to the with the specified template and options. /// - /// The to add the health checks endpoint to. + /// The to add the health checks endpoint to. /// The URL pattern of the health checks endpoint. /// A used to configure the health checks. /// A convention routes for the health checks endpoint. public static IEndpointConventionBuilder MapHealthChecks( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, HealthCheckOptions options) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (options == null) @@ -57,12 +57,12 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(options)); } - return MapHealthChecksCore(routes, pattern, options); + return MapHealthChecksCore(endpoints, pattern, options); } - private static IEndpointConventionBuilder MapHealthChecksCore(IEndpointRouteBuilder routes, string pattern, HealthCheckOptions options) + private static IEndpointConventionBuilder MapHealthChecksCore(IEndpointRouteBuilder endpoints, string pattern, HealthCheckOptions options) { - if (routes.ServiceProvider.GetService(typeof(HealthCheckService)) == null) + if (endpoints.ServiceProvider.GetService(typeof(HealthCheckService)) == null) { throw new InvalidOperationException(Resources.FormatUnableToFindServices( nameof(IServiceCollection), @@ -72,11 +72,11 @@ namespace Microsoft.AspNetCore.Builder var args = options != null ? new[] { Options.Create(options) } : Array.Empty(); - var pipeline = routes.CreateApplicationBuilder() + var pipeline = endpoints.CreateApplicationBuilder() .UseMiddleware(args) .Build(); - return routes.Map(pattern, pipeline).WithDisplayName(DefaultDisplayName); + return endpoints.Map(pattern, pipeline).WithDisplayName(DefaultDisplayName); } } } diff --git a/src/Middleware/HealthChecks/test/UnitTests/HealthCheckEndpointRouteBuilderExtensionsTest.cs b/src/Middleware/HealthChecks/test/UnitTests/HealthCheckEndpointRouteBuilderExtensionsTest.cs index 485276d898..00a7da8d64 100644 --- a/src/Middleware/HealthChecks/test/UnitTests/HealthCheckEndpointRouteBuilderExtensionsTest.cs +++ b/src/Middleware/HealthChecks/test/UnitTests/HealthCheckEndpointRouteBuilderExtensionsTest.cs @@ -24,9 +24,10 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks var builder = new WebHostBuilder() .Configure(app => { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapHealthChecks("/healthz"); + endpoints.MapHealthChecks("/healthz"); }); }) .ConfigureServices(services => @@ -50,9 +51,10 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks var builder = new WebHostBuilder() .Configure(app => { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapHealthChecks("/healthz"); + endpoints.MapHealthChecks("/healthz"); }); }) .ConfigureServices(services => @@ -79,9 +81,10 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks var builder = new WebHostBuilder() .Configure(app => { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapHealthChecks("/healthz", new HealthCheckOptions + endpoints.MapHealthChecks("/healthz", new HealthCheckOptions { ResponseWriter = async (context, report) => { diff --git a/src/Middleware/NodeServices/samples/NodeServicesExamples/Startup.cs b/src/Middleware/NodeServices/samples/NodeServicesExamples/Startup.cs index 934d39e512..585d6f30ef 100644 --- a/src/Middleware/NodeServices/samples/NodeServicesExamples/Startup.cs +++ b/src/Middleware/NodeServices/samples/NodeServicesExamples/Startup.cs @@ -42,11 +42,11 @@ namespace NodeServicesExamples }); app.UseStaticFiles(); - app.UseMvc(routes => + app.UseRouting(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Middleware/SpaServices/README.md b/src/Middleware/SpaServices/README.md index 3102b55269..c5a524a656 100644 --- a/src/Middleware/SpaServices/README.md +++ b/src/Middleware/SpaServices/README.md @@ -649,6 +649,9 @@ For the list of available options, please see [Webpack Hot Middleware docs](http ## Routing helper: MapSpaFallbackRoute +*Note: this functionality has been superseded by `endpoints.MapFallbackToFile(...)` provided by endpoint routing. +`MapFallbackToFile` behaves similarly to `MapSpaFallbackRoute`.* + In most single-page applications, you'll want client-side routing as well as your server-side routing. Most of the time, the two routing systems work independently without interfering. However, there is one case where things get challenging: identifying 404s. If a request arrives for `/some/page`, and it doesn't match any server-side route, it's likely that you want to return HTML that starts up your client-side application, which probably understands the route `/some/page`. But if a request arrives for `/images/user-512.png`, and it doesn't match any server-side route or static file, it's **not** likely that your client-side application would handle it - you probably want to return a 404. diff --git a/src/Middleware/SpaServices/samples/Webpack/Startup.cs b/src/Middleware/SpaServices/samples/Webpack/Startup.cs index c6e91d2fe7..3aed2d5db4 100644 --- a/src/Middleware/SpaServices/samples/Webpack/Startup.cs +++ b/src/Middleware/SpaServices/samples/Webpack/Startup.cs @@ -32,11 +32,10 @@ namespace Webpack }); app.UseStaticFiles(); - app.UseMvc(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Middleware/StaticFiles/ref/Microsoft.AspNetCore.StaticFiles.netcoreapp3.0.cs b/src/Middleware/StaticFiles/ref/Microsoft.AspNetCore.StaticFiles.netcoreapp3.0.cs index abeeb6504f..5695c7befe 100644 --- a/src/Middleware/StaticFiles/ref/Microsoft.AspNetCore.StaticFiles.netcoreapp3.0.cs +++ b/src/Middleware/StaticFiles/ref/Microsoft.AspNetCore.StaticFiles.netcoreapp3.0.cs @@ -61,10 +61,10 @@ namespace Microsoft.AspNetCore.Builder } public static partial class StaticFilesEndpointRouteBuilderExtensions { - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string filePath) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string filePath, Microsoft.AspNetCore.Builder.StaticFileOptions options) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, string filePath) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, string filePath, Microsoft.AspNetCore.Builder.StaticFileOptions options) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string filePath) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string filePath, Microsoft.AspNetCore.Builder.StaticFileOptions options) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string filePath) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string filePath, Microsoft.AspNetCore.Builder.StaticFileOptions options) { throw null; } } } namespace Microsoft.AspNetCore.StaticFiles diff --git a/src/Middleware/StaticFiles/src/StaticFilesEndpointRouteBuilderExtensions.cs b/src/Middleware/StaticFiles/src/StaticFilesEndpointRouteBuilderExtensions.cs index d34e54e959..4a102ae4bc 100644 --- a/src/Middleware/StaticFiles/src/StaticFilesEndpointRouteBuilderExtensions.cs +++ b/src/Middleware/StaticFiles/src/StaticFilesEndpointRouteBuilderExtensions.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-filenames with the lowest possible priority. The request will be routed to a /// that attempts to serve the file specified by . /// - /// The . + /// The . /// The file path of the file to serve. /// The /// @@ -38,12 +38,12 @@ namespace Microsoft.AspNetCore.Builder /// /// public static IEndpointConventionBuilder MapFallbackToFile( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string filePath) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (filePath == null) @@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(filePath)); } - return routes.MapFallback(CreateRequestDelegate(routes, filePath)); + return endpoints.MapFallback(CreateRequestDelegate(endpoints, filePath)); } /// @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-filenames with the lowest possible priority. The request will be routed to a /// that attempts to serve the file specified by . /// - /// The . + /// The . /// The file path of the file to serve. /// for the . /// The @@ -76,13 +76,13 @@ namespace Microsoft.AspNetCore.Builder /// /// public static IEndpointConventionBuilder MapFallbackToFile( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string filePath, StaticFileOptions options) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (filePath == null) @@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(filePath)); } - return routes.MapFallback(CreateRequestDelegate(routes, filePath, options)); + return endpoints.MapFallback(CreateRequestDelegate(endpoints, filePath, options)); } /// @@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-filenames with the lowest possible priority. The request will be routed to a /// that attempts to serve the file specified by . /// - /// The . + /// The . /// The route pattern. /// The file path of the file to serve. /// The @@ -121,13 +121,13 @@ namespace Microsoft.AspNetCore.Builder /// /// public static IEndpointConventionBuilder MapFallbackToFile( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, string filePath) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (pattern == null) @@ -140,7 +140,7 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(filePath)); } - return routes.MapFallback(pattern, CreateRequestDelegate(routes, filePath)); + return endpoints.MapFallback(pattern, CreateRequestDelegate(endpoints, filePath)); } /// @@ -148,7 +148,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-filenames with the lowest possible priority. The request will be routed to a /// that attempts to serve the file specified by . /// - /// The .\ + /// The .\ /// The route pattern. /// The file path of the file to serve. /// for the . @@ -169,14 +169,14 @@ namespace Microsoft.AspNetCore.Builder /// /// public static IEndpointConventionBuilder MapFallbackToFile( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, string filePath, StaticFileOptions options) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (pattern == null) @@ -189,15 +189,15 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(filePath)); } - return routes.MapFallback(pattern, CreateRequestDelegate(routes, filePath, options)); + return endpoints.MapFallback(pattern, CreateRequestDelegate(endpoints, filePath, options)); } private static RequestDelegate CreateRequestDelegate( - IEndpointRouteBuilder routes, + IEndpointRouteBuilder endpoints, string filePath, StaticFileOptions options = null) { - var app = routes.CreateApplicationBuilder(); + var app = endpoints.CreateApplicationBuilder(); app.Use(next => context => { context.Request.Path = "/" + filePath; diff --git a/src/Middleware/StaticFiles/test/FunctionalTests/FallbackStaticFileTest.cs b/src/Middleware/StaticFiles/test/FunctionalTests/FallbackStaticFileTest.cs index 00dc48ae08..2d12ee7a30 100644 --- a/src/Middleware/StaticFiles/test/FunctionalTests/FallbackStaticFileTest.cs +++ b/src/Middleware/StaticFiles/test/FunctionalTests/FallbackStaticFileTest.cs @@ -35,15 +35,15 @@ namespace Microsoft.AspNetCore.StaticFiles .Configure(app => { var environment = app.ApplicationServices.GetRequiredService(); - - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.Map("/hello", context => + endpoints.Map("/hello", context => { return context.Response.WriteAsync("Hello, world!"); }); - routes.MapFallbackToFile("default.html", new StaticFileOptions() + endpoints.MapFallbackToFile("default.html", new StaticFileOptions() { FileProvider = new PhysicalFileProvider(Path.Combine(environment.WebRootPath, "SubFolder")), }); @@ -83,14 +83,15 @@ namespace Microsoft.AspNetCore.StaticFiles .UseWebRoot(AppContext.BaseDirectory) .Configure(app => { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.Map("/hello", context => + endpoints.Map("/hello", context => { return context.Response.WriteAsync("Hello, world!"); }); - routes.MapFallbackToFile("/prefix/{*path:nonfile}", "TestDocument.txt"); + endpoints.MapFallbackToFile("/prefix/{*path:nonfile}", "TestDocument.txt"); }); }); diff --git a/src/Middleware/StaticFiles/test/FunctionalTests/StaticFileMiddlewareTests.cs b/src/Middleware/StaticFiles/test/FunctionalTests/StaticFileMiddlewareTests.cs index 7413eaf89d..ba4d7e5538 100644 --- a/src/Middleware/StaticFiles/test/FunctionalTests/StaticFileMiddlewareTests.cs +++ b/src/Middleware/StaticFiles/test/FunctionalTests/StaticFileMiddlewareTests.cs @@ -50,12 +50,14 @@ namespace Microsoft.AspNetCore.StaticFiles public async Task Endpoint_PassesThrough() { var builder = new WebHostBuilder() - .ConfigureServices(services => services.AddSingleton(LoggerFactory)) + .ConfigureServices(services => { services.AddSingleton(LoggerFactory); services.AddRouting(); }) .UseKestrel() .UseWebRoot(AppContext.BaseDirectory) .Configure(app => { // Routing first => static files noops + app.UseRouting(); + app.Use(next => context => { // Assign an endpoint, this will make the default files noop. @@ -70,6 +72,8 @@ namespace Microsoft.AspNetCore.StaticFiles }); app.UseStaticFiles(); + + app.UseEndpoints(endpoints => {}); }); using (var server = builder.Start(TestUrlHelper.GetTestUrl(ServerType.Kestrel))) diff --git a/src/Middleware/StaticFiles/test/UnitTests/DefaultFilesMiddlewareTests.cs b/src/Middleware/StaticFiles/test/UnitTests/DefaultFilesMiddlewareTests.cs index aff8e01a9c..5c4c43f704 100644 --- a/src/Middleware/StaticFiles/test/UnitTests/DefaultFilesMiddlewareTests.cs +++ b/src/Middleware/StaticFiles/test/UnitTests/DefaultFilesMiddlewareTests.cs @@ -82,6 +82,8 @@ namespace Microsoft.AspNetCore.StaticFiles var server = StaticFilesTestServer.Create( app => { + app.UseRouting(); + app.Use(next => context => { // Assign an endpoint, this will make the default files noop. @@ -100,8 +102,10 @@ namespace Microsoft.AspNetCore.StaticFiles RequestPath = new PathString(""), FileProvider = fileProvider }); + + app.UseEndpoints(endpoints => {}); }, - services => services.AddDirectoryBrowser()); + services => { services.AddDirectoryBrowser(); services.AddRouting(); }); var response = await server.CreateRequest("/SubFolder/").GetAsync(); Assert.Equal(HttpStatusCode.OK, response.StatusCode); diff --git a/src/Middleware/StaticFiles/test/UnitTests/DirectoryBrowserMiddlewareTests.cs b/src/Middleware/StaticFiles/test/UnitTests/DirectoryBrowserMiddlewareTests.cs index 8710f46c28..010daa14da 100644 --- a/src/Middleware/StaticFiles/test/UnitTests/DirectoryBrowserMiddlewareTests.cs +++ b/src/Middleware/StaticFiles/test/UnitTests/DirectoryBrowserMiddlewareTests.cs @@ -96,6 +96,8 @@ namespace Microsoft.AspNetCore.StaticFiles var server = StaticFilesTestServer.Create( app => { + app.UseRouting(); + app.Use(next => context => { // Assign an endpoint, this will make the directory browser noop @@ -115,8 +117,10 @@ namespace Microsoft.AspNetCore.StaticFiles RequestPath = new PathString(""), FileProvider = fileProvider }); + + app.UseEndpoints(endpoints => {}); }, - services => services.AddDirectoryBrowser()); + services => { services.AddDirectoryBrowser(); services.AddRouting(); }); var response = await server.CreateRequest("/").GetAsync(); Assert.Equal(HttpStatusCode.NotAcceptable, response.StatusCode); diff --git a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/StartupOpenIdConnectTesting.cs b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/StartupOpenIdConnectTesting.cs index 4ddecfa7df..bb066895a9 100644 --- a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/StartupOpenIdConnectTesting.cs +++ b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/StartupOpenIdConnectTesting.cs @@ -141,25 +141,31 @@ namespace MusicStore // Add static files to the request pipeline app.UseStaticFiles(); - // Add authentication to the request pipeline + // Add the endpoint routing matcher middleware to the request pipeline + app.UseRouting(); + + // Add cookie-based authentication to the request pipeline app.UseAuthentication(); - // Add MVC to the request pipeline - app.UseMvc(routes => + // Add the authorization middleware to the request pipeline + app.UseAuthorization(); + + // Add endpoints to the request pipeline + app.UseEndpoints(endpoints => { - routes.MapRoute( + endpoints.MapControllerRoute( name: "areaRoute", - template: "{area:exists}/{controller}/{action}", + pattern: "{area:exists}/{controller}/{action}", defaults: new { action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "default", - template: "{controller}/{action}/{id?}", + pattern: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "api", - template: "{controller}/{id?}"); + pattern: "{controller}/{id?}"); }); //Populates the MusicStore sample data diff --git a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/StartupSocialTesting.cs b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/StartupSocialTesting.cs index 16744a703e..ba7baefdd2 100644 --- a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/StartupSocialTesting.cs +++ b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/StartupSocialTesting.cs @@ -181,25 +181,31 @@ namespace MusicStore // Add static files to the request pipeline app.UseStaticFiles(); + // Add the endpoint routing matcher middleware to the request pipeline + app.UseRouting(); + // Add cookie-based authentication to the request pipeline app.UseAuthentication(); - // Add MVC to the request pipeline - app.UseMvc(routes => + // Add the authorization middleware to the request pipeline + app.UseAuthorization(); + + // Add endpoints to the request pipeline + app.UseEndpoints(endpoints => { - routes.MapRoute( + endpoints.MapControllerRoute( name: "areaRoute", - template: "{area:exists}/{controller}/{action}", + pattern: "{area:exists}/{controller}/{action}", defaults: new { action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "default", - template: "{controller}/{action}/{id?}", + pattern: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "api", - template: "{controller}/{id?}"); + pattern: "{controller}/{id?}"); }); //Populates the MusicStore sample data diff --git a/src/MusicStore/samples/MusicStore/Startup.cs b/src/MusicStore/samples/MusicStore/Startup.cs index 1e33ec67e6..faf4a05bae 100644 --- a/src/MusicStore/samples/MusicStore/Startup.cs +++ b/src/MusicStore/samples/MusicStore/Startup.cs @@ -195,25 +195,31 @@ namespace MusicStore // Add static files to the request pipeline app.UseStaticFiles(); + // Add the endpoint routing matcher middleware to the request pipeline + app.UseRouting(); + // Add cookie-based authentication to the request pipeline app.UseAuthentication(); - // Add MVC to the request pipeline - app.UseMvc(routes => + // Add the authorization middleware to the request pipeline + app.UseAuthorization(); + + // Add endpoints to the request pipeline + app.UseEndpoints(endpoints => { - routes.MapRoute( + endpoints.MapControllerRoute( name: "areaRoute", - template: "{area:exists}/{controller}/{action}", + pattern: "{area:exists}/{controller}/{action}", defaults: new { action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "default", - template: "{controller}/{action}/{id?}", + pattern: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "api", - template: "{controller}/{id?}"); + pattern: "{controller}/{id?}"); }); //Populates the MusicStore sample data diff --git a/src/MusicStore/samples/MusicStore/StartupNtlmAuthentication.cs b/src/MusicStore/samples/MusicStore/StartupNtlmAuthentication.cs index 36e6947e0b..5eadf1f8a0 100644 --- a/src/MusicStore/samples/MusicStore/StartupNtlmAuthentication.cs +++ b/src/MusicStore/samples/MusicStore/StartupNtlmAuthentication.cs @@ -142,22 +142,31 @@ namespace MusicStore // Add static files to the request pipeline app.UseStaticFiles(); - // Add MVC to the request pipeline - app.UseMvc(routes => + // Add the endpoint routing matcher middleware to the request pipeline + app.UseRouting(); + + // Add cookie-based authentication to the request pipeline + app.UseAuthentication(); + + // Add the authorization middleware to the request pipeline + app.UseAuthorization(); + + // Add endpoints to the request pipeline + app.UseEndpoints(endpoints => { - routes.MapRoute( + endpoints.MapControllerRoute( name: "areaRoute", - template: "{area:exists}/{controller}/{action}", + pattern: "{area:exists}/{controller}/{action}", defaults: new { action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "default", - template: "{controller}/{action}/{id?}", + pattern: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "api", - template: "{controller}/{id?}"); + pattern: "{controller}/{id?}"); }); //Populates the MusicStore sample data diff --git a/src/MusicStore/samples/MusicStore/StartupOpenIdConnect.cs b/src/MusicStore/samples/MusicStore/StartupOpenIdConnect.cs index e1ab91928d..397ca1f011 100644 --- a/src/MusicStore/samples/MusicStore/StartupOpenIdConnect.cs +++ b/src/MusicStore/samples/MusicStore/StartupOpenIdConnect.cs @@ -140,22 +140,31 @@ namespace MusicStore // Add static files to the request pipeline app.UseStaticFiles(); - // Add MVC to the request pipeline - app.UseMvc(routes => + // Add the endpoint routing matcher middleware to the request pipeline + app.UseRouting(); + + // Add cookie-based authentication to the request pipeline + app.UseAuthentication(); + + // Add the authorization middleware to the request pipeline + app.UseAuthorization(); + + // Add endpoints to the request pipeline + app.UseEndpoints(endpoints => { - routes.MapRoute( + endpoints.MapControllerRoute( name: "areaRoute", - template: "{area:exists}/{controller}/{action}", + pattern: "{area:exists}/{controller}/{action}", defaults: new { action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "default", - template: "{controller}/{action}/{id?}", + pattern: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); - routes.MapRoute( + endpoints.MapControllerRoute( name: "api", - template: "{controller}/{id?}"); + pattern: "{controller}/{id?}"); }); //Populates the MusicStore sample data diff --git a/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs b/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs index ccfbff6d84..50a39b3b73 100644 --- a/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs +++ b/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs @@ -5,14 +5,14 @@ namespace Microsoft.AspNetCore.Builder { public static partial class ControllerEndpointRouteBuilderExtensions { - public static void MapAreaControllerRoute(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string name, string areaName, string pattern, object defaults = null, object constraints = null, object dataTokens = null) { } - public static void MapControllerRoute(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string name, string pattern, object defaults = null, object constraints = null, object dataTokens = null) { } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapControllers(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapDefaultControllerRoute(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes) { throw null; } - public static void MapFallbackToAreaController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string action, string controller, string area) { } - public static void MapFallbackToAreaController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, string action, string controller, string area) { } - public static void MapFallbackToController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string action, string controller) { } - public static void MapFallbackToController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, string action, string controller) { } + public static void MapAreaControllerRoute(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string name, string areaName, string pattern, object defaults = null, object constraints = null, object dataTokens = null) { } + public static void MapControllerRoute(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string name, string pattern, object defaults = null, object constraints = null, object dataTokens = null) { } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapControllers(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapDefaultControllerRoute(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) { throw null; } + public static void MapFallbackToAreaController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string action, string controller, string area) { } + public static void MapFallbackToAreaController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string action, string controller, string area) { } + public static void MapFallbackToController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string action, string controller) { } + public static void MapFallbackToController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string action, string controller) { } } public static partial class MvcApplicationBuilderExtensions { diff --git a/src/Mvc/Mvc.Core/src/Builder/ControllerEndpointRouteBuilderExtensions.cs b/src/Mvc/Mvc.Core/src/Builder/ControllerEndpointRouteBuilderExtensions.cs index ccc66f9ec4..03d25e70c2 100644 --- a/src/Mvc/Mvc.Core/src/Builder/ControllerEndpointRouteBuilderExtensions.cs +++ b/src/Mvc/Mvc.Core/src/Builder/ControllerEndpointRouteBuilderExtensions.cs @@ -20,36 +20,36 @@ namespace Microsoft.AspNetCore.Builder /// /// Adds endpoints for controller actions to the without specifying any routes. /// - /// The . + /// The . /// An for endpoints associated with controller actions. - public static IEndpointConventionBuilder MapControllers(this IEndpointRouteBuilder routes) + public static IEndpointConventionBuilder MapControllers(this IEndpointRouteBuilder endpoints) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } - EnsureControllerServices(routes); + EnsureControllerServices(endpoints); - return GetOrCreateDataSource(routes); + return GetOrCreateDataSource(endpoints); } /// /// Adds endpoints for controller actions to the and adds the default route /// {controller=Home}/{action=Index}/{id?}. /// - /// The . + /// The . /// An for endpoints associated with controller actions. - public static IEndpointConventionBuilder MapDefaultControllerRoute(this IEndpointRouteBuilder routes) + public static IEndpointConventionBuilder MapDefaultControllerRoute(this IEndpointRouteBuilder endpoints) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } - EnsureControllerServices(routes); + EnsureControllerServices(endpoints); - var dataSource = GetOrCreateDataSource(routes); + var dataSource = GetOrCreateDataSource(endpoints); dataSource.AddRoute(new ConventionalRouteEntry( "default", "{controller=Home}/{action=Index}/{id?}", @@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Builder /// with the given , , /// , , and . /// - /// The to add the route to. + /// The to add the route to. /// The name of the route. /// The URL pattern of the route. /// @@ -81,21 +81,21 @@ namespace Microsoft.AspNetCore.Builder /// values of the data tokens. /// public static void MapControllerRoute( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string name, string pattern, object defaults = null, object constraints = null, object dataTokens = null) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } - EnsureControllerServices(routes); + EnsureControllerServices(endpoints); - var dataSource = GetOrCreateDataSource(routes); + var dataSource = GetOrCreateDataSource(endpoints); dataSource.AddRoute(new ConventionalRouteEntry( name, pattern, @@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Builder /// with the given , , , /// , , and . /// - /// The to add the route to. + /// The to add the route to. /// The name of the route. /// The area name. /// The URL pattern of the route. @@ -126,7 +126,7 @@ namespace Microsoft.AspNetCore.Builder /// values of the data tokens. /// public static void MapAreaControllerRoute( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string name, string areaName, string pattern, @@ -134,9 +134,9 @@ namespace Microsoft.AspNetCore.Builder object constraints = null, object dataTokens = null) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (string.IsNullOrEmpty(areaName)) @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Builder var constraintsDictionary = new RouteValueDictionary(constraints); constraintsDictionary["area"] = constraintsDictionary["area"] ?? new StringRouteConstraint(areaName); - routes.MapControllerRoute(name, pattern, defaultsDictionary, constraintsDictionary, dataTokens); + endpoints.MapControllerRoute(name, pattern, defaultsDictionary, constraintsDictionary, dataTokens); } /// @@ -158,7 +158,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-file-names with the lowest possible priority. The request will be routed to a controller endpoint that /// matches , and . /// - /// The to add the route to. + /// The to add the route to. /// The action name. /// The controller name. /// @@ -184,13 +184,13 @@ namespace Microsoft.AspNetCore.Builder /// /// public static void MapFallbackToController( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string action, string controller) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (action == null) @@ -203,14 +203,14 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(controller)); } - EnsureControllerServices(routes); + EnsureControllerServices(endpoints); // Called for side-effect to make sure that the data source is registered. - GetOrCreateDataSource(routes); + GetOrCreateDataSource(endpoints); // Maps a fallback endpoint with an empty delegate. This is OK because // we don't expect the delegate to run. - routes.MapFallback(context => Task.CompletedTask).Add(b => + endpoints.MapFallback(context => Task.CompletedTask).Add(b => { // MVC registers a policy that looks for this metadata. b.Metadata.Add(CreateDynamicControllerMetadata(action, controller, area: null)); @@ -222,7 +222,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-file-names with the lowest possible priority. The request will be routed to a controller endpoint that /// matches , and . /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The action name. /// The controller name. @@ -252,14 +252,14 @@ namespace Microsoft.AspNetCore.Builder /// /// public static void MapFallbackToController( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, string action, string controller) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (pattern == null) @@ -277,14 +277,14 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(controller)); } - EnsureControllerServices(routes); + EnsureControllerServices(endpoints); // Called for side-effect to make sure that the data source is registered. - GetOrCreateDataSource(routes); + GetOrCreateDataSource(endpoints); // Maps a fallback endpoint with an empty delegate. This is OK because // we don't expect the delegate to run. - routes.MapFallback(pattern, context => Task.CompletedTask).Add(b => + endpoints.MapFallback(pattern, context => Task.CompletedTask).Add(b => { // MVC registers a policy that looks for this metadata. b.Metadata.Add(CreateDynamicControllerMetadata(action, controller, area: null)); @@ -296,7 +296,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-file-names with the lowest possible priority. The request will be routed to a controller endpoint that /// matches , , and . /// - /// The to add the route to. + /// The to add the route to. /// The action name. /// The controller name. /// The area name. @@ -323,14 +323,14 @@ namespace Microsoft.AspNetCore.Builder /// /// public static void MapFallbackToAreaController( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string action, string controller, string area) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (action == null) @@ -343,14 +343,14 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(controller)); } - EnsureControllerServices(routes); + EnsureControllerServices(endpoints); // Called for side-effect to make sure that the data source is registered. - GetOrCreateDataSource(routes); + GetOrCreateDataSource(endpoints); // Maps a fallback endpoint with an empty delegate. This is OK because // we don't expect the delegate to run. - routes.MapFallback(context => Task.CompletedTask).Add(b => + endpoints.MapFallback(context => Task.CompletedTask).Add(b => { // MVC registers a policy that looks for this metadata. b.Metadata.Add(CreateDynamicControllerMetadata(action, controller, area)); @@ -362,7 +362,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-file-names with the lowest possible priority. The request will be routed to a controller endpoint that /// matches , , and . /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The action name. /// The controller name. @@ -393,15 +393,15 @@ namespace Microsoft.AspNetCore.Builder /// /// public static void MapFallbackToAreaController( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, string action, string controller, string area) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (pattern == null) @@ -419,14 +419,14 @@ namespace Microsoft.AspNetCore.Builder throw new ArgumentNullException(nameof(controller)); } - EnsureControllerServices(routes); + EnsureControllerServices(endpoints); // Called for side-effect to make sure that the data source is registered. - GetOrCreateDataSource(routes); + GetOrCreateDataSource(endpoints); // Maps a fallback endpoint with an empty delegate. This is OK because // we don't expect the delegate to run. - routes.MapFallback(pattern, context => Task.CompletedTask).Add(b => + endpoints.MapFallback(pattern, context => Task.CompletedTask).Add(b => { // MVC registers a policy that looks for this metadata. b.Metadata.Add(CreateDynamicControllerMetadata(action, controller, area)); @@ -443,9 +443,9 @@ namespace Microsoft.AspNetCore.Builder }); } - private static void EnsureControllerServices(IEndpointRouteBuilder routes) + private static void EnsureControllerServices(IEndpointRouteBuilder endpoints) { - var marker = routes.ServiceProvider.GetService(); + var marker = endpoints.ServiceProvider.GetService(); if (marker == null) { throw new InvalidOperationException(Resources.FormatUnableToFindServices( @@ -455,13 +455,13 @@ namespace Microsoft.AspNetCore.Builder } } - private static ControllerActionEndpointDataSource GetOrCreateDataSource(IEndpointRouteBuilder routes) + private static ControllerActionEndpointDataSource GetOrCreateDataSource(IEndpointRouteBuilder endpoints) { - var dataSource = routes.DataSources.OfType().FirstOrDefault(); + var dataSource = endpoints.DataSources.OfType().FirstOrDefault(); if (dataSource == null) { - dataSource = routes.ServiceProvider.GetRequiredService(); - routes.DataSources.Add(dataSource); + dataSource = endpoints.ServiceProvider.GetRequiredService(); + endpoints.DataSources.Add(dataSource); } return dataSource; diff --git a/src/Mvc/Mvc.Core/src/Builder/MvcApplicationBuilderExtensions.cs b/src/Mvc/Mvc.Core/src/Builder/MvcApplicationBuilderExtensions.cs index bb1903fefc..a6fab64c94 100644 --- a/src/Mvc/Mvc.Core/src/Builder/MvcApplicationBuilderExtensions.cs +++ b/src/Mvc/Mvc.Core/src/Builder/MvcApplicationBuilderExtensions.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Routing; @@ -18,9 +17,6 @@ namespace Microsoft.AspNetCore.Builder /// public static class MvcApplicationBuilderExtensions { - // Property key set in routing package by UseEndpointRouting to indicate middleware is registered - private const string EndpointRoutingRegisteredKey = "__EndpointRoutingMiddlewareRegistered"; - /// /// Adds MVC to the request execution pipeline. /// @@ -88,58 +84,23 @@ namespace Microsoft.AspNetCore.Builder if (options.Value.EnableEndpointRouting) { - var dataSource = app.ApplicationServices.GetRequiredService(); - - var endpointRouteBuilder = new EndpointRouteBuilder(app); - - configureRoutes(endpointRouteBuilder); - - foreach (var router in endpointRouteBuilder.Routes) - { - // Only accept Microsoft.AspNetCore.Routing.Route when converting to endpoint - // Sub-types could have additional customization that we can't knowingly convert - if (router is Route route && router.GetType() == typeof(Route)) - { - var entry = new ConventionalRouteEntry( - route.Name, - route.RouteTemplate, - route.Defaults, - route.Constraints.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value), - route.DataTokens); - - dataSource.AddRoute(entry); - } - else - { - throw new InvalidOperationException($"Cannot use '{router.GetType().FullName}' with Endpoint Routing."); - } - } - - if (!app.Properties.TryGetValue(EndpointRoutingRegisteredKey, out _)) - { - // Matching middleware has not been registered yet - // For back-compat register middleware so an endpoint is matched and then immediately used - app.UseRouting(routerBuilder => - { - routerBuilder.DataSources.Add(dataSource); - }); - } - - return app.UseEndpoint(); + var message = + "Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use " + + "'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside " + + "'ConfigureServices(...)."; + throw new InvalidOperationException(message); } - else + + var routes = new RouteBuilder(app) { - var routes = new RouteBuilder(app) - { - DefaultHandler = app.ApplicationServices.GetRequiredService(), - }; + DefaultHandler = app.ApplicationServices.GetRequiredService(), + }; - configureRoutes(routes); + configureRoutes(routes); - routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices)); + routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices)); - return app.UseRouter(routes.Build()); - } + return app.UseRouter(routes.Build()); } private class EndpointRouteBuilder : IRouteBuilder diff --git a/src/Mvc/Mvc.Core/src/Routing/ActionEndpointDataSource.cs b/src/Mvc/Mvc.Core/src/Routing/ActionEndpointDataSource.cs index 8132177195..b5c0eb10e5 100644 --- a/src/Mvc/Mvc.Core/src/Routing/ActionEndpointDataSource.cs +++ b/src/Mvc/Mvc.Core/src/Routing/ActionEndpointDataSource.cs @@ -10,9 +10,6 @@ using Microsoft.AspNetCore.Mvc.Infrastructure; namespace Microsoft.AspNetCore.Mvc.Routing { - // This is only used to support the scenario where UseMvc is called with - // EnableEndpointRouting = true. For layering reasons we can't use the PageActionEndpointDataSource - // here. internal class ActionEndpointDataSource : ActionEndpointDataSourceBase { private readonly ActionEndpointFactory _endpointFactory; @@ -22,10 +19,10 @@ namespace Microsoft.AspNetCore.Mvc.Routing : base(actions) { _endpointFactory = endpointFactory; - + _routes = new List(); - // IMPORTANT: this needs to be the last thing we do in the constructor. + // IMPORTANT: this needs to be the last thing we do in the constructor. // Change notifications can happen immediately! Subscribe(); } diff --git a/src/Mvc/Mvc.Core/test/Builder/MvcApplicationBuilderExtensionsTest.cs b/src/Mvc/Mvc.Core/test/Builder/MvcApplicationBuilderExtensionsTest.cs index 7bfbfda4b3..11dee90d69 100644 --- a/src/Mvc/Mvc.Core/test/Builder/MvcApplicationBuilderExtensionsTest.cs +++ b/src/Mvc/Mvc.Core/test/Builder/MvcApplicationBuilderExtensionsTest.cs @@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Builder } [Fact] - public void UseMvc_EndpointRoutingEnabled_AddsRoute() + public void UseMvc_EndpointRoutingEnabled_ThrowsException() { // Arrange var services = new ServiceCollection(); @@ -73,21 +73,21 @@ namespace Microsoft.AspNetCore.Mvc.Core.Builder var appBuilder = new ApplicationBuilder(serviceProvider); // Act - appBuilder.UseMvc(routes => + var ex = Assert.Throws(() => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + appBuilder.UseMvc(routes => + { + routes.MapRoute( + name: "default", + template: "{controller=Home}/{action=Index}/{id?}"); + }); }); - var routeOptions = appBuilder.ApplicationServices - .GetRequiredService>(); - - var dataSource = (ActionEndpointDataSource)Assert.Single(routeOptions.Value.EndpointDataSources, ds => ds is ActionEndpointDataSource); - - var endpointInfo = Assert.Single(dataSource.Routes); - Assert.Equal("default", endpointInfo.RouteName); - Assert.Equal("{controller=Home}/{action=Index}/{id?}", endpointInfo.Pattern.RawText); + var expected = + "Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use " + + "'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside " + + "'ConfigureServices(...)."; + Assert.Equal(expected, ex.Message); } } } diff --git a/src/Mvc/Mvc.RazorPages/ref/Microsoft.AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs b/src/Mvc/Mvc.RazorPages/ref/Microsoft.AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs index d6f71c30c6..37ae8ad5c6 100644 --- a/src/Mvc/Mvc.RazorPages/ref/Microsoft.AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs +++ b/src/Mvc/Mvc.RazorPages/ref/Microsoft.AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs @@ -5,11 +5,11 @@ namespace Microsoft.AspNetCore.Builder { public static partial class RazorPagesEndpointRouteBuilderExtensions { - public static void MapFallbackToAreaPage(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string page, string area) { } - public static void MapFallbackToAreaPage(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, string page, string area) { } - public static void MapFallbackToPage(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string page) { } - public static void MapFallbackToPage(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, string page) { } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapRazorPages(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes) { throw null; } + public static void MapFallbackToAreaPage(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string page, string area) { } + public static void MapFallbackToAreaPage(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string page, string area) { } + public static void MapFallbackToPage(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string page) { } + public static void MapFallbackToPage(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string page) { } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapRazorPages(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) { throw null; } } } namespace Microsoft.AspNetCore.Mvc.ApplicationModels diff --git a/src/Mvc/Mvc.RazorPages/src/Builder/RazorPagesEndpointRouteBuilderExtensions.cs b/src/Mvc/Mvc.RazorPages/src/Builder/RazorPagesEndpointRouteBuilderExtensions.cs index 310c22f9ad..90a9dd0657 100644 --- a/src/Mvc/Mvc.RazorPages/src/Builder/RazorPagesEndpointRouteBuilderExtensions.cs +++ b/src/Mvc/Mvc.RazorPages/src/Builder/RazorPagesEndpointRouteBuilderExtensions.cs @@ -19,18 +19,18 @@ namespace Microsoft.AspNetCore.Builder /// /// Adds endpoints for Razor Pages to the . /// - /// The . + /// The . /// An for endpoints associated with Razor Pages. - public static IEndpointConventionBuilder MapRazorPages(this IEndpointRouteBuilder routes) + public static IEndpointConventionBuilder MapRazorPages(this IEndpointRouteBuilder endpoints) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } - EnsureRazorPagesServices(routes); + EnsureRazorPagesServices(endpoints); - return GetOrCreateDataSource(routes); + return GetOrCreateDataSource(endpoints); } /// @@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-file-names with the lowest possible priority. The request will be routed to a page endpoint that /// matches . /// - /// The to add the route to. + /// The to add the route to. /// The page name. /// /// @@ -57,11 +57,11 @@ namespace Microsoft.AspNetCore.Builder /// will be available. /// /// - public static void MapFallbackToPage(this IEndpointRouteBuilder routes, string page) + public static void MapFallbackToPage(this IEndpointRouteBuilder endpoints, string page) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (page == null) @@ -71,14 +71,14 @@ namespace Microsoft.AspNetCore.Builder PageConventionCollection.EnsureValidPageName(page, nameof(page)); - EnsureRazorPagesServices(routes); + EnsureRazorPagesServices(endpoints); // Called for side-effect to make sure that the data source is registered. - GetOrCreateDataSource(routes); + GetOrCreateDataSource(endpoints); // Maps a fallback endpoint with an empty delegate. This is OK because // we don't expect the delegate to run. - routes.MapFallback(context => Task.CompletedTask).Add(b => + endpoints.MapFallback(context => Task.CompletedTask).Add(b => { // MVC registers a policy that looks for this metadata. b.Metadata.Add(CreateDynamicPageMetadata(page, area: null)); @@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-file-names with the lowest possible priority. The request will be routed to a page endpoint that /// matches . /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The action name. /// @@ -114,13 +114,13 @@ namespace Microsoft.AspNetCore.Builder /// /// public static void MapFallbackToPage( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, string page) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (pattern == null) @@ -135,14 +135,14 @@ namespace Microsoft.AspNetCore.Builder PageConventionCollection.EnsureValidPageName(page, nameof(page)); - EnsureRazorPagesServices(routes); + EnsureRazorPagesServices(endpoints); // Called for side-effect to make sure that the data source is registered. - GetOrCreateDataSource(routes); + GetOrCreateDataSource(endpoints); // Maps a fallback endpoint with an empty delegate. This is OK because // we don't expect the delegate to run. - routes.MapFallback(pattern, context => Task.CompletedTask).Add(b => + endpoints.MapFallback(pattern, context => Task.CompletedTask).Add(b => { // MVC registers a policy that looks for this metadata. b.Metadata.Add(CreateDynamicPageMetadata(page, area: null)); @@ -154,7 +154,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-file-names with the lowest possible priority. The request will be routed to a page endpoint that /// matches , and . /// - /// The to add the route to. + /// The to add the route to. /// The action name. /// The area name. /// @@ -175,13 +175,13 @@ namespace Microsoft.AspNetCore.Builder /// /// public static void MapFallbackToAreaPage( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string page, string area) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (page == null) @@ -191,14 +191,14 @@ namespace Microsoft.AspNetCore.Builder PageConventionCollection.EnsureValidPageName(page, nameof(page)); - EnsureRazorPagesServices(routes); + EnsureRazorPagesServices(endpoints); // Called for side-effect to make sure that the data source is registered. - GetOrCreateDataSource(routes); + GetOrCreateDataSource(endpoints); // Maps a fallback endpoint with an empty delegate. This is OK because // we don't expect the delegate to run. - routes.MapFallback(context => Task.CompletedTask).Add(b => + endpoints.MapFallback(context => Task.CompletedTask).Add(b => { // MVC registers a policy that looks for this metadata. b.Metadata.Add(CreateDynamicPageMetadata(page, area)); @@ -210,7 +210,7 @@ namespace Microsoft.AspNetCore.Builder /// requests for non-file-names with the lowest possible priority. The request will be routed to a page endpoint that /// matches , and . /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// The action name. /// The area name. @@ -235,14 +235,14 @@ namespace Microsoft.AspNetCore.Builder /// /// public static void MapFallbackToAreaPage( - this IEndpointRouteBuilder routes, + this IEndpointRouteBuilder endpoints, string pattern, string page, string area) { - if (routes == null) + if (endpoints == null) { - throw new ArgumentNullException(nameof(routes)); + throw new ArgumentNullException(nameof(endpoints)); } if (pattern == null) @@ -257,14 +257,14 @@ namespace Microsoft.AspNetCore.Builder PageConventionCollection.EnsureValidPageName(page, nameof(page)); - EnsureRazorPagesServices(routes); + EnsureRazorPagesServices(endpoints); // Called for side-effect to make sure that the data source is registered. - GetOrCreateDataSource(routes); + GetOrCreateDataSource(endpoints); // Maps a fallback endpoint with an empty delegate. This is OK because // we don't expect the delegate to run. - routes.MapFallback(pattern, context => Task.CompletedTask).Add(b => + endpoints.MapFallback(pattern, context => Task.CompletedTask).Add(b => { // MVC registers a policy that looks for this metadata. b.Metadata.Add(CreateDynamicPageMetadata(page, area)); @@ -280,9 +280,9 @@ namespace Microsoft.AspNetCore.Builder }); } - private static void EnsureRazorPagesServices(IEndpointRouteBuilder routes) + private static void EnsureRazorPagesServices(IEndpointRouteBuilder endpoints) { - var marker = routes.ServiceProvider.GetService(); + var marker = endpoints.ServiceProvider.GetService(); if (marker == null) { throw new InvalidOperationException(Mvc.Core.Resources.FormatUnableToFindServices( @@ -292,13 +292,13 @@ namespace Microsoft.AspNetCore.Builder } } - private static PageActionEndpointDataSource GetOrCreateDataSource(IEndpointRouteBuilder routes) + private static PageActionEndpointDataSource GetOrCreateDataSource(IEndpointRouteBuilder endpoints) { - var dataSource = routes.DataSources.OfType().FirstOrDefault(); + var dataSource = endpoints.DataSources.OfType().FirstOrDefault(); if (dataSource == null) { - dataSource = routes.ServiceProvider.GetRequiredService(); - routes.DataSources.Add(dataSource); + dataSource = endpoints.ServiceProvider.GetRequiredService(); + endpoints.DataSources.Add(dataSource); } return dataSource; diff --git a/src/Mvc/benchmarkapps/BasicApi/Startup.cs b/src/Mvc/benchmarkapps/BasicApi/Startup.cs index e1d5428d93..a7e4a0dac6 100644 --- a/src/Mvc/benchmarkapps/BasicApi/Startup.cs +++ b/src/Mvc/benchmarkapps/BasicApi/Startup.cs @@ -155,8 +155,15 @@ namespace BasicApi } }); + app.UseRouting(); + app.UseAuthentication(); - app.UseMvc(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); } private void CreateDatabaseTables(IServiceProvider services) diff --git a/src/Mvc/benchmarkapps/BasicViews/Startup.cs b/src/Mvc/benchmarkapps/BasicViews/Startup.cs index 8d24470a28..53c561bd76 100644 --- a/src/Mvc/benchmarkapps/BasicViews/Startup.cs +++ b/src/Mvc/benchmarkapps/BasicViews/Startup.cs @@ -116,7 +116,16 @@ namespace BasicViews }); app.UseStaticFiles(); - app.UseMvcWithDefaultRoute(); + + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + }); } private void CreateDatabaseTables(IServiceProvider services) diff --git a/src/Mvc/benchmarkapps/RazorRendering/Startup.cs b/src/Mvc/benchmarkapps/RazorRendering/Startup.cs index 3092f1639c..2eb0abb1c1 100644 --- a/src/Mvc/benchmarkapps/RazorRendering/Startup.cs +++ b/src/Mvc/benchmarkapps/RazorRendering/Startup.cs @@ -22,7 +22,13 @@ public class Startup public void Configure(IApplicationBuilder app, IHostingEnvironment env) { - app.UseMvc(); + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); + }); } private static List DataA = GenerateDataA(); diff --git a/src/Mvc/samples/MvcSandbox/Startup.cs b/src/Mvc/samples/MvcSandbox/Startup.cs index 6b81682f80..0f426789ac 100644 --- a/src/Mvc/samples/MvcSandbox/Startup.cs +++ b/src/Mvc/samples/MvcSandbox/Startup.cs @@ -38,7 +38,8 @@ namespace MvcSandbox app.UseDeveloperExceptionPage(); app.UseStaticFiles(); - app.UseRouting(builder => + app.UseRouting(); + app.UseEndpoints(builder => { builder.MapGet( requestDelegate: WriteEndpoints, @@ -73,8 +74,6 @@ namespace MvcSandbox builder.MapComponentHub("app"); builder.MapFallbackToPage("/Components"); }); - - app.UseEndpoint(); } private static Task WriteEndpoints(HttpContext httpContext) diff --git a/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterEndpointRoutingTest.cs b/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterEndpointRoutingTest.cs new file mode 100644 index 0000000000..49d8818478 --- /dev/null +++ b/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterEndpointRoutingTest.cs @@ -0,0 +1,31 @@ +// 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.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc.FunctionalTests +{ + public class GlobalAuthorizationFilterEndpointRoutingTest : GlobalAuthorizationFilterTestBase, IClassFixture> + { + public GlobalAuthorizationFilterEndpointRoutingTest(MvcTestFixture fixture) + { + Factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder); + Client = Factory.CreateDefaultClient(); + } + + private static void ConfigureWebHostBuilder(IWebHostBuilder builder) => + builder.UseStartup(); + + public WebApplicationFactory Factory { get; } + + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/8387")] + public override Task DeniesAnonymousUsers_ByDefault() + { + return Task.CompletedTask; + } + } +} diff --git a/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs b/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterTestBase.cs similarity index 71% rename from src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs rename to src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterTestBase.cs index 0443d9252e..45ad795edc 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterTestBase.cs @@ -5,29 +5,16 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.Testing; using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests { - public class GlobalAuthorizationFilterTest : IClassFixture> + public abstract class GlobalAuthorizationFilterTestBase : IClassFixture> { - public GlobalAuthorizationFilterTest(MvcTestFixture fixture) - { - Factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder); - Client = Factory.CreateDefaultClient(); - } - - private static void ConfigureWebHostBuilder(IWebHostBuilder builder) => - builder.UseStartup(); - - public HttpClient Client { get; } - - public WebApplicationFactory Factory { get; } + public HttpClient Client { get; protected set; } [Fact] - public async Task DeniesAnonymousUsers_ByDefault() + public virtual async Task DeniesAnonymousUsers_ByDefault() { // Arrange & Act var response = await Client.GetAsync("http://localhost/Administration/Index"); diff --git a/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterUseMvcTest.cs b/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterUseMvcTest.cs new file mode 100644 index 0000000000..8a52d219fe --- /dev/null +++ b/src/Mvc/test/Mvc.FunctionalTests/GlobalAuthorizationFilterUseMvcTest.cs @@ -0,0 +1,24 @@ +// 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.Linq; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc.FunctionalTests +{ + public class GlobalAuthorizationFilterUseMvcTest : GlobalAuthorizationFilterTestBase, IClassFixture> + { + public GlobalAuthorizationFilterUseMvcTest(MvcTestFixture fixture) + { + Factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder); + Client = Factory.CreateDefaultClient(); + } + + private static void ConfigureWebHostBuilder(IWebHostBuilder builder) => + builder.UseStartup(); + + public WebApplicationFactory Factory { get; } + } +} diff --git a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs index c082723dd8..8f4f5be2c0 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs @@ -918,7 +918,7 @@ Hello from /Pages/WithViewStart/Index.cshtml!"; { // Arrange var expected = -@"Microsoft.AspNetCore.Mvc.Routing.EndpointRoutingUrlHelper +@"Microsoft.AspNetCore.Mvc.Routing.UrlHelper Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper`1[AspNetCore.InjectedPageProperties] Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore.InjectedPageProperties]"; diff --git a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs index 4a11189cb2..08b735034f 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal("Hello from /Admin/RouteTemplate my-user-id 4", content.Trim()); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/8387")] public async Task AuthConvention_IsAppliedOnBasePathRelativePaths_ForFiles() { // Act @@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal("/Login?ReturnUrl=%2FConventions%2FAuth", response.Headers.Location.PathAndQuery); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/8387")] public async Task AuthConvention_IsAppliedOnBasePathRelativePaths_For_Folders() { // Act @@ -372,7 +372,7 @@ Hello from /Pages/Shared/"; Assert.Equal(expected, response.Trim(), ignoreLineEndingDifferences: true); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/8387")] public async Task AuthorizeFolderConvention_CanBeAppliedToAreaPages() { // Act diff --git a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithEndpointRoutingTest.cs b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithEndpointRoutingTest.cs index 183372722d..da5d688cf7 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithEndpointRoutingTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithEndpointRoutingTest.cs @@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests public HttpClient Client { get; } - [Fact] + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/8387")] public async Task Authorize_AppliedUsingConvention_Works() { // Act @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal("Hello from Anonymous", content.Trim()); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/8387")] public async Task Authorize_AppliedUsingAttributeOnModel_Works() { // Act diff --git a/src/Mvc/test/Mvc.FunctionalTests/RoutingUseMvcWithEndpointRoutingTest.cs b/src/Mvc/test/Mvc.FunctionalTests/RoutingUseMvcWithEndpointRoutingTest.cs deleted file mode 100644 index 154a0fd965..0000000000 --- a/src/Mvc/test/Mvc.FunctionalTests/RoutingUseMvcWithEndpointRoutingTest.cs +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.Mvc.FunctionalTests -{ - public class RoutingUseMvcWithEndpointRoutingTest : RoutingTestsBase - { - public RoutingUseMvcWithEndpointRoutingTest(MvcTestFixture fixture) - : base(fixture) - { - } - - [Fact] - public async Task AttributeRoutedAction_ContainsPage_RouteMatched() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/PageRoute/Attribute/pagevalue"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Contains("/PageRoute/Attribute/pagevalue", result.ExpectedUrls); - Assert.Equal("PageRoute", result.Controller); - Assert.Equal("AttributeRoute", result.Action); - - Assert.Contains( - new KeyValuePair("page", "pagevalue"), - result.RouteValues); - } - - [Fact] - public async Task ParameterTransformer_TokenReplacement_Found() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/parameter-transformer/my-action"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("ParameterTransformer", result.Controller); - Assert.Equal("MyAction", result.Action); - } - - [Fact] - public async Task ParameterTransformer_TokenReplacement_NotFound() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/ParameterTransformer/MyAction"); - - // Assert - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Fact] - public async Task AttributeRoutedAction_Parameters_Found() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/EndpointRouting/Index"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("EndpointRouting", result.Controller); - Assert.Equal("Index", result.Action); - } - - [Fact] - public async Task AttributeRoutedAction_Parameters_DefaultValue_Found() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/EndpointRouting"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("EndpointRouting", result.Controller); - Assert.Equal("Index", result.Action); - } - - [Fact] - public async Task AttributeRoutedAction_ParameterTransformer_Found() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/endpoint-routing/ParameterTransformer"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("EndpointRouting", result.Controller); - Assert.Equal("ParameterTransformer", result.Action); - } - - [Fact] - public async Task AttributeRoutedAction_ParameterTransformer_NotFound() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/EndpointRouting/ParameterTransformer"); - - // Assert - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Fact] - public async Task AttributeRoutedAction_ParameterTransformer_LinkToSelf() - { - // Arrange - var url = LinkFrom("http://localhost/endpoint-routing/ParameterTransformer").To(new { }); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("EndpointRouting", result.Controller); - Assert.Equal("ParameterTransformer", result.Action); - - Assert.Equal("/endpoint-routing/ParameterTransformer", result.Link); - } - - [Fact] - public async Task AttributeRoutedAction_ParameterTransformer_LinkWithAmbientController() - { - // Arrange - var url = LinkFrom("http://localhost/endpoint-routing/ParameterTransformer").To(new { action = "Get", id = 5 }); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("EndpointRouting", result.Controller); - Assert.Equal("ParameterTransformer", result.Action); - - Assert.Equal("/endpoint-routing/5", result.Link); - } - - [Fact] - public async Task AttributeRoutedAction_ParameterTransformer_LinkToAttributeRoutedController() - { - // Arrange - var url = LinkFrom("http://localhost/endpoint-routing/ParameterTransformer").To(new { action = "ShowPosts", controller = "Blog" }); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("EndpointRouting", result.Controller); - Assert.Equal("ParameterTransformer", result.Action); - - Assert.Equal("/Blog/ShowPosts", result.Link); - } - - [Fact] - public async Task AttributeRoutedAction_ParameterTransformer_LinkToConventionalController() - { - // Arrange - var url = LinkFrom("http://localhost/endpoint-routing/ParameterTransformer").To(new { action = "Index", controller = "Home" }); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("EndpointRouting", result.Controller); - Assert.Equal("ParameterTransformer", result.Action); - - Assert.Equal("/", result.Link); - } - - [Fact] - public async override Task HasEndpointMatch() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/Routing/HasEndpointMatch"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.True(result); - } - - [Fact] - public async override Task RouteData_Routers_ConventionalRoute() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/RouteData/Conventional"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal( - Array.Empty(), - result.Routers); - } - - [Fact] - public async override Task RouteData_Routers_AttributeRoute() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/RouteData/Attribute"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal( - Array.Empty(), - result.Routers); - } - - // Endpoint routing exposes HTTP 405s for HTTP method mismatches - [Fact] - public override async Task ConventionalRoutedController_InArea_ActionBlockedByHttpMethod() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/Travel/Flight/BuyTickets"); - - // Assert - Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode); - } - - [Fact] - public async Task ConventionalRoutedAction_ParameterTransformer() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/ConventionalTransformerRoute/conventional-transformer/Index"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("ConventionalTransformer", result.Controller); - Assert.Equal("Index", result.Action); - } - - [Fact] - public async Task ConventionalRoutedAction_ParameterTransformer_NotFound() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/ConventionalTransformerRoute/ConventionalTransformer/Index"); - - // Assert - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Fact] - public async Task ConventionalRoutedAction_ParameterTransformer_DefaultValue() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/ConventionalTransformerRoute/conventional-transformer"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("ConventionalTransformer", result.Controller); - Assert.Equal("Index", result.Action); - } - - [Fact] - public async Task ConventionalRoutedAction_ParameterTransformer_WithParam() - { - // Arrange & Act - var response = await Client.GetAsync("http://localhost/ConventionalTransformerRoute/conventional-transformer/Param/my-value"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("ConventionalTransformer", result.Controller); - Assert.Equal("Param", result.Action); - - Assert.Equal("/ConventionalTransformerRoute/conventional-transformer/Param/my-value", Assert.Single(result.ExpectedUrls)); - } - - [Fact] - public async Task ConventionalRoutedAction_ParameterTransformer_LinkToConventionalController() - { - // Arrange - var url = LinkFrom("http://localhost/ConventionalTransformerRoute/conventional-transformer/Index").To(new { action = "Index", controller = "Home" }); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("ConventionalTransformer", result.Controller); - Assert.Equal("Index", result.Action); - Assert.Equal("/", result.Link); - } - - [Fact] - public async Task ConventionalRoutedAction_ParameterTransformer_LinkToConventionalControllerWithParam() - { - // Arrange - var url = LinkFrom("http://localhost/ConventionalTransformerRoute/conventional-transformer/Index").To(new { action = "Param", controller = "ConventionalTransformer", param = "MyValue" }); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("ConventionalTransformer", result.Controller); - Assert.Equal("Index", result.Action); - Assert.Equal("/ConventionalTransformerRoute/conventional-transformer/Param/my-value", result.Link); - } - - [Fact] - public async Task ConventionalRoutedAction_ParameterTransformer_LinkToSelf() - { - // Arrange - var url = LinkFrom("http://localhost/ConventionalTransformerRoute/conventional-transformer/Index").To(new {}); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("ConventionalTransformer", result.Controller); - Assert.Equal("Index", result.Action); - Assert.Equal("/ConventionalTransformerRoute/conventional-transformer", result.Link); - } - - // Endpoint routing exposes HTTP 405s for HTTP method mismatches. - protected override void AssertCorsRejectionStatusCode(HttpResponseMessage response) - { - Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode); - } - } -} diff --git a/src/Mvc/test/WebSites/ApiExplorerWebSite/Startup.cs b/src/Mvc/test/WebSites/ApiExplorerWebSite/Startup.cs index 571218280f..ff736bf9c9 100644 --- a/src/Mvc/test/WebSites/ApiExplorerWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/ApiExplorerWebSite/Startup.cs @@ -46,9 +46,10 @@ namespace ApiExplorerWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Mvc/test/WebSites/ApplicationModelWebSite/Startup.cs b/src/Mvc/test/WebSites/ApplicationModelWebSite/Startup.cs index 439cdd8941..7d288a4cf5 100644 --- a/src/Mvc/test/WebSites/ApplicationModelWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/ApplicationModelWebSite/Startup.cs @@ -27,12 +27,13 @@ namespace ApplicationModelWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapControllerRoute(name: "areaRoute", pattern: "{area:exists}/{controller=Home}/{action=Index}"); - routes.MapControllerRoute(name: "default", pattern: "{controller}/{action}/{id?}"); + endpoints.MapControllerRoute(name: "areaRoute", pattern: "{area:exists}/{controller=Home}/{action=Index}"); + endpoints.MapControllerRoute(name: "default", pattern: "{controller}/{action}/{id?}"); - routes.MapRazorPages(); + endpoints.MapRazorPages(); }); } diff --git a/src/Mvc/test/WebSites/BasicWebSite/Startup.cs b/src/Mvc/test/WebSites/BasicWebSite/Startup.cs index 2d82820d61..7e5236d53b 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/Startup.cs @@ -35,14 +35,15 @@ namespace BasicWebSite // Initializes the RequestId service for each request app.UseMiddleware(); - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapControllerRoute( + endpoints.MapControllerRoute( name: "ActionAsMethod", pattern: "{controller}/{action}", defaults: new { controller = "Home", action = "Index" }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( name: "PageRoute", pattern: "{controller}/{action}/{page}"); }); diff --git a/src/Mvc/test/WebSites/BasicWebSite/StartupRequestLimitSize.cs b/src/Mvc/test/WebSites/BasicWebSite/StartupRequestLimitSize.cs index 3e0e9aa16e..ed7524fa4d 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/StartupRequestLimitSize.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/StartupRequestLimitSize.cs @@ -39,10 +39,11 @@ namespace BasicWebSite return next(); }); - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); - routes.MapRazorPages(); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } diff --git a/src/Mvc/test/WebSites/BasicWebSite/StartupWithCookieTempDataProviderAndCookieConsent.cs b/src/Mvc/test/WebSites/BasicWebSite/StartupWithCookieTempDataProviderAndCookieConsent.cs index 25abeeca3b..7083bd21dc 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/StartupWithCookieTempDataProviderAndCookieConsent.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/StartupWithCookieTempDataProviderAndCookieConsent.cs @@ -28,11 +28,11 @@ namespace BasicWebSite app.UseDeveloperExceptionPage(); app.UseCookiePolicy(); - - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); - routes.MapRazorPages(); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } } diff --git a/src/Mvc/test/WebSites/BasicWebSite/StartupWithCustomInvalidModelStateFactory.cs b/src/Mvc/test/WebSites/BasicWebSite/StartupWithCustomInvalidModelStateFactory.cs index f37bc908d4..ff911cc981 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/StartupWithCustomInvalidModelStateFactory.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/StartupWithCustomInvalidModelStateFactory.cs @@ -48,9 +48,10 @@ namespace BasicWebSite { app.UseDeveloperExceptionPage(); - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapControllers(); + endpoints.MapControllers(); }); } } diff --git a/src/Mvc/test/WebSites/BasicWebSite/StartupWithSessionTempDataProvider.cs b/src/Mvc/test/WebSites/BasicWebSite/StartupWithSessionTempDataProvider.cs index 9c321e2001..744a3fea0b 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/StartupWithSessionTempDataProvider.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/StartupWithSessionTempDataProvider.cs @@ -26,10 +26,11 @@ namespace BasicWebSite app.UseDeveloperExceptionPage(); app.UseSession(); - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); - routes.MapRazorPages(); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } } diff --git a/src/Mvc/test/WebSites/ControllersFromServicesWebSite/Startup.cs b/src/Mvc/test/WebSites/ControllersFromServicesWebSite/Startup.cs index f8e7b9dd7f..0202fc9f83 100644 --- a/src/Mvc/test/WebSites/ControllersFromServicesWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/ControllersFromServicesWebSite/Startup.cs @@ -64,9 +64,10 @@ namespace ControllersFromServicesWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Mvc/test/WebSites/CorsWebSite/Startup.cs b/src/Mvc/test/WebSites/CorsWebSite/Startup.cs index 6f89c6aa4d..9c68dc4d62 100644 --- a/src/Mvc/test/WebSites/CorsWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/CorsWebSite/Startup.cs @@ -74,9 +74,10 @@ namespace CorsWebSite public virtual void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapControllers(); + endpoints.MapControllers(); }); } diff --git a/src/Mvc/test/WebSites/ErrorPageMiddlewareWebSite/Startup.cs b/src/Mvc/test/WebSites/ErrorPageMiddlewareWebSite/Startup.cs index 07fb576c33..c5e50c7a71 100644 --- a/src/Mvc/test/WebSites/ErrorPageMiddlewareWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/ErrorPageMiddlewareWebSite/Startup.cs @@ -22,9 +22,10 @@ namespace ErrorPageMiddlewareWebSite public void Configure(IApplicationBuilder app) { app.UseDeveloperExceptionPage(); - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapControllers(); + endpoints.MapControllers(); }); } diff --git a/src/Mvc/test/WebSites/FSharpWebSite/Startup.fs b/src/Mvc/test/WebSites/FSharpWebSite/Startup.fs index 09b0db7737..229b67de8d 100644 --- a/src/Mvc/test/WebSites/FSharpWebSite/Startup.fs +++ b/src/Mvc/test/WebSites/FSharpWebSite/Startup.fs @@ -16,4 +16,5 @@ type Startup () = member this.Configure(app: IApplicationBuilder) = app.UseDeveloperExceptionPage() |> ignore app.UseStaticFiles() |> ignore - app.UseMvcWithDefaultRoute() |> ignore + app.UseRouting() |> ignore + app.UseEndpoints(fun endpoints -> endpoints.MapDefaultControllerRoute() |> ignore) |> ignore diff --git a/src/Mvc/test/WebSites/FilesWebSite/Startup.cs b/src/Mvc/test/WebSites/FilesWebSite/Startup.cs index d3821e06d8..cd918afa87 100644 --- a/src/Mvc/test/WebSites/FilesWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/FilesWebSite/Startup.cs @@ -21,9 +21,10 @@ namespace FilesWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Mvc/test/WebSites/FormatterWebSite/Startup.cs b/src/Mvc/test/WebSites/FormatterWebSite/Startup.cs index 796ddc3037..603e7dc618 100644 --- a/src/Mvc/test/WebSites/FormatterWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/FormatterWebSite/Startup.cs @@ -26,9 +26,10 @@ namespace FormatterWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } } diff --git a/src/Mvc/test/WebSites/FormatterWebSite/StartupWithJsonInputFormatter.cs b/src/Mvc/test/WebSites/FormatterWebSite/StartupWithJsonInputFormatter.cs index 8a65c09db7..3966fb6ba4 100644 --- a/src/Mvc/test/WebSites/FormatterWebSite/StartupWithJsonInputFormatter.cs +++ b/src/Mvc/test/WebSites/FormatterWebSite/StartupWithJsonInputFormatter.cs @@ -23,9 +23,10 @@ namespace FormatterWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } } diff --git a/src/Mvc/test/WebSites/FormatterWebSite/StartupWithRespectBrowserAcceptHeader.cs b/src/Mvc/test/WebSites/FormatterWebSite/StartupWithRespectBrowserAcceptHeader.cs index ee419a2caf..9614f491f7 100644 --- a/src/Mvc/test/WebSites/FormatterWebSite/StartupWithRespectBrowserAcceptHeader.cs +++ b/src/Mvc/test/WebSites/FormatterWebSite/StartupWithRespectBrowserAcceptHeader.cs @@ -19,9 +19,10 @@ namespace FormatterWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } } diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/Startup.cs b/src/Mvc/test/WebSites/GenericHostWebSite/Startup.cs index adb6da9a44..cb2ce81b4a 100644 --- a/src/Mvc/test/WebSites/GenericHostWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/GenericHostWebSite/Startup.cs @@ -40,17 +40,18 @@ namespace GenericHostWebSite app.UseStaticFiles(); - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapControllerRoute( + endpoints.MapControllerRoute( "areaRoute", "{area:exists}/{controller}/{action}", new { controller = "Home", action = "Index" }); - routes.MapControllerRoute("ActionAsMethod", "{controller}/{action}", + endpoints.MapControllerRoute("ActionAsMethod", "{controller}/{action}", defaults: new { controller = "Home", action = "Index" }); - routes.MapControllerRoute("PageRoute", "{controller}/{action}/{page}"); + endpoints.MapControllerRoute("PageRoute", "{controller}/{action}/{page}"); }); } } diff --git a/src/Mvc/test/WebSites/HtmlGenerationWebSite/Startup.cs b/src/Mvc/test/WebSites/HtmlGenerationWebSite/Startup.cs index 1a36418505..b1efdeb4ed 100644 --- a/src/Mvc/test/WebSites/HtmlGenerationWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/HtmlGenerationWebSite/Startup.cs @@ -30,22 +30,23 @@ namespace HtmlGenerationWebSite { app.UseStaticFiles(); - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapControllerRoute( + endpoints.MapControllerRoute( name: "areaRoute", pattern: "{area:exists}/{controller}/{action}/{id?}", defaults: new { action = "Index" }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( name: "productRoute", pattern: "Product/{action}", defaults: new { controller = "Product" }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action}/{id?}", defaults: new { controller = "HtmlGeneration_Home", action = "Index" }); - routes.MapRazorPages(); + endpoints.MapRazorPages(); }); } diff --git a/src/Mvc/test/WebSites/RazorBuildWebSite/Startup.cs b/src/Mvc/test/WebSites/RazorBuildWebSite/Startup.cs index b6dcfb42b7..0db8a20c74 100644 --- a/src/Mvc/test/WebSites/RazorBuildWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/RazorBuildWebSite/Startup.cs @@ -23,10 +23,11 @@ namespace RazorBuildWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); - routes.MapRazorPages(); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/Startup.cs b/src/Mvc/test/WebSites/RazorPagesWebSite/Startup.cs index bf0fa2fa99..f8bb11a78c 100644 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/Startup.cs @@ -25,13 +25,16 @@ namespace RazorPagesWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => - { - routes.MapControllers(); - routes.MapRazorPages(); - }); + app.UseRouting(); + app.UseAuthentication(); app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + endpoints.MapRazorPages(); + }); } } } diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs b/src/Mvc/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs index 9d9bf26a2f..97f11d6235 100644 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs @@ -38,14 +38,17 @@ namespace RazorPagesWebSite public void Configure(IApplicationBuilder app) { - app.UseAuthentication(); - app.UseStaticFiles(); - app.UseRouting(routes => + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapControllerRoute("areaRoute", "{area:exists}/{controller=Home}/{action=Index}"); - routes.MapRazorPages(); + endpoints.MapControllerRoute("areaRoute", "{area:exists}/{controller=Home}/{action=Index}"); + endpoints.MapRazorPages(); }); } } diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/StartupWithoutEndpointRouting.cs b/src/Mvc/test/WebSites/RazorPagesWebSite/StartupWithoutEndpointRouting.cs index 7cd47c7a65..4b08d0c458 100644 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/StartupWithoutEndpointRouting.cs +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/StartupWithoutEndpointRouting.cs @@ -15,7 +15,7 @@ namespace RazorPagesWebSite public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => options.LoginPath = "/Login"); - services.AddMvc() + services.AddMvc(options => options.EnableEndpointRouting = false) .AddMvcLocalization() .AddNewtonsoftJson() .AddRazorPagesOptions(options => diff --git a/src/Mvc/test/WebSites/RazorWebSite/Startup.cs b/src/Mvc/test/WebSites/RazorWebSite/Startup.cs index 6f7471b33c..915e8607de 100644 --- a/src/Mvc/test/WebSites/RazorWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/RazorWebSite/Startup.cs @@ -45,6 +45,9 @@ namespace RazorWebSite public void Configure(IApplicationBuilder app) { app.UseDeveloperExceptionPage(); + + app.UseRouting(); + app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("en-GB", "en-US"), @@ -62,10 +65,10 @@ namespace RazorWebSite } }); - app.UseRouting(routes => + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); - routes.MapRazorPages(); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } } diff --git a/src/Mvc/test/WebSites/RazorWebSite/StartupDataAnnotations.cs b/src/Mvc/test/WebSites/RazorWebSite/StartupDataAnnotations.cs index 5f3ae08f90..63f063aef8 100644 --- a/src/Mvc/test/WebSites/RazorWebSite/StartupDataAnnotations.cs +++ b/src/Mvc/test/WebSites/RazorWebSite/StartupDataAnnotations.cs @@ -32,6 +32,10 @@ namespace RazorWebSite public void Configure(IApplicationBuilder app) { app.UseDeveloperExceptionPage(); + app.UseStaticFiles(); + + app.UseRouting(); + app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("en-US", "en-US"), @@ -44,11 +48,10 @@ namespace RazorWebSite new CultureInfo("en-US") } }); - app.UseStaticFiles(); - - app.UseRouting(routes => + + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } } diff --git a/src/Mvc/test/WebSites/RoutingWebSite/RoutingWebSite.csproj b/src/Mvc/test/WebSites/RoutingWebSite/RoutingWebSite.csproj index 2ebdca4f3c..229db281ca 100644 --- a/src/Mvc/test/WebSites/RoutingWebSite/RoutingWebSite.csproj +++ b/src/Mvc/test/WebSites/RoutingWebSite/RoutingWebSite.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.0 diff --git a/src/Mvc/test/WebSites/RoutingWebSite/Startup.cs b/src/Mvc/test/WebSites/RoutingWebSite/Startup.cs index 47a966efd7..c44d472f7c 100644 --- a/src/Mvc/test/WebSites/RoutingWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/RoutingWebSite/Startup.cs @@ -38,62 +38,63 @@ namespace RoutingWebSite public virtual void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapControllerRoute( + endpoints.MapControllerRoute( "NonParameterConstraintRoute", "NonParameterConstraintRoute/{controller}/{action}", defaults: null, constraints: new { controller = "NonParameterConstraint", nonParameter = new QueryStringConstraint() }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( "DataTokensRoute", "DataTokensRoute/{controller}/{action}", defaults: null, constraints: new { controller = "DataTokens" }, dataTokens: new { hasDataTokens = true }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( "ConventionalTransformerRoute", "ConventionalTransformerRoute/{controller:slugify}/{action=Index}/{param:slugify?}", defaults: null, constraints: new { controller = "ConventionalTransformer" }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( "DefaultValuesRoute_OptionalParameter", "DefaultValuesRoute/Optional/{controller=DEFAULTVALUES}/{action=OPTIONALPARAMETER}/{id?}/{**catchAll}", defaults: null, constraints: new { controller = "DefaultValues", action = "OptionalParameter" }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( "DefaultValuesRoute_DefaultParameter", "DefaultValuesRoute/Default/{controller=DEFAULTVALUES}/{action=DEFAULTPARAMETER}/{id=17}/{**catchAll}", defaults: null, constraints: new { controller = "DefaultValues", action = "DefaultParameter" }); - routes.MapAreaControllerRoute( + endpoints.MapAreaControllerRoute( "flightRoute", "adminRoute", "{area:exists}/{controller}/{action}", defaults: new { controller = "Home", action = "Index" }, constraints: new { area = "Travel" }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( "PageRoute", "{controller}/{action}/{page}", defaults: null, constraints: new { controller = "PageRoute" }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( "ActionAsMethod", "{controller}/{action}", defaults: new { controller = "Home", action = "Index" }); - routes.MapControllerRoute( + endpoints.MapControllerRoute( "RouteWithOptionalSegment", "{controller}/{action}/{path?}"); - routes.MapRazorPages(); + endpoints.MapRazorPages(); }); app.Map("/afterrouting", b => b.Run(c => diff --git a/src/Mvc/test/WebSites/RoutingWebSite/StartupForFallback.cs b/src/Mvc/test/WebSites/RoutingWebSite/StartupForFallback.cs index 3bb86e4c89..e59bf80b00 100644 --- a/src/Mvc/test/WebSites/RoutingWebSite/StartupForFallback.cs +++ b/src/Mvc/test/WebSites/RoutingWebSite/StartupForFallback.cs @@ -25,15 +25,16 @@ namespace RoutingWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { // Workaround for #8130 // // You can't fallback to this unless it already has another route. - routes.MapAreaControllerRoute("admin", "Admin", "Admin/{controller=Home}/{action=Index}/{id?}"); + endpoints.MapAreaControllerRoute("admin", "Admin", "Admin/{controller=Home}/{action=Index}/{id?}"); - routes.MapFallbackToAreaController("admin/{*path:nonfile}", "Index", "Fallback", "Admin"); - routes.MapFallbackToPage("/FallbackPage"); + endpoints.MapFallbackToAreaController("admin/{*path:nonfile}", "Index", "Fallback", "Admin"); + endpoints.MapFallbackToPage("/FallbackPage"); }); app.Map("/afterrouting", b => b.Run(c => diff --git a/src/Mvc/test/WebSites/RoutingWebSite/StartupForLinkGenerator.cs b/src/Mvc/test/WebSites/RoutingWebSite/StartupForLinkGenerator.cs index fee063c20d..cbb680b80e 100644 --- a/src/Mvc/test/WebSites/RoutingWebSite/StartupForLinkGenerator.cs +++ b/src/Mvc/test/WebSites/RoutingWebSite/StartupForLinkGenerator.cs @@ -39,10 +39,11 @@ namespace RoutingWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); - routes.MapRazorPages(); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } } diff --git a/src/Mvc/test/WebSites/RoutingWebSite/StartupWithUseMvcAndEndpointRouting.cs b/src/Mvc/test/WebSites/RoutingWebSite/StartupWithUseMvcAndEndpointRouting.cs deleted file mode 100644 index 6d90c870f9..0000000000 --- a/src/Mvc/test/WebSites/RoutingWebSite/StartupWithUseMvcAndEndpointRouting.cs +++ /dev/null @@ -1,80 +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.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Abstractions; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; - -namespace RoutingWebSite -{ - public class StartupWithUseMvcAndEndpointRouting : Startup - { - public override void Configure(IApplicationBuilder app) - { - app.UseMvc(routes => - { - routes.MapRoute( - "NonParameterConstraintRoute", - "NonParameterConstraintRoute/{controller}/{action}", - defaults: null, - constraints: new { controller = "NonParameterConstraint", nonParameter = new QueryStringConstraint() }); - - routes.MapRoute( - "DataTokensRoute", - "DataTokensRoute/{controller}/{action}", - defaults: null, - constraints: new { controller = "DataTokens" }, - dataTokens: new { hasDataTokens = true }); - - routes.MapRoute( - "ConventionalTransformerRoute", - "ConventionalTransformerRoute/{controller:slugify}/{action=Index}/{param:slugify?}", - defaults: null, - constraints: new { controller = "ConventionalTransformer" }); - - routes.MapRoute( - "DefaultValuesRoute_OptionalParameter", - "DefaultValuesRoute/Optional/{controller=DEFAULTVALUES}/{action=OPTIONALPARAMETER}/{id?}/{**catchAll}", - defaults: null, - constraints: new { controller = "DefaultValues", action = "OptionalParameter" }); - - routes.MapRoute( - "DefaultValuesRoute_DefaultParameter", - "DefaultValuesRoute/Default/{controller=DEFAULTVALUES}/{action=DEFAULTPARAMETER}/{id=17}/{**catchAll}", - defaults: null, - constraints: new { controller = "DefaultValues", action = "DefaultParameter" }); - - routes.MapAreaRoute( - "flightRoute", - "adminRoute", - "{area:exists}/{controller}/{action}", - defaults: new { controller = "Home", action = "Index" }, - constraints: new { area = "Travel" }); - - routes.MapRoute( - "PageRoute", - "{controller}/{action}/{page}", - defaults: null, - constraints: new { controller = "PageRoute" }); - - routes.MapRoute( - "ActionAsMethod", - "{controller}/{action}", - defaults: new { controller = "Home", action = "Index" }); - - routes.MapRoute( - "RouteWithOptionalSegment", - "{controller}/{action}/{path?}"); - }); - - app.Map("/afterrouting", b => b.Run(c => - { - return c.Response.WriteAsync("Hello from middleware after routing"); - })); - } - } -} diff --git a/src/Mvc/test/WebSites/SecurityWebSite/Startup.cs b/src/Mvc/test/WebSites/SecurityWebSite/Startup.cs index 16d9364aea..0e26a546c2 100644 --- a/src/Mvc/test/WebSites/SecurityWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/SecurityWebSite/Startup.cs @@ -18,7 +18,7 @@ namespace SecurityWebSite services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddAntiforgery(); - services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => { options.LoginPath = "/Home/Login"; options.LogoutPath = "/Home/Logout"; @@ -30,11 +30,14 @@ namespace SecurityWebSite // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { - app.UseAuthentication(); + app.UseRouting(); - app.UseRouting(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } } diff --git a/src/Mvc/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilter.cs b/src/Mvc/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilter.cs index ca1167e13a..2a0ba81886 100644 --- a/src/Mvc/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilter.cs +++ b/src/Mvc/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilter.cs @@ -33,11 +33,14 @@ namespace SecurityWebSite public void Configure(IApplicationBuilder app) { - app.UseAuthentication(); + app.UseRouting(); - app.UseRouting(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } } diff --git a/src/Mvc/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilterWithUseMvc.cs b/src/Mvc/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilterWithUseMvc.cs new file mode 100644 index 0000000000..9977b1cf73 --- /dev/null +++ b/src/Mvc/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilterWithUseMvc.cs @@ -0,0 +1,42 @@ +// 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.Authentication.Cookies; +using Microsoft.AspNetCore.Authorization.Policy; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Authorization; +using Microsoft.Extensions.DependencyInjection; + +namespace SecurityWebSite +{ + public class StartupWithGlobalDenyAnonymousFilterWithUseMvc + { + public void ConfigureServices(IServiceCollection services) + { + services + .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(options => + { + options.LoginPath = "/Home/Login"; + options.LogoutPath = "/Home/Logout"; + }).AddCookie("Cookie2"); + + services.AddMvc(o => + { + o.EnableEndpointRouting = false; + o.Filters.Add(new AuthorizeFilter()); + }) + .SetCompatibilityVersion(CompatibilityVersion.Latest); + + services.AddScoped(); + } + + public void Configure(IApplicationBuilder app) + { + app.UseAuthentication(); + + app.UseMvcWithDefaultRoute(); + } + } +} diff --git a/src/Mvc/test/WebSites/SecurityWebSite/StartupWithUseMvc.cs b/src/Mvc/test/WebSites/SecurityWebSite/StartupWithUseMvc.cs new file mode 100644 index 0000000000..74cebe7eac --- /dev/null +++ b/src/Mvc/test/WebSites/SecurityWebSite/StartupWithUseMvc.cs @@ -0,0 +1,37 @@ +// 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.Authentication.Cookies; +using Microsoft.AspNetCore.Authorization.Policy; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; + +namespace SecurityWebSite +{ + public class StartupWithUseMvc + { + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + // Add framework services. + services.AddMvc(options => options.EnableEndpointRouting = false) + .SetCompatibilityVersion(CompatibilityVersion.Latest); + services.AddAntiforgery(); + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => + { + options.LoginPath = "/Home/Login"; + options.LogoutPath = "/Home/Logout"; + }).AddCookie("Cookie2"); + + services.AddScoped(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app) + { + app.UseAuthentication(); + app.UseMvcWithDefaultRoute(); + } + } +} diff --git a/src/Mvc/test/WebSites/SimpleWebSite/Startup.cs b/src/Mvc/test/WebSites/SimpleWebSite/Startup.cs index 8de6a98153..8f14d68158 100644 --- a/src/Mvc/test/WebSites/SimpleWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/SimpleWebSite/Startup.cs @@ -26,9 +26,10 @@ namespace SimpleWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Mvc/test/WebSites/TagHelpersWebSite/Startup.cs b/src/Mvc/test/WebSites/TagHelpersWebSite/Startup.cs index 0caf7375b9..f01dac0414 100644 --- a/src/Mvc/test/WebSites/TagHelpersWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/TagHelpersWebSite/Startup.cs @@ -20,9 +20,10 @@ namespace TagHelpersWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Mvc/test/WebSites/VersioningWebSite/Startup.cs b/src/Mvc/test/WebSites/VersioningWebSite/Startup.cs index 909af127d7..0314094df8 100644 --- a/src/Mvc/test/WebSites/VersioningWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/VersioningWebSite/Startup.cs @@ -23,9 +23,10 @@ namespace VersioningWebSite public virtual void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Mvc/test/WebSites/XmlFormattersWebSite/Startup.cs b/src/Mvc/test/WebSites/XmlFormattersWebSite/Startup.cs index 74c2e21b5a..0e45dec94a 100644 --- a/src/Mvc/test/WebSites/XmlFormattersWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/XmlFormattersWebSite/Startup.cs @@ -27,9 +27,9 @@ namespace XmlFormattersWebSite services.Configure(options => { // Since both XmlSerializer and DataContractSerializer based formatters - // have supported media types of 'application/xml' and 'text/xml', it + // have supported media types of 'application/xml' and 'text/xml', it // would be difficult for a test to choose a particular formatter based on - // request information (Ex: Accept header). + // request information (Ex: Accept header). // We'll configure the ones on MvcOptions to use a distinct set of content types. XmlSerializerInputFormatter xmlSerializerInputFormatter = null; @@ -107,9 +107,10 @@ namespace XmlFormattersWebSite public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapDefaultControllerRoute(); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/Startup.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/Startup.cs index b17317b9f6..078171e104 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-CSharp/Startup.cs @@ -26,9 +26,11 @@ namespace Company.WebApplication1 app.UseDeveloperExceptionPage(); } - app.UseRouting(routes => + app.UseRouting(); + + app.UseEndpoints(endpoints => { - routes.MapGet("/", async context => + endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); }); diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/Startup.fs b/src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/Startup.fs index b0fc8d5c8a..80312fb99a 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/Startup.fs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/EmptyWeb-FSharp/Startup.fs @@ -16,9 +16,11 @@ type Startup() = // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. member this.Configure(app: IApplicationBuilder, env: IWebHostEnvironment) = - if env.IsDevelopment() then + if env.IsDevelopment() then app.UseDeveloperExceptionPage() |> ignore - app.UseRouting(fun routing -> - routing.MapGet("/", fun context -> context.Response.WriteAsync("Hello World!")) |> ignore + app.UseRouting() |> ignore + + app.UseEndpoints(fun endpoints -> + endpoints.MapGet("/", fun context -> context.Response.WriteAsync("Hello World!")) |> ignore ) |> ignore diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/GrpcService-CSharp.Server/Startup.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/GrpcService-CSharp.Server/Startup.cs index fd4841db07..b91f9e1457 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/GrpcService-CSharp.Server/Startup.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/GrpcService-CSharp/GrpcService-CSharp.Server/Startup.cs @@ -26,9 +26,11 @@ namespace GrpcService_CSharp app.UseDeveloperExceptionPage(); } - app.UseRouting(routes => + app.UseRouting(); + + app.UseEndpoints(endpoints => { - routes.MapGrpcService(); + endpoints.MapGrpcService(); }); } } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs index c8c26ab666..a250f47e74 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs @@ -48,10 +48,12 @@ namespace RazorComponentsWeb_CSharp #endif app.UseStaticFiles(); - app.UseRouting(routes => + app.UseRouting(); + + app.UseEndpoints(endpoints => { - routes.MapRazorPages(); - routes.MapComponentHub("app"); + endpoints.MapRazorPages(); + endpoints.MapComponentHub("app"); }); } } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs index dd647f34df..3f407be714 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs @@ -158,20 +158,22 @@ namespace Company.WebApplication1 #endif app.UseStaticFiles(); - app.UseRouting(routes => - { - routes.MapRazorPages(); -#if (IndividualB2CAuth || OrganizationalAuth) - routes.MapControllers(); -#endif - }); - app.UseCookiePolicy(); + app.UseRouting(); + #if (OrganizationalAuth || IndividualAuth) app.UseAuthentication(); #endif app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); +#if (IndividualB2CAuth || OrganizationalAuth) + endpoints.MapControllers(); +#endif + }); } } } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs index dc24469393..c6611407b5 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs @@ -157,20 +157,22 @@ namespace Company.WebApplication1 #endif app.UseStaticFiles(); - app.UseRouting(routes => - { - routes.MapControllerRoute( - name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); - routes.MapRazorPages(); - }); - app.UseCookiePolicy(); + app.UseRouting(); + #if (OrganizationalAuth || IndividualAuth) app.UseAuthentication(); #endif app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapRazorPages(); + }); } } } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Startup.fs b/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Startup.fs index e8a2b45c3d..fa65fda3f5 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Startup.fs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Startup.fs @@ -41,12 +41,14 @@ type Startup private () = #endif app.UseStaticFiles() |> ignore - app.UseRouting(fun routes -> - routes.MapControllerRoute( - name = "default", - pattern = "{controller=Home}/{action=Index}/{id?}") |> ignore - routes.MapRazorPages() |> ignore) |> ignore + app.UseRouting() |> ignore app.UseAuthorization() |> ignore + app.UseEndpoints(fun endpoints -> + endpoints.MapControllerRoute( + name = "default", + pattern = "{controller=Home}/{action=Index}/{id?}") |> ignore + endpoints.MapRazorPages() |> ignore) |> ignore + member val Configuration : IConfiguration = null with get, set diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs index 028797d6c1..987d2d282b 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs @@ -65,15 +65,17 @@ namespace Company.WebApplication1 app.UseHttpsRedirection(); #endif - app.UseRouting(routes => - { - routes.MapControllers(); - }); + app.UseRouting(); #if (OrganizationalAuth || IndividualAuth) app.UseAuthentication(); #endif app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); } } } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Startup.fs b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Startup.fs index a6f84b5513..55ed03b223 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Startup.fs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Startup.fs @@ -37,10 +37,12 @@ type Startup private () = #else #endif - app.UseRouting(fun routes -> - routes.MapControllers() |> ignore - ) |> ignore + app.UseRouting() |> ignore app.UseAuthorization() |> ignore + app.UseEndpoints(fun endpoints -> + endpoints.MapControllers() |> ignore + ) |> ignore + member val Configuration : IConfiguration = null with get, set diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Startup.cs b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Startup.cs index 33c61393dc..9c8c517545 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Startup.cs @@ -55,7 +55,7 @@ namespace Company.WebApplication1 services.AddAuthentication() .AddIdentityServerJwt(); #endif - services.AddMvc() + services.AddMvc(options => options.EnableEndpointRouting = false) .AddNewtonsoftJson(); // In production, the Angular files will be served from this directory diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs index a9c8ec711f..4350f6488f 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/Startup.cs @@ -55,7 +55,7 @@ namespace Company.WebApplication1 services.AddAuthentication() .AddIdentityServerJwt(); #endif - services.AddMvc() + services.AddMvc(options => options.EnableEndpointRouting = false) .AddNewtonsoftJson(); // In production, the React files will be served from this directory diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs index 1ec2eb2027..f0e7cf2f43 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/ReactRedux-CSharp/Startup.cs @@ -23,7 +23,7 @@ namespace Company.WebApplication1 // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddMvc() + services.AddMvc(options => options.EnableEndpointRouting = false) .AddNewtonsoftJson(); // In production, the React files will be served from this directory diff --git a/src/Security/samples/ClaimsTransformation/Startup.cs b/src/Security/samples/ClaimsTransformation/Startup.cs index 99145e2baf..039148e520 100644 --- a/src/Security/samples/ClaimsTransformation/Startup.cs +++ b/src/Security/samples/ClaimsTransformation/Startup.cs @@ -48,14 +48,16 @@ namespace AuthSamples.ClaimsTransformer app.UseStaticFiles(); - // Must go before UseMvc - app.UseAuthentication(); + app.UseRouting(); - app.UseMvc(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( + endpoints.MapControllerRoute( name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + pattern: "{controller=Home}/{action=Index}/{id?}"); }); } } diff --git a/src/Security/samples/Cookies/Startup.cs b/src/Security/samples/Cookies/Startup.cs index 536ddfb716..c0d2fc0fc9 100644 --- a/src/Security/samples/Cookies/Startup.cs +++ b/src/Security/samples/Cookies/Startup.cs @@ -55,14 +55,14 @@ namespace AuthSamples.Cookies app.UseStaticFiles(); - // Must go before UseMvc - app.UseAuthentication(); + app.UseRouting(); - app.UseMvc(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapDefaultControllerRoute(); }); } } diff --git a/src/Security/samples/CustomPolicyProvider/Startup.cs b/src/Security/samples/CustomPolicyProvider/Startup.cs index 9aaebd2770..f09ba6fb89 100644 --- a/src/Security/samples/CustomPolicyProvider/Startup.cs +++ b/src/Security/samples/CustomPolicyProvider/Startup.cs @@ -21,7 +21,7 @@ namespace CustomPolicyProvider services.AddMvc(); - // Add cookie authentication so that it's possible to sign-in to test the + // Add cookie authentication so that it's possible to sign-in to test the // custom authorization policy behavior of the sample services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => @@ -33,13 +33,14 @@ namespace CustomPolicyProvider public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { - app.UseAuthentication(); + app.UseRouting(); - app.UseMvc(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}"); + endpoints.MapDefaultControllerRoute(); }); } } diff --git a/src/Security/samples/DynamicSchemes/Startup.cs b/src/Security/samples/DynamicSchemes/Startup.cs index f0cb216969..8eaac7cd15 100644 --- a/src/Security/samples/DynamicSchemes/Startup.cs +++ b/src/Security/samples/DynamicSchemes/Startup.cs @@ -42,11 +42,15 @@ namespace AuthSamples.DynamicSchemes app.UseStaticFiles(); - app.UseMvc(routes => + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller}/{action=Index}/{id?}"); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } } diff --git a/src/Security/samples/Identity.ExternalClaims/Pages/MyClaims.cshtml b/src/Security/samples/Identity.ExternalClaims/Pages/MyClaims.cshtml index cfa36c4178..1c23c044c7 100644 --- a/src/Security/samples/Identity.ExternalClaims/Pages/MyClaims.cshtml +++ b/src/Security/samples/Identity.ExternalClaims/Pages/MyClaims.cshtml @@ -1,4 +1,4 @@ -@page +@page @using Microsoft.AspNetCore.Authentication; @model MyClaimsModel @{ @@ -16,11 +16,21 @@

AuthenticationProperties

+@{ + var authenticateResult = await HttpContext.AuthenticateAsync(); +} -
- @foreach (var prop in (await HttpContext.AuthenticateAsync()).Properties.Items) - { -
@prop.Key
-
@prop.Value
- } -
+@if (authenticateResult.Succeeded) +{ +
+ @foreach (var prop in authenticateResult.Properties.Items) + { +
@prop.Key
+
@prop.Value
+ } +
+} +else +{ +

Not Authenticated!

+} diff --git a/src/Security/samples/Identity.ExternalClaims/Startup.cs b/src/Security/samples/Identity.ExternalClaims/Startup.cs index 3608e0f35e..68ea7bab3c 100644 --- a/src/Security/samples/Identity.ExternalClaims/Startup.cs +++ b/src/Security/samples/Identity.ExternalClaims/Startup.cs @@ -83,11 +83,15 @@ namespace Identity.ExternalClaims app.UseAuthentication(); - app.UseMvc(routes => + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller}/{action=Index}/{id?}"); + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); }); } } diff --git a/src/Security/samples/PathSchemeSelection/Startup.cs b/src/Security/samples/PathSchemeSelection/Startup.cs index 0687586327..adffca9a97 100644 --- a/src/Security/samples/PathSchemeSelection/Startup.cs +++ b/src/Security/samples/PathSchemeSelection/Startup.cs @@ -74,17 +74,19 @@ namespace AuthSamples.PathSchemeSelection app.UseStaticFiles(); - // Must go before UseMvc - app.UseAuthentication(); + app.UseRouting(); - app.UseMvc(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( + endpoints.MapControllerRoute( name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); - routes.MapRoute( + pattern: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapControllerRoute( name: "api", - template: "api/{controller=Home}/{action=Index}/{id?}"); + pattern: "api/{controller=Home}/{action=Index}/{id?}"); }); } } diff --git a/src/Security/samples/StaticFilesAuth/Startup.cs b/src/Security/samples/StaticFilesAuth/Startup.cs index 027629f64f..737dca18fc 100644 --- a/src/Security/samples/StaticFilesAuth/Startup.cs +++ b/src/Security/samples/StaticFilesAuth/Startup.cs @@ -107,11 +107,14 @@ namespace StaticFilesAuth SetupFileServer(branch, files); }); - app.UseMvc(routes => + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/Security/test/AuthSamples.FunctionalTests/IdentityExternalClaimsTests.cs b/src/Security/test/AuthSamples.FunctionalTests/IdentityExternalClaimsTests.cs index e91874ac06..955a911486 100644 --- a/src/Security/test/AuthSamples.FunctionalTests/IdentityExternalClaimsTests.cs +++ b/src/Security/test/AuthSamples.FunctionalTests/IdentityExternalClaimsTests.cs @@ -29,7 +29,7 @@ namespace AuthSamples.FunctionalTests Assert.Equal(HttpStatusCode.OK, response.StatusCode); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/8387")] public async Task MyClaimsRedirectsToLoginPageWhenNotLoggedIn() { // Arrange & Act diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs index 13231ced52..1d7dbd6718 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs @@ -53,25 +53,28 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public void Configure(IApplicationBuilder app) { - app.UseAuthentication(); + app.UseRouting(); - app.UseRouting(routes => + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapHub("/default"); - routes.MapHub("/dynamic"); - routes.MapHub("/hubT"); - routes.MapHub("/authorizedhub"); - routes.MapHub("/authorizedhub2") + endpoints.MapHub("/default"); + endpoints.MapHub("/dynamic"); + endpoints.MapHub("/hubT"); + endpoints.MapHub("/authorizedhub"); + endpoints.MapHub("/authorizedhub2") .RequireAuthorization(new AuthorizeAttribute(JwtBearerDefaults.AuthenticationScheme)); - routes.MapHub("/default-nowebsockets", options => options.Transports = HttpTransportType.LongPolling | HttpTransportType.ServerSentEvents); + endpoints.MapHub("/default-nowebsockets", options => options.Transports = HttpTransportType.LongPolling | HttpTransportType.ServerSentEvents); - routes.MapGet("/generateJwtToken", context => + endpoints.MapGet("/generateJwtToken", context => { return context.Response.WriteAsync(GenerateJwtToken()); }); - routes.Map("/redirect/{*anything}", context => + endpoints.Map("/redirect/{*anything}", context => { return context.Response.WriteAsync(JsonConvert.SerializeObject(new { @@ -80,8 +83,6 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests })); }); }); - - app.UseAuthorization(); } private string GenerateJwtToken() diff --git a/src/SignalR/clients/ts/FunctionalTests/Startup.cs b/src/SignalR/clients/ts/FunctionalTests/Startup.cs index f95a19471a..4704c9d785 100644 --- a/src/SignalR/clients/ts/FunctionalTests/Startup.cs +++ b/src/SignalR/clients/ts/FunctionalTests/Startup.cs @@ -124,21 +124,34 @@ namespace FunctionalTests return next.Invoke(); }); - app.UseRouting(routes => + app.UseRouting(); + + app.Use(async (context, next) => { - routes.MapHub("/testhub"); - routes.MapHub("/testhub-nowebsockets", options => options.Transports = HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling); - routes.MapHub("/uncreatable"); - routes.MapHub("/authorizedhub"); + if (context.Request.Path.Value.Contains("/negotiate")) + { + context.Response.Cookies.Append("testCookie", "testValue"); + context.Response.Cookies.Append("testCookie2", "testValue2"); + context.Response.Cookies.Append("expiredCookie", "doesntmatter", new CookieOptions() { Expires = DateTimeOffset.Now.AddHours(-1) }); + } + await next.Invoke(); + }); - routes.MapConnectionHandler("/echo"); + app.UseEndpoints(endpoints => + { + endpoints.MapHub("/testhub"); + endpoints.MapHub("/testhub-nowebsockets", options => options.Transports = HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling); + endpoints.MapHub("/uncreatable"); + endpoints.MapHub("/authorizedhub"); - routes.MapGet("/generateJwtToken", context => + endpoints.MapConnectionHandler("/echo"); + + endpoints.MapGet("/generateJwtToken", context => { return context.Response.WriteAsync(GenerateJwtToken()); }); - routes.MapGet("/deployment", context => + endpoints.MapGet("/deployment", context => { var attributes = Assembly.GetAssembly(typeof(Startup)).GetCustomAttributes(); @@ -170,17 +183,6 @@ namespace FunctionalTests return Task.CompletedTask; }); }); - - app.Use(async (context, next) => - { - if (context.Request.Path.Value.Contains("/negotiate")) - { - context.Response.Cookies.Append("testCookie", "testValue"); - context.Response.Cookies.Append("testCookie2", "testValue2"); - context.Response.Cookies.Append("expiredCookie", "doesntmatter", new CookieOptions() { Expires = DateTimeOffset.Now.AddHours(-1) }); - } - await next.Invoke(); - }); } private string GenerateJwtToken() diff --git a/src/SignalR/common/Http.Connections/ref/Microsoft.AspNetCore.Http.Connections.netcoreapp3.0.cs b/src/SignalR/common/Http.Connections/ref/Microsoft.AspNetCore.Http.Connections.netcoreapp3.0.cs index 2aefc48b03..9b9db9128c 100644 --- a/src/SignalR/common/Http.Connections/ref/Microsoft.AspNetCore.Http.Connections.netcoreapp3.0.cs +++ b/src/SignalR/common/Http.Connections/ref/Microsoft.AspNetCore.Http.Connections.netcoreapp3.0.cs @@ -5,10 +5,10 @@ namespace Microsoft.AspNetCore.Builder { public static partial class ConnectionEndpointRouteBuilderExtensions { - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapConnectionHandler(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern) where TConnectionHandler : Microsoft.AspNetCore.Connections.ConnectionHandler { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapConnectionHandler(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, System.Action configureOptions) where TConnectionHandler : Microsoft.AspNetCore.Connections.ConnectionHandler { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapConnections(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions options, System.Action configure) { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapConnections(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, System.Action configure) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapConnectionHandler(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern) where TConnectionHandler : Microsoft.AspNetCore.Connections.ConnectionHandler { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapConnectionHandler(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Action configureOptions) where TConnectionHandler : Microsoft.AspNetCore.Connections.ConnectionHandler { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapConnections(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions options, System.Action configure) { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapConnections(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Action configure) { throw null; } } public static partial class ConnectionsAppBuilderExtensions { diff --git a/src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs b/src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs index 06af119fad..1fd4f7ca23 100644 --- a/src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs +++ b/src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs @@ -18,34 +18,34 @@ namespace Microsoft.AspNetCore.Builder /// /// Maps incoming requests with the specified path to the provided connection pipeline. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// A callback to configure the connection. /// An for endpoints associated with the connections. - public static IEndpointConventionBuilder MapConnections(this IEndpointRouteBuilder routes, string pattern, Action configure) => - routes.MapConnections(pattern, new HttpConnectionDispatcherOptions(), configure); + public static IEndpointConventionBuilder MapConnections(this IEndpointRouteBuilder endpoints, string pattern, Action configure) => + endpoints.MapConnections(pattern, new HttpConnectionDispatcherOptions(), configure); /// /// Maps incoming requests with the specified path to the provided connection pipeline. /// /// The type. - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// An for endpoints associated with the connections. - public static IEndpointConventionBuilder MapConnectionHandler(this IEndpointRouteBuilder routes, string pattern) where TConnectionHandler : ConnectionHandler + public static IEndpointConventionBuilder MapConnectionHandler(this IEndpointRouteBuilder endpoints, string pattern) where TConnectionHandler : ConnectionHandler { - return routes.MapConnectionHandler(pattern, configureOptions: null); + return endpoints.MapConnectionHandler(pattern, configureOptions: null); } /// /// Maps incoming requests with the specified path to the provided connection pipeline. /// /// The type. - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// A callback to configure dispatcher options. /// An for endpoints associated with the connections. - public static IEndpointConventionBuilder MapConnectionHandler(this IEndpointRouteBuilder routes, string pattern, Action configureOptions) where TConnectionHandler : ConnectionHandler + public static IEndpointConventionBuilder MapConnectionHandler(this IEndpointRouteBuilder endpoints, string pattern, Action configureOptions) where TConnectionHandler : ConnectionHandler { var options = new HttpConnectionDispatcherOptions(); // REVIEW: WE should consider removing this and instead just relying on the @@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Builder } configureOptions?.Invoke(options); - var conventionBuilder = routes.MapConnections(pattern, options, b => + var conventionBuilder = endpoints.MapConnections(pattern, options, b => { b.UseConnectionHandler(); }); @@ -79,16 +79,16 @@ namespace Microsoft.AspNetCore.Builder /// /// Maps incoming requests with the specified path to the provided connection pipeline. /// - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// Options used to configure the connection. /// A callback to configure the connection. /// An for endpoints associated with the connections. - public static IEndpointConventionBuilder MapConnections(this IEndpointRouteBuilder routes, string pattern, HttpConnectionDispatcherOptions options, Action configure) + public static IEndpointConventionBuilder MapConnections(this IEndpointRouteBuilder endpoints, string pattern, HttpConnectionDispatcherOptions options, Action configure) { - var dispatcher = routes.ServiceProvider.GetRequiredService(); + var dispatcher = endpoints.ServiceProvider.GetRequiredService(); - var connectionBuilder = new ConnectionBuilder(routes.ServiceProvider); + var connectionBuilder = new ConnectionBuilder(endpoints.ServiceProvider); configure(connectionBuilder); var connectionDelegate = connectionBuilder.Build(); @@ -98,21 +98,21 @@ namespace Microsoft.AspNetCore.Builder var conventionBuilders = new List(); // Build the negotiate application - var app = routes.CreateApplicationBuilder(); + var app = endpoints.CreateApplicationBuilder(); app.UseWebSockets(); app.Run(c => dispatcher.ExecuteNegotiateAsync(c, options)); var negotiateHandler = app.Build(); - var negotiateBuilder = routes.Map(pattern + "/negotiate", negotiateHandler); + var negotiateBuilder = endpoints.Map(pattern + "/negotiate", negotiateHandler); conventionBuilders.Add(negotiateBuilder); // build the execute handler part of the protocol - app = routes.CreateApplicationBuilder(); + app = endpoints.CreateApplicationBuilder(); app.UseWebSockets(); app.Run(c => dispatcher.ExecuteAsync(c, options, connectionDelegate)); var executehandler = app.Build(); - var executeBuilder = routes.Map(pattern, executehandler); + var executeBuilder = endpoints.Map(pattern, executehandler); conventionBuilders.Add(executeBuilder); var compositeConventionBuilder = new CompositeEndpointConventionBuilder(conventionBuilders); diff --git a/src/SignalR/samples/JwtSample/Startup.cs b/src/SignalR/samples/JwtSample/Startup.cs index a29e43816f..ac926f07a0 100644 --- a/src/SignalR/samples/JwtSample/Startup.cs +++ b/src/SignalR/samples/JwtSample/Startup.cs @@ -67,10 +67,12 @@ namespace JwtSample { app.UseFileServer(); - app.UseRouting(routes => + app.UseRouting(); + + app.UseEndpoints(endpoints => { - routes.MapHub("/broadcast"); - routes.MapGet("/generatetoken", context => + endpoints.MapHub("/broadcast"); + endpoints.MapGet("/generatetoken", context => { return context.Response.WriteAsync(GenerateToken(context)); }); diff --git a/src/SignalR/samples/SignalRSamples/Startup.cs b/src/SignalR/samples/SignalRSamples/Startup.cs index 9608eb89d7..ba8cf35786 100644 --- a/src/SignalR/samples/SignalRSamples/Startup.cs +++ b/src/SignalR/samples/SignalRSamples/Startup.cs @@ -43,17 +43,21 @@ namespace SignalRSamples app.UseDeveloperExceptionPage(); } - app.UseRouting(routes => + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { - routes.MapHub("/dynamic"); - routes.MapHub("/default"); - routes.MapHub("/streaming"); - routes.MapHub("/uploading"); - routes.MapHub("/hubT"); + endpoints.MapHub("/dynamic"); + endpoints.MapHub("/default"); + endpoints.MapHub("/streaming"); + endpoints.MapHub("/uploading"); + endpoints.MapHub("/hubT"); - routes.MapConnectionHandler("/chat"); + endpoints.MapConnectionHandler("/chat"); - routes.MapGet("/deployment", context => + endpoints.MapGet("/deployment", context => { var attributes = Assembly.GetAssembly(typeof(Startup)).GetCustomAttributes(); @@ -85,8 +89,6 @@ namespace SignalRSamples return Task.CompletedTask; }); }); - - app.UseAuthorization(); } } } diff --git a/src/SignalR/samples/SocialWeather/Startup.cs b/src/SignalR/samples/SocialWeather/Startup.cs index 0199a6c16f..594c5d178e 100644 --- a/src/SignalR/samples/SocialWeather/Startup.cs +++ b/src/SignalR/samples/SocialWeather/Startup.cs @@ -34,9 +34,11 @@ namespace SocialWeather app.UseFileServer(); - app.UseRouting(routes => + app.UseRouting(); + + app.UseEndpoints(endpoints => { - routes.MapConnectionHandler("/weather"); + endpoints.MapConnectionHandler("/weather"); }); var formatterResolver = app.ApplicationServices.GetRequiredService(); diff --git a/src/SignalR/server/SignalR/ref/Microsoft.AspNetCore.SignalR.netcoreapp3.0.cs b/src/SignalR/server/SignalR/ref/Microsoft.AspNetCore.SignalR.netcoreapp3.0.cs index fc4907a263..f2504a0e22 100644 --- a/src/SignalR/server/SignalR/ref/Microsoft.AspNetCore.SignalR.netcoreapp3.0.cs +++ b/src/SignalR/server/SignalR/ref/Microsoft.AspNetCore.SignalR.netcoreapp3.0.cs @@ -5,8 +5,8 @@ namespace Microsoft.AspNetCore.Builder { public static partial class HubEndpointRouteBuilderExtensions { - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern) where THub : Microsoft.AspNetCore.SignalR.Hub { throw null; } - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder routes, string pattern, System.Action configureOptions) where THub : Microsoft.AspNetCore.SignalR.Hub { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern) where THub : Microsoft.AspNetCore.SignalR.Hub { throw null; } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Action configureOptions) where THub : Microsoft.AspNetCore.SignalR.Hub { throw null; } } public static partial class SignalRAppBuilderExtensions { diff --git a/src/SignalR/server/SignalR/src/HubEndpointRouteBuilderExtensions.cs b/src/SignalR/server/SignalR/src/HubEndpointRouteBuilderExtensions.cs index fd392179d1..42414b791a 100644 --- a/src/SignalR/server/SignalR/src/HubEndpointRouteBuilderExtensions.cs +++ b/src/SignalR/server/SignalR/src/HubEndpointRouteBuilderExtensions.cs @@ -17,25 +17,25 @@ namespace Microsoft.AspNetCore.Builder /// Maps incoming requests with the specified path to the specified type. /// /// The type to map requests to. - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// An for endpoints associated with the connections. - public static IEndpointConventionBuilder MapHub(this IEndpointRouteBuilder routes, string pattern) where THub : Hub + public static IEndpointConventionBuilder MapHub(this IEndpointRouteBuilder endpoints, string pattern) where THub : Hub { - return routes.MapHub(pattern, configureOptions: null); + return endpoints.MapHub(pattern, configureOptions: null); } /// /// Maps incoming requests with the specified path to the specified type. /// /// The type to map requests to. - /// The to add the route to. + /// The to add the route to. /// The route pattern. /// A callback to configure dispatcher options. /// An for endpoints associated with the connections. - public static IEndpointConventionBuilder MapHub(this IEndpointRouteBuilder routes, string pattern, Action configureOptions) where THub : Hub + public static IEndpointConventionBuilder MapHub(this IEndpointRouteBuilder endpoints, string pattern, Action configureOptions) where THub : Hub { - var marker = routes.ServiceProvider.GetService(); + var marker = endpoints.ServiceProvider.GetService(); if (marker == null) { @@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Builder configureOptions?.Invoke(options); - var conventionBuilder = routes.MapConnections(pattern, options, b => + var conventionBuilder = endpoints.MapConnections(pattern, options, b => { b.UseHub(); }); diff --git a/src/SignalR/server/SignalR/test/MapSignalRTests.cs b/src/SignalR/server/SignalR/test/MapSignalRTests.cs index a15293d545..84e85957c5 100644 --- a/src/SignalR/server/SignalR/test/MapSignalRTests.cs +++ b/src/SignalR/server/SignalR/test/MapSignalRTests.cs @@ -78,9 +78,10 @@ namespace Microsoft.AspNetCore.SignalR.Tests var ex = Assert.Throws(() => { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapHub("/overloads"); + endpoints.MapHub("/overloads"); }); }); @@ -166,10 +167,10 @@ namespace Microsoft.AspNetCore.SignalR.Tests [Fact] public void MapHubEndPointRoutingAppliesAttributesBeforeConventions() { - void ConfigureRoutes(IEndpointRouteBuilder routes) + void ConfigureRoutes(IEndpointRouteBuilder endpoints) { // This "Foo" policy should override the default auth attribute - routes.MapHub("/path") + endpoints.MapHub("/path") .RequireAuthorization(new AuthorizeAttribute("Foo")); } @@ -188,10 +189,10 @@ namespace Microsoft.AspNetCore.SignalR.Tests [Fact] public void MapHubEndPointRoutingAppliesHubMetadata() { - void ConfigureRoutes(IEndpointRouteBuilder routes) + void ConfigureRoutes(IEndpointRouteBuilder endpoints) { // This "Foo" policy should override the default auth attribute - routes.MapHub("/path"); + endpoints.MapHub("/path"); } using (var host = BuildWebHostWithEndPointRouting(ConfigureRoutes)) @@ -241,7 +242,8 @@ namespace Microsoft.AspNetCore.SignalR.Tests }) .Configure(app => { - app.UseRouting(routes => configure(routes)); + app.UseRouting(); + app.UseEndpoints(endpoints => configure(endpoints)); }) .UseUrls("http://127.0.0.1:0") .Build(); diff --git a/src/SignalR/server/SignalR/test/Startup.cs b/src/SignalR/server/SignalR/test/Startup.cs index 471449fea0..dff6265075 100644 --- a/src/SignalR/server/SignalR/test/Startup.cs +++ b/src/SignalR/server/SignalR/test/Startup.cs @@ -29,14 +29,15 @@ namespace Microsoft.AspNetCore.SignalR.Tests public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapHub("/uncreatable"); + endpoints.MapHub("/uncreatable"); - routes.MapConnectionHandler("/echo"); - routes.MapConnectionHandler("/echoAndClose"); - routes.MapConnectionHandler("/httpheader"); - routes.MapConnectionHandler("/auth"); + endpoints.MapConnectionHandler("/echo"); + endpoints.MapConnectionHandler("/echoAndClose"); + endpoints.MapConnectionHandler("/httpheader"); + endpoints.MapConnectionHandler("/auth"); }); } } diff --git a/src/SignalR/server/StackExchangeRedis/test/Startup.cs b/src/SignalR/server/StackExchangeRedis/test/Startup.cs index fc49a8741e..298956ba8e 100644 --- a/src/SignalR/server/StackExchangeRedis/test/Startup.cs +++ b/src/SignalR/server/StackExchangeRedis/test/Startup.cs @@ -29,9 +29,10 @@ namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests public void Configure(IApplicationBuilder app) { - app.UseRouting(routes => + app.UseRouting(); + app.UseEndpoints(endpoints => { - routes.MapHub("/echo"); + endpoints.MapHub("/echo"); }); }