From 57ec8b0f04238f34d04daaceb90b2bbbddf7205c Mon Sep 17 00:00:00 2001 From: jacalvar Date: Mon, 11 Jul 2016 17:27:39 -0700 Subject: [PATCH] [Fixes #228] Update sample app to show more common routing patterns and add functional tests for it. --- Routing.sln | 17 ++++- global.json | 2 +- samples/RoutingSample.Web/Startup.cs | 49 ++++--------- ...t.AspNetCore.Routing.FunctionalTests.xproj | 22 ++++++ .../RoutingSampleTest.cs | 72 +++++++++++++++++++ .../RoutingTestFixture.cs | 34 +++++++++ .../project.json | 28 ++++++++ 7 files changed, 187 insertions(+), 37 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.xproj create mode 100644 test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingSampleTest.cs create mode 100644 test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingTestFixture.cs create mode 100644 test/Microsoft.AspNetCore.Routing.FunctionalTests/project.json diff --git a/Routing.sln b/Routing.sln index 4c8664b5b9..e26ce955b4 100644 --- a/Routing.sln +++ b/Routing.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25029.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0E966C37-7334-4D96-AAF6-9F49FBD166E3}" EndProject @@ -27,6 +27,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Routin EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests", "test\Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests\Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests.xproj", "{741B0B05-CE96-473B-B962-6B0A347DF79A}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Routing.FunctionalTests", "test\Microsoft.AspNetCore.Routing.FunctionalTests\Microsoft.AspNetCore.Routing.FunctionalTests.xproj", "{5C73140B-41F3-466F-A07B-3614E4D80DF9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -114,6 +116,18 @@ Global {741B0B05-CE96-473B-B962-6B0A347DF79A}.Release|Mixed Platforms.Build.0 = Release|Any CPU {741B0B05-CE96-473B-B962-6B0A347DF79A}.Release|x86.ActiveCfg = Release|Any CPU {741B0B05-CE96-473B-B962-6B0A347DF79A}.Release|x86.Build.0 = Release|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Debug|x86.ActiveCfg = Debug|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Debug|x86.Build.0 = Debug|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Release|Any CPU.Build.0 = Release|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Release|x86.ActiveCfg = Release|Any CPU + {5C73140B-41F3-466F-A07B-3614E4D80DF9}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -126,5 +140,6 @@ Global {09C2933C-23AC-41B7-994D-E8A5184A629C} = {95359B4B-4C85-4B44-A75B-0621905C4CF6} {ED253B01-24F1-43D1-AA0B-079391E105A9} = {0E966C37-7334-4D96-AAF6-9F49FBD166E3} {741B0B05-CE96-473B-B962-6B0A347DF79A} = {95359B4B-4C85-4B44-A75B-0621905C4CF6} + {5C73140B-41F3-466F-A07B-3614E4D80DF9} = {95359B4B-4C85-4B44-A75B-0621905C4CF6} EndGlobalSection EndGlobal diff --git a/global.json b/global.json index 983ba0401e..5fbf613f8e 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,3 @@ { - "projects": ["src"] + "projects": [ "src", "samples" ] } diff --git a/samples/RoutingSample.Web/Startup.cs b/samples/RoutingSample.Web/Startup.cs index ff029f8ed1..9e00ee296e 100644 --- a/samples/RoutingSample.Web/Startup.cs +++ b/samples/RoutingSample.Web/Startup.cs @@ -2,11 +2,13 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Globalization; +using System.Text.RegularExpressions; using System.Threading; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Constraints; using Microsoft.Extensions.DependencyInjection; namespace RoutingSample.Web @@ -20,46 +22,23 @@ namespace RoutingSample.Web public void Configure(IApplicationBuilder app) { - var endpoint1 = new RouteHandler((c) => + app.UseRouter(routes => { - return c.Response.WriteAsync($"match1, route values - {string.Join(", ", c.GetRouteData().Values)}"); - }); - - var endpoint2 = new RouteHandler((c) => c.Response.WriteAsync("Hello, World!")); - - var routeBuilder = new RouteBuilder(app) - { - DefaultHandler = endpoint1, - }; - - routeBuilder.MapRoute("api/status/{item}", c => c.Response.WriteAsync($"{c.GetRouteValue("item")} is just fine.")); - routeBuilder.MapRoute("localized/{lang=en-US}", b => - { - b.Use(next => async (c) => + routes.DefaultHandler = new RouteHandler((c) => { - var culture = new CultureInfo((string)c.GetRouteValue("lang")); -#if NET451 - Thread.CurrentThread.CurrentCulture = culture; - Thread.CurrentThread.CurrentUICulture = culture; -#else - CultureInfo.CurrentCulture = culture; - CultureInfo.CurrentUICulture = culture; -#endif - await next(c); + return c.Response.WriteAsync($"Verb = {c.Request.Method.ToUpperInvariant()} - Path = {c.Request.Path} - Route values - {string.Join(", ", c.GetRouteData().Values)}"); }); - b.Run(c => c.Response.WriteAsync($"What would you do with {1000000m:C}?")); + routes.MapGet("api/get/{id}", (c) => c.Response.WriteAsync($"API Get {c.GetRouteData().Values["id"]}")); + + routes.MapRoute("api/middleware", (IApplicationBuilder fork) => fork.Use((c, n) => c.Response.WriteAsync("Middleware!"))); + + routes.MapRoute( + name: "AllVerbs", + template: "api/all/{name}/{lastName?}", + defaults: new { lastName = "Doe" }, + constraints: new { lastName = new RegexRouteConstraint(new Regex("[a-zA-Z]{3}")) }); }); - - routeBuilder.AddPrefixRoute("api/store", endpoint1); - routeBuilder.AddPrefixRoute("hello/world", endpoint2); - - routeBuilder.MapLocaleRoute("en-US", "store/US/{action}", new { controller = "Store" }); - routeBuilder.MapLocaleRoute("en-GB", "store/UK/{action}", new { controller = "Store" }); - - routeBuilder.AddPrefixRoute("", endpoint2); - - app.UseRouter(routeBuilder.Build()); } public static void Main(string[] args) diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.xproj b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.xproj new file mode 100644 index 0000000000..db34da4c9b --- /dev/null +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.xproj @@ -0,0 +1,22 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 5c73140b-41f3-466f-a07b-3614e4d80df9 + Microsoft.AspNetCore.Routing.FunctionalTests + .\obj + .\bin\ + v4.5.2 + + + 2.0 + + + + + + diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingSampleTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingSampleTest.cs new file mode 100644 index 0000000000..f0322f4d3d --- /dev/null +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingSampleTest.cs @@ -0,0 +1,72 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.AspNetCore.Routing.FunctionalTests +{ + public class RoutingSampleTest : IClassFixture> + { + public RoutingSampleTest(RoutingTestFixture fixture) + { + Client = fixture.Client; + } + + public HttpClient Client { get; } + + [Fact] + public async Task Routing_CanRouteRequestDelegate_ToSpecificHttpVerb() + { + // Arrange + var message = new HttpRequestMessage(HttpMethod.Get, "api/get/5"); + + // Act + var response = await Client.SendAsync(message); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal($"API Get 5", await response.Content.ReadAsStringAsync()); + } + + [Fact] + public async Task Routing_CanRouteRequest_ToSpecificMiddleware() + { + // Arrange + var message = new HttpRequestMessage(HttpMethod.Get, "api/middleware"); + + // Act + var response = await Client.SendAsync(message); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal($"Middleware!", await response.Content.ReadAsStringAsync()); + } + + [Theory] + [InlineData("GET")] + [InlineData("POST")] + [InlineData("PUT")] + [InlineData("PATCH")] + [InlineData("DELETE")] + [InlineData("HEAD")] + [InlineData("OPTIONS")] + public async Task Routing_CanRouteRequest_ToDefaultHandler(string httpVerb) + { + // Arrange + var message = new HttpRequestMessage(new HttpMethod(httpVerb), "api/all/Joe/Duf"); + var expectedBody = $"Verb = {httpVerb} - Path = /api/all/Joe/Duf - Route values - [name, Joe], [lastName, Duf]"; + + // Act + var response = await Client.SendAsync(message); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var body = await response.Content.ReadAsStringAsync(); + Assert.Equal(expectedBody, body); + } + } +} diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingTestFixture.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingTestFixture.cs new file mode 100644 index 0000000000..1ced141956 --- /dev/null +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/RoutingTestFixture.cs @@ -0,0 +1,34 @@ +// 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.Net.Http; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; + +namespace Microsoft.AspNetCore.Routing.FunctionalTests +{ + public class RoutingTestFixture : IDisposable + { + private readonly TestServer _server; + + public RoutingTestFixture() + { + var builder = new WebHostBuilder() + .UseStartup(typeof(TStartup)); + + _server = new TestServer(builder); + + Client = _server.CreateClient(); + Client.BaseAddress = new Uri("http://localhost"); + } + + public HttpClient Client { get; } + + public void Dispose() + { + Client.Dispose(); + _server.Dispose(); + } + } +} diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/project.json b/test/Microsoft.AspNetCore.Routing.FunctionalTests/project.json new file mode 100644 index 0000000000..8b044658f0 --- /dev/null +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/project.json @@ -0,0 +1,28 @@ +{ + "buildOptions": { + "warningsAsErrors": true + }, + "dependencies": { + "dotnet-test-xunit": "2.2.0-*", + "Microsoft.AspNetCore.Routing": "1.1.0-*", + "Microsoft.AspNetCore.TestHost": "1.1.0-*", + "Microsoft.AspNetCore.Testing": "1.1.0-*", + "Moq": "4.6.25-*", + "RoutingSample.Web": "1.0.0-*", + "xunit": "2.2.0-*" + }, + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0-*", + "type": "platform" + }, + "System.Diagnostics.TraceSource": "4.0.0-*" + }, + "imports": "dotnet5.4" + }, + "net451": {} + }, + "testRunner": "xunit" +}