From 6a44aca6a204055ed9f18a7ed19634f85d4994db Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Tue, 15 Jan 2019 08:09:27 -0800 Subject: [PATCH] React to WebHostBuilderFactory changes (#6460) --- build/artifacts.props | 3 - build/repo.props | 4 - eng/Dependencies.props | 1 + src/Hosting/Hosting.sln | 27 ---- .../src/GenericHost/GenericWebHostBuilder.cs | 7 +- .../src/Microsoft.AspNetCore.TestHost.csproj | 7 +- src/Hosting/TestHost/src/TestServer.cs | 2 +- .../TestHost/src/WebHostBuilderExtensions.cs | 16 +- .../TestHost/src/WebHostBuilderFactory.cs | 15 +- ...Hosting.WebHostBuilderFactory.Tests.csproj | 22 --- .../WebHostFactoryResolverTests.cs | 84 ----------- .../BuildWebHostInvalidSignature.csproj | 14 -- .../BuildWebHostInvalidSignature/Program.cs | 16 -- .../BuildWebHostInvalidSignature/Startup.cs | 19 --- .../BuildWebHostPatternTestSite.csproj | 14 -- .../BuildWebHostPatternTestSite/Program.cs | 16 -- .../BuildWebHostPatternTestSite/Startup.cs | 19 --- ...reateWebHostBuilderInvalidSignature.csproj | 14 -- .../Program.cs | 16 -- .../Startup.cs | 19 --- src/Mvc/Mvc.sln | 15 ++ .../Microsoft.AspNetCore.Mvc.Testing.csproj | 5 +- .../Properties/Resources.Designer.cs | 12 +- .../Resources.resx | 4 +- .../WebApplicationFactory.cs | 85 ++++++++++- .../Infrastructure/MvcTestFixture.cs | 18 +++ ...soft.AspNetCore.Mvc.FunctionalTests.csproj | 1 + .../TestingInfrastructureInheritanceTests.cs | 38 ++++- .../TestingInfrastructureTests.cs | 20 +++ .../WebSites/BasicWebSite/BasicWebSite.csproj | 10 +- src/Mvc/test/WebSites/BasicWebSite/Program.cs | 1 - src/Mvc/test/WebSites/BasicWebSite/Startup.cs | 2 + .../Controllers/TestingController.cs | 137 ++++++++++++++++++ .../GenericHostWebSite.csproj | 27 ++++ .../WebSites/GenericHostWebSite/Program.cs | 33 +++++ .../WebSites/GenericHostWebSite/Startup.cs | 58 ++++++++ .../WebSites/GenericHostWebSite/_bower.json | 14 ++ .../WebSites/GenericHostWebSite/_bower.readme | 7 + .../WebSites/GenericHostWebSite/_gruntfile.js | 20 +++ .../WebSites/GenericHostWebSite/_package.json | 10 ++ .../WebSites/GenericHostWebSite/readme.md | 4 + .../jquery.validate.unobtrusive.min.js | 5 + .../Directory.Build.props | 8 - .../FactoryResolutionResult.cs | 54 ------- .../FactoryResolutionResultKind.cs | 14 -- .../WebHostFactoryResolver.cs | 68 --------- 46 files changed, 527 insertions(+), 478 deletions(-) delete mode 100644 src/Hosting/test/WebHostBuilderFactory.Tests/Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Tests.csproj delete mode 100644 src/Hosting/test/WebHostBuilderFactory.Tests/WebHostFactoryResolverTests.cs delete mode 100644 src/Hosting/test/testassets/BuildWebHostInvalidSignature/BuildWebHostInvalidSignature.csproj delete mode 100644 src/Hosting/test/testassets/BuildWebHostInvalidSignature/Program.cs delete mode 100644 src/Hosting/test/testassets/BuildWebHostInvalidSignature/Startup.cs delete mode 100644 src/Hosting/test/testassets/BuildWebHostPatternTestSite/BuildWebHostPatternTestSite.csproj delete mode 100644 src/Hosting/test/testassets/BuildWebHostPatternTestSite/Program.cs delete mode 100644 src/Hosting/test/testassets/BuildWebHostPatternTestSite/Startup.cs delete mode 100644 src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/CreateWebHostBuilderInvalidSignature.csproj delete mode 100644 src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/Program.cs delete mode 100644 src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/Startup.cs create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/Controllers/TestingController.cs create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/GenericHostWebSite.csproj create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/Program.cs create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/Startup.cs create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/_bower.json create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/_bower.readme create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/_gruntfile.js create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/_package.json create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/readme.md create mode 100644 src/Mvc/test/WebSites/GenericHostWebSite/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js delete mode 100644 src/Shared/Hosting.WebHostBuilderFactory/Directory.Build.props delete mode 100644 src/Shared/Hosting.WebHostBuilderFactory/FactoryResolutionResult.cs delete mode 100644 src/Shared/Hosting.WebHostBuilderFactory/FactoryResolutionResultKind.cs delete mode 100644 src/Shared/Hosting.WebHostBuilderFactory/WebHostFactoryResolver.cs diff --git a/build/artifacts.props b/build/artifacts.props index 30a75247b2..756194a28b 100644 --- a/build/artifacts.props +++ b/build/artifacts.props @@ -97,9 +97,6 @@ This can be done once #4246 is complete, and done in conjunction with converting - - - diff --git a/build/repo.props b/build/repo.props index 3482b02d5a..f50b7d4f03 100644 --- a/build/repo.props +++ b/build/repo.props @@ -34,10 +34,6 @@ true - - - - diff --git a/eng/Dependencies.props b/eng/Dependencies.props index 09c4c702d6..5bb5c428db 100644 --- a/eng/Dependencies.props +++ b/eng/Dependencies.props @@ -65,6 +65,7 @@ and are generated based on the last package release. + diff --git a/src/Hosting/Hosting.sln b/src/Hosting/Hosting.sln index 7f1103247a..0fad5fbf16 100644 --- a/src/Hosting/Hosting.sln +++ b/src/Hosting/Hosting.sln @@ -29,16 +29,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hostin EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{31587D24-F6B5-4A47-A962-47CA7FEA79D0}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildWebHostInvalidSignature", "test\testassets\BuildWebHostInvalidSignature\BuildWebHostInvalidSignature.csproj", "{BF146375-AA6C-43F3-BF0A-DCA551892DF8}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting.FunctionalTests", "test\FunctionalTests\Microsoft.AspNetCore.Hosting.FunctionalTests.csproj", "{D6EC0A3E-384A-4EE9-8068-21E1848BBB11}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Tests", "test\WebHostBuilderFactory.Tests\Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Tests.csproj", "{4AB4D911-7741-4F3E-982E-7945C6FC36C4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildWebHostPatternTestSite", "test\testassets\BuildWebHostPatternTestSite\BuildWebHostPatternTestSite.csproj", "{953E1E06-F39F-45E7-840D-FA8DE1E01740}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CreateWebHostBuilderInvalidSignature", "test\testassets\CreateWebHostBuilderInvalidSignature\CreateWebHostBuilderInvalidSignature.csproj", "{BE562963-37E1-410F-8751-A3044458B861}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStartupInjectionAssemblyName", "test\testassets\IStartupInjectionAssemblyName\IStartupInjectionAssemblyName.csproj", "{F032B4F6-2F03-4885-AB03-CA81038808A6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting.TestSites", "test\testassets\Microsoft.AspNetCore.Hosting.TestSites\Microsoft.AspNetCore.Hosting.TestSites.csproj", "{9CA19BE4-DC10-4690-9142-61BD007B6D80}" @@ -95,26 +87,10 @@ Global {CCD5D010-7E06-4209-ADD5-3B010A41DCF1}.Debug|Any CPU.Build.0 = Debug|Any CPU {CCD5D010-7E06-4209-ADD5-3B010A41DCF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {CCD5D010-7E06-4209-ADD5-3B010A41DCF1}.Release|Any CPU.Build.0 = Release|Any CPU - {BF146375-AA6C-43F3-BF0A-DCA551892DF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF146375-AA6C-43F3-BF0A-DCA551892DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF146375-AA6C-43F3-BF0A-DCA551892DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BF146375-AA6C-43F3-BF0A-DCA551892DF8}.Release|Any CPU.Build.0 = Release|Any CPU {D6EC0A3E-384A-4EE9-8068-21E1848BBB11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D6EC0A3E-384A-4EE9-8068-21E1848BBB11}.Debug|Any CPU.Build.0 = Debug|Any CPU {D6EC0A3E-384A-4EE9-8068-21E1848BBB11}.Release|Any CPU.ActiveCfg = Release|Any CPU {D6EC0A3E-384A-4EE9-8068-21E1848BBB11}.Release|Any CPU.Build.0 = Release|Any CPU - {4AB4D911-7741-4F3E-982E-7945C6FC36C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4AB4D911-7741-4F3E-982E-7945C6FC36C4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4AB4D911-7741-4F3E-982E-7945C6FC36C4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4AB4D911-7741-4F3E-982E-7945C6FC36C4}.Release|Any CPU.Build.0 = Release|Any CPU - {953E1E06-F39F-45E7-840D-FA8DE1E01740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {953E1E06-F39F-45E7-840D-FA8DE1E01740}.Debug|Any CPU.Build.0 = Debug|Any CPU - {953E1E06-F39F-45E7-840D-FA8DE1E01740}.Release|Any CPU.ActiveCfg = Release|Any CPU - {953E1E06-F39F-45E7-840D-FA8DE1E01740}.Release|Any CPU.Build.0 = Release|Any CPU - {BE562963-37E1-410F-8751-A3044458B861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE562963-37E1-410F-8751-A3044458B861}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE562963-37E1-410F-8751-A3044458B861}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE562963-37E1-410F-8751-A3044458B861}.Release|Any CPU.Build.0 = Release|Any CPU {F032B4F6-2F03-4885-AB03-CA81038808A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F032B4F6-2F03-4885-AB03-CA81038808A6}.Debug|Any CPU.Build.0 = Debug|Any CPU {F032B4F6-2F03-4885-AB03-CA81038808A6}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -134,9 +110,6 @@ Global GlobalSection(NestedProjects) = preSolution {7351DDBC-71DF-4C40-A364-981710B80E29} = {3E9635DD-53A9-4098-B6F6-E5C3C8F7C600} {3C3F4D2D-6676-4A0B-895D-348E7DD4152E} = {3E9635DD-53A9-4098-B6F6-E5C3C8F7C600} - {BF146375-AA6C-43F3-BF0A-DCA551892DF8} = {31587D24-F6B5-4A47-A962-47CA7FEA79D0} - {953E1E06-F39F-45E7-840D-FA8DE1E01740} = {31587D24-F6B5-4A47-A962-47CA7FEA79D0} - {BE562963-37E1-410F-8751-A3044458B861} = {31587D24-F6B5-4A47-A962-47CA7FEA79D0} {F032B4F6-2F03-4885-AB03-CA81038808A6} = {31587D24-F6B5-4A47-A962-47CA7FEA79D0} {9CA19BE4-DC10-4690-9142-61BD007B6D80} = {31587D24-F6B5-4A47-A962-47CA7FEA79D0} {570D1047-A109-4209-9258-9BA7C8BDC9AA} = {31587D24-F6B5-4A47-A962-47CA7FEA79D0} diff --git a/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs b/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs index bf7c089f95..b38bf97f05 100644 --- a/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs +++ b/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs @@ -203,9 +203,14 @@ namespace Microsoft.AspNetCore.Hosting.Internal public IWebHostBuilder UseStartup(Type startupType) { + // UseStartup can be called multiple times. Only run the last one. + _builder.Properties["UseStartup.StartupType"] = startupType; _builder.ConfigureServices((context, services) => { - UseStartup(startupType, context, services); + if (_builder.Properties.TryGetValue("UseStartup.StartupType", out var cachedType) && (Type)cachedType == startupType) + { + UseStartup(startupType, context, services); + } }); return this; diff --git a/src/Hosting/TestHost/src/Microsoft.AspNetCore.TestHost.csproj b/src/Hosting/TestHost/src/Microsoft.AspNetCore.TestHost.csproj index f309bf0eea..00423705cc 100644 --- a/src/Hosting/TestHost/src/Microsoft.AspNetCore.TestHost.csproj +++ b/src/Hosting/TestHost/src/Microsoft.AspNetCore.TestHost.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core web server for writing and running tests. @@ -9,12 +9,9 @@ true - - - - + diff --git a/src/Hosting/TestHost/src/TestServer.cs b/src/Hosting/TestHost/src/TestServer.cs index 40a3e63f05..6c45c0b21b 100644 --- a/src/Hosting/TestHost/src/TestServer.cs +++ b/src/Hosting/TestHost/src/TestServer.cs @@ -146,7 +146,7 @@ namespace Microsoft.AspNetCore.TestHost if (!_disposed) { _disposed = true; - _hostInstance.Dispose(); + _hostInstance?.Dispose(); } } diff --git a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs b/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs index 308ac86cd4..41b7c31dba 100644 --- a/src/Hosting/TestHost/src/WebHostBuilderExtensions.cs +++ b/src/Hosting/TestHost/src/WebHostBuilderExtensions.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; @@ -33,9 +33,17 @@ namespace Microsoft.AspNetCore.TestHost throw new ArgumentNullException(nameof(servicesConfiguration)); } - webHostBuilder.ConfigureServices( - s => s.AddSingleton( - new ConfigureTestServicesStartupConfigureServicesFilter(servicesConfiguration))); + if (webHostBuilder.GetType().Name.Equals("GenericWebHostBuilder")) + { + // Generic host doesn't need to do anything special here since there's only one container. + webHostBuilder.ConfigureServices(servicesConfiguration); + } + else + { + webHostBuilder.ConfigureServices( + s => s.AddSingleton( + new ConfigureTestServicesStartupConfigureServicesFilter(servicesConfiguration))); + } return webHostBuilder; } diff --git a/src/Hosting/TestHost/src/WebHostBuilderFactory.cs b/src/Hosting/TestHost/src/WebHostBuilderFactory.cs index 3a0b0a552e..86930ce8d5 100644 --- a/src/Hosting/TestHost/src/WebHostBuilderFactory.cs +++ b/src/Hosting/TestHost/src/WebHostBuilderFactory.cs @@ -1,23 +1,18 @@ -// 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.Reflection; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.WebHostBuilderFactory; +using Microsoft.Extensions.Hosting; namespace Microsoft.AspNetCore.TestHost { public static class WebHostBuilderFactory { - public static IWebHostBuilder CreateFromAssemblyEntryPoint(Assembly assembly, string [] args) + public static IWebHostBuilder CreateFromAssemblyEntryPoint(Assembly assembly, string[] args) { - var result = WebHostFactoryResolver.ResolveWebHostBuilderFactory(assembly); - if (result.ResultKind != FactoryResolutionResultKind.Success) - { - return null; - } - - return result.WebHostBuilderFactory(args); + var factory = HostFactoryResolver.ResolveWebHostBuilderFactory(assembly); + return factory?.Invoke(args); } public static IWebHostBuilder CreateFromTypesAssemblyEntryPoint(string[] args) => diff --git a/src/Hosting/test/WebHostBuilderFactory.Tests/Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Tests.csproj b/src/Hosting/test/WebHostBuilderFactory.Tests/Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Tests.csproj deleted file mode 100644 index 359607677b..0000000000 --- a/src/Hosting/test/WebHostBuilderFactory.Tests/Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Tests.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - netcoreapp3.0 - - - - - - - - - - - - - - - - - - diff --git a/src/Hosting/test/WebHostBuilderFactory.Tests/WebHostFactoryResolverTests.cs b/src/Hosting/test/WebHostBuilderFactory.Tests/WebHostFactoryResolverTests.cs deleted file mode 100644 index f2732f75c4..0000000000 --- a/src/Hosting/test/WebHostBuilderFactory.Tests/WebHostFactoryResolverTests.cs +++ /dev/null @@ -1,84 +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 Xunit; - -namespace Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Tests -{ - public class WebHostFactoryResolverTests - { - [Fact] - public void CanFindWebHostBuilder_CreateWebHostBuilderPattern() - { - // Arrange & Act - var resolverResult = WebHostFactoryResolver.ResolveWebHostBuilderFactory(typeof(IStartupInjectionAssemblyName.Startup).Assembly); - - // Assert - Assert.Equal(FactoryResolutionResultKind.Success, resolverResult.ResultKind); - Assert.NotNull(resolverResult.WebHostBuilderFactory); - Assert.NotNull(resolverResult.WebHostFactory); - Assert.IsAssignableFrom(resolverResult.WebHostBuilderFactory(Array.Empty())); - } - - [Fact] - public void CanFindWebHost_CreateWebHostBuilderPattern() - { - // Arrange & Act - var resolverResult = WebHostFactoryResolver.ResolveWebHostFactory(typeof(IStartupInjectionAssemblyName.Startup).Assembly); - - // Assert - Assert.Equal(FactoryResolutionResultKind.Success, resolverResult.ResultKind); - Assert.NotNull(resolverResult.WebHostBuilderFactory); - Assert.NotNull(resolverResult.WebHostFactory); - } - - [Fact] - public void CanNotFindWebHostBuilder_BuildWebHostPattern() - { - // Arrange & Act - var resolverResult = WebHostFactoryResolver.ResolveWebHostBuilderFactory(typeof(BuildWebHostPatternTestSite.Startup).Assembly); - - // Assert - Assert.Equal(FactoryResolutionResultKind.NoCreateWebHostBuilder, resolverResult.ResultKind); - Assert.Null(resolverResult.WebHostBuilderFactory); - Assert.Null(resolverResult.WebHostFactory); - } - - [Fact] - public void CanNotFindWebHostBuilder_CreateWebHostBuilderIncorrectSignature() - { - // Arrange & Act - var resolverResult = WebHostFactoryResolver.ResolveWebHostBuilderFactory(typeof(CreateWebHostBuilderInvalidSignature.Startup).Assembly); - - // Assert - Assert.Equal(FactoryResolutionResultKind.NoCreateWebHostBuilder, resolverResult.ResultKind); - Assert.Null(resolverResult.WebHostBuilderFactory); - Assert.Null(resolverResult.WebHostFactory); - } - - [Fact] - public void CanNotFindWebHost_BuildWebHostIncorrectSignature() - { - // Arrange & Act - var resolverResult = WebHostFactoryResolver.ResolveWebHostFactory(typeof(BuildWebHostInvalidSignature.Startup).Assembly); - - // Assert - Assert.Equal(FactoryResolutionResultKind.NoBuildWebHost, resolverResult.ResultKind); - Assert.Null(resolverResult.WebHostBuilderFactory); - Assert.Null(resolverResult.WebHostFactory); - } - - [Fact] - public void CanFindWebHost_BuildWebHostPattern() - { - // Arrange & Act - var resolverResult = WebHostFactoryResolver.ResolveWebHostFactory(typeof(BuildWebHostPatternTestSite.Startup).Assembly); - - // Assert - Assert.Equal(FactoryResolutionResultKind.Success, resolverResult.ResultKind); - Assert.Null(resolverResult.WebHostBuilderFactory); - Assert.NotNull(resolverResult.WebHostFactory); - } - } -} diff --git a/src/Hosting/test/testassets/BuildWebHostInvalidSignature/BuildWebHostInvalidSignature.csproj b/src/Hosting/test/testassets/BuildWebHostInvalidSignature/BuildWebHostInvalidSignature.csproj deleted file mode 100644 index 3ea37b679b..0000000000 --- a/src/Hosting/test/testassets/BuildWebHostInvalidSignature/BuildWebHostInvalidSignature.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - netcoreapp3.0 - Exe - - - - - - - - - diff --git a/src/Hosting/test/testassets/BuildWebHostInvalidSignature/Program.cs b/src/Hosting/test/testassets/BuildWebHostInvalidSignature/Program.cs deleted file mode 100644 index b25cb703ad..0000000000 --- a/src/Hosting/test/testassets/BuildWebHostInvalidSignature/Program.cs +++ /dev/null @@ -1,16 +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.Hosting; - -namespace BuildWebHostInvalidSignature -{ - class Program - { - static void Main(string[] args) - { - } - - public static IWebHost BuildWebHost() => null; - } -} diff --git a/src/Hosting/test/testassets/BuildWebHostInvalidSignature/Startup.cs b/src/Hosting/test/testassets/BuildWebHostInvalidSignature/Startup.cs deleted file mode 100644 index 0b52bc36b8..0000000000 --- a/src/Hosting/test/testassets/BuildWebHostInvalidSignature/Startup.cs +++ /dev/null @@ -1,19 +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.Extensions.DependencyInjection; - -namespace BuildWebHostInvalidSignature -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - } - - public void Configure(IApplicationBuilder builder) - { - } - } -} diff --git a/src/Hosting/test/testassets/BuildWebHostPatternTestSite/BuildWebHostPatternTestSite.csproj b/src/Hosting/test/testassets/BuildWebHostPatternTestSite/BuildWebHostPatternTestSite.csproj deleted file mode 100644 index 3ea37b679b..0000000000 --- a/src/Hosting/test/testassets/BuildWebHostPatternTestSite/BuildWebHostPatternTestSite.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - netcoreapp3.0 - Exe - - - - - - - - - diff --git a/src/Hosting/test/testassets/BuildWebHostPatternTestSite/Program.cs b/src/Hosting/test/testassets/BuildWebHostPatternTestSite/Program.cs deleted file mode 100644 index a5a20508b9..0000000000 --- a/src/Hosting/test/testassets/BuildWebHostPatternTestSite/Program.cs +++ /dev/null @@ -1,16 +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.Hosting; - -namespace BuildWebHostPatternTestSite -{ - class Program - { - static void Main(string[] args) - { - } - - public static IWebHost BuildWebHost(string[] args) => null; - } -} diff --git a/src/Hosting/test/testassets/BuildWebHostPatternTestSite/Startup.cs b/src/Hosting/test/testassets/BuildWebHostPatternTestSite/Startup.cs deleted file mode 100644 index 10ecf07a99..0000000000 --- a/src/Hosting/test/testassets/BuildWebHostPatternTestSite/Startup.cs +++ /dev/null @@ -1,19 +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.Extensions.DependencyInjection; - -namespace BuildWebHostPatternTestSite -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - } - - public void Configure(IApplicationBuilder builder) - { - } - } -} diff --git a/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/CreateWebHostBuilderInvalidSignature.csproj b/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/CreateWebHostBuilderInvalidSignature.csproj deleted file mode 100644 index 3ea37b679b..0000000000 --- a/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/CreateWebHostBuilderInvalidSignature.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - netcoreapp3.0 - Exe - - - - - - - - - diff --git a/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/Program.cs b/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/Program.cs deleted file mode 100644 index 9322836fe0..0000000000 --- a/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/Program.cs +++ /dev/null @@ -1,16 +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.Hosting; - -namespace CreateWebHostBuilderInvalidSignature -{ - class Program - { - static void Main(string[] args) - { - } - - public static IWebHostBuilder CreateWebHostBuilder() => null; - } -} diff --git a/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/Startup.cs b/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/Startup.cs deleted file mode 100644 index 2655a7e937..0000000000 --- a/src/Hosting/test/testassets/CreateWebHostBuilderInvalidSignature/Startup.cs +++ /dev/null @@ -1,19 +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.Extensions.DependencyInjection; - -namespace CreateWebHostBuilderInvalidSignature -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - } - - public void Configure(IApplicationBuilder builder) - { - } - } -} diff --git a/src/Mvc/Mvc.sln b/src/Mvc/Mvc.sln index 1dfdb97911..316098c927 100644 --- a/src/Mvc/Mvc.sln +++ b/src/Mvc/Mvc.sln @@ -268,6 +268,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Respon EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IISIntegration", "..\Servers\IIS\IISIntegration\src\Microsoft.AspNetCore.Server.IISIntegration.csproj", "{35AE5599-AD99-4198-AC91-C599459E9023}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenericHostWebSite", "test\WebSites\GenericHostWebSite\GenericHostWebSite.csproj", "{D9BE3E50-5CE8-4D8D-BA19-AA219D009752}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1562,6 +1564,18 @@ Global {35AE5599-AD99-4198-AC91-C599459E9023}.Release|Mixed Platforms.Build.0 = Release|Any CPU {35AE5599-AD99-4198-AC91-C599459E9023}.Release|x86.ActiveCfg = Release|Any CPU {35AE5599-AD99-4198-AC91-C599459E9023}.Release|x86.Build.0 = Release|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Debug|x86.ActiveCfg = Debug|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Debug|x86.Build.0 = Debug|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Release|Any CPU.Build.0 = Release|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Release|x86.ActiveCfg = Release|Any CPU + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1678,6 +1692,7 @@ Global {C75C6E51-4FFD-4902-8739-9109E51875B4} = {9328599D-A7AF-43BC-BE08-7503DF9B8CE6} {11D8DEBD-2E84-4EF2-8039-4B4BAC58F189} = {9328599D-A7AF-43BC-BE08-7503DF9B8CE6} {35AE5599-AD99-4198-AC91-C599459E9023} = {9328599D-A7AF-43BC-BE08-7503DF9B8CE6} + {D9BE3E50-5CE8-4D8D-BA19-AA219D009752} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {63D344F6-F86D-40E6-85B9-0AABBE338C4A} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Microsoft.AspNetCore.Mvc.Testing.csproj b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Microsoft.AspNetCore.Mvc.Testing.csproj index 5ea627fc00..36f14c1bc8 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Microsoft.AspNetCore.Mvc.Testing.csproj +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Microsoft.AspNetCore.Mvc.Testing.csproj @@ -11,10 +11,9 @@ - - - + + diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Properties/Resources.Designer.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Properties/Resources.Designer.cs index aa246881eb..e5c4f62c9b 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Properties/Resources.Designer.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Properties/Resources.Designer.cs @@ -25,18 +25,18 @@ namespace Microsoft.AspNetCore.Mvc.Testing => string.Format(CultureInfo.CurrentCulture, GetString("InvalidAssemblyEntryPoint"), p0); /// - /// No method 'public static {0} CreateWebHostBuilder(string[] args)' found on '{1}'. Alternatively, {2} can be extended and 'protected virtual {0} {3}()' can be overridden to provide your own {0} instance. + /// No method 'public static {0} CreateHostBuilder(string[] args)' or 'public static {1} CreateWebHostBuilder(string[] args)' found on '{2}'. Alternatively, {3} can be extended and '{4}' or '{5}' can be overridden to provide your own instance. /// - internal static string MissingCreateWebHostBuilderMethod + internal static string MissingBuilderMethod { - get => GetString("MissingCreateWebHostBuilderMethod"); + get => GetString("MissingBuilderMethod"); } /// - /// No method 'public static {0} CreateWebHostBuilder(string[] args)' found on '{1}'. Alternatively, {2} can be extended and 'protected virtual {0} {3}()' can be overridden to provide your own {0} instance. + /// No method 'public static {0} CreateHostBuilder(string[] args)' or 'public static {1} CreateWebHostBuilder(string[] args)' found on '{2}'. Alternatively, {3} can be extended and '{4}' or '{5}' can be overridden to provide your own instance. /// - internal static string FormatMissingCreateWebHostBuilderMethod(object p0, object p1, object p2, object p3) - => string.Format(CultureInfo.CurrentCulture, GetString("MissingCreateWebHostBuilderMethod"), p0, p1, p2, p3); + internal static string FormatMissingBuilderMethod(object p0, object p1, object p2, object p3, object p4, object p5) + => string.Format(CultureInfo.CurrentCulture, GetString("MissingBuilderMethod"), p0, p1, p2, p3, p4, p5); /// /// Can't find'{0}'. This file is required for functional tests to run properly. There should be a copy of the file on your source project bin folder. If that is not the case, make sure that the property PreserveCompilationContext is set to true on your project file. E.g '<PreserveCompilationContext>true</PreserveCompilationContext>'. For functional tests to work they need to either run from the build output folder or the {1} file from your application's output directory must be copied to the folder where the tests are running on. A common cause for this error is having shadow copying enabled when the tests run. diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Resources.resx b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Resources.resx index adf4045ebe..fad454a319 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Resources.resx +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/Resources.resx @@ -120,8 +120,8 @@ The provided Type '{0}' does not belong to an assembly with an entry point. A common cause for this error is providing a Type from a class library. - - No method 'public static {0} CreateWebHostBuilder(string[] args)' found on '{1}'. Alternatively, {2} can be extended and 'protected virtual {0} {3}()' can be overridden to provide your own {0} instance. + + No method 'public static {0} CreateHostBuilder(string[] args)' or 'public static {1} CreateWebHostBuilder(string[] args)' found on '{2}'. Alternatively, {3} can be extended and '{4}' or '{5}' can be overridden to provide your own instance. Can't find'{0}'. This file is required for functional tests to run properly. There should be a copy of the file on your source project bin folder. If that is not the case, make sure that the property PreserveCompilationContext is set to true on your project file. E.g '<PreserveCompilationContext>true</PreserveCompilationContext>'. For functional tests to work they need to either run from the build output folder or the {1} file from your application's output directory must be copied to the folder where the tests are running on. A common cause for this error is having shadow copying enabled when the tests run. diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/WebApplicationFactory.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/WebApplicationFactory.cs index 8356180bd9..1524622bd4 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/WebApplicationFactory.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Testing/WebApplicationFactory.cs @@ -8,8 +8,12 @@ using System.Linq; using System.Net.Http; using System.Reflection; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyModel; +using Microsoft.Extensions.Hosting; +using EnvironmentName = Microsoft.Extensions.Hosting.EnvironmentName; namespace Microsoft.AspNetCore.Mvc.Testing { @@ -22,6 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.Testing { private bool _disposed; private TestServer _server; + private IHost _host; private Action _configuration; private IList _clients = new List(); private List> _derivedFactories = @@ -66,7 +71,14 @@ namespace Microsoft.AspNetCore.Mvc.Testing /// /// Gets the created by this . /// - public TestServer Server => _server; + public TestServer Server + { + get + { + EnsureServer(); + return _server; + } + } /// /// Gets the of factories created from this factory @@ -96,7 +108,9 @@ namespace Microsoft.AspNetCore.Mvc.Testing var factory = new DelegatedWebApplicationFactory( ClientOptions, CreateServer, + CreateHost, CreateWebHostBuilder, + CreateHostBuilder, GetTestAssemblies, ConfigureClient, builder => @@ -119,6 +133,19 @@ namespace Microsoft.AspNetCore.Mvc.Testing EnsureDepsFile(); + var hostBuilder = CreateHostBuilder(); + if (hostBuilder != null) + { + hostBuilder.ConfigureWebHost(webHostBuilder => + { + SetContentRoot(webHostBuilder); + _configuration(webHostBuilder); + webHostBuilder.UseTestServer(); + }); + _host = CreateHost(hostBuilder); + _server = (TestServer)_host.Services.GetRequiredService(); + return; + } var builder = CreateWebHostBuilder(); SetContentRoot(builder); @@ -266,11 +293,30 @@ namespace Microsoft.AspNetCore.Mvc.Testing } } + /// + /// Creates a used to set up . + /// + /// + /// The default implementation of this method looks for a public static IHostBuilder CreateHostBuilder(string[] args) + /// method defined on the entry point of the assembly of and invokes it passing an empty string + /// array as arguments. + /// + /// A instance. + protected virtual IHostBuilder CreateHostBuilder() + { + var hostBuilder = HostFactoryResolver.ResolveHostBuilderFactory(typeof(TEntryPoint).Assembly)?.Invoke(Array.Empty()); + if (hostBuilder != null) + { + hostBuilder.UseEnvironment(EnvironmentName.Development); + } + return hostBuilder; + } + /// /// Creates a used to set up . /// /// - /// The default implementation of this method looks for a public static IWebHostBuilder CreateDefaultBuilder(string[] args) + /// The default implementation of this method looks for a public static IWebHostBuilder CreateWebHostBuilder(string[] args) /// method defined on the entry point of the assembly of and invokes it passing an empty string /// array as arguments. /// @@ -280,26 +326,44 @@ namespace Microsoft.AspNetCore.Mvc.Testing var builder = WebHostBuilderFactory.CreateFromTypesAssemblyEntryPoint(Array.Empty()); if (builder == null) { - throw new InvalidOperationException(Resources.FormatMissingCreateWebHostBuilderMethod( + throw new InvalidOperationException(Resources.FormatMissingBuilderMethod( + nameof(IHostBuilder), nameof(IWebHostBuilder), typeof(TEntryPoint).Assembly.EntryPoint.DeclaringType.FullName, typeof(WebApplicationFactory).Name, + nameof(CreateHostBuilder), nameof(CreateWebHostBuilder))); } else { - return builder.UseEnvironment("Development"); + return builder.UseEnvironment(EnvironmentName.Development); } } /// /// Creates the with the bootstrapped application in . + /// This is only called for applications using . Applications based on + /// will use instead. /// /// The used to /// create the server. /// The with the bootstrapped application. protected virtual TestServer CreateServer(IWebHostBuilder builder) => new TestServer(builder); + /// + /// Creates the with the bootstrapped application in . + /// This is only called for applications using . Applications based on + /// will use instead. + /// + /// The used to create the host. + /// The with the bootstrapped application. + protected virtual IHost CreateHost(IHostBuilder builder) + { + var host = builder.Build(); + host.Start(); + return host; + } + /// /// Gives a fixture an opportunity to configure the application before it gets built. /// @@ -425,6 +489,7 @@ namespace Microsoft.AspNetCore.Mvc.Testing } _server?.Dispose(); + _host?.Dispose(); } _disposed = true; @@ -433,21 +498,27 @@ namespace Microsoft.AspNetCore.Mvc.Testing private class DelegatedWebApplicationFactory : WebApplicationFactory { private readonly Func _createServer; + private readonly Func _createHost; private readonly Func _createWebHostBuilder; + private readonly Func _createHostBuilder; private readonly Func> _getTestAssemblies; private readonly Action _configureClient; public DelegatedWebApplicationFactory( WebApplicationFactoryClientOptions options, Func createServer, + Func createHost, Func createWebHostBuilder, + Func createHostBuilder, Func> getTestAssemblies, Action configureClient, Action configureWebHost) { ClientOptions = new WebApplicationFactoryClientOptions(options); _createServer = createServer; + _createHost = createHost; _createWebHostBuilder = createWebHostBuilder; + _createHostBuilder = createHostBuilder; _getTestAssemblies = getTestAssemblies; _configureClient = configureClient; _configuration = configureWebHost; @@ -455,8 +526,12 @@ namespace Microsoft.AspNetCore.Mvc.Testing protected override TestServer CreateServer(IWebHostBuilder builder) => _createServer(builder); + protected override IHost CreateHost(IHostBuilder builder) => _createHost(builder); + protected override IWebHostBuilder CreateWebHostBuilder() => _createWebHostBuilder(); + protected override IHostBuilder CreateHostBuilder() => _createHostBuilder(); + protected override IEnumerable GetTestAssemblies() => _getTestAssemblies(); protected override void ConfigureWebHost(IWebHostBuilder builder) => _configuration(builder); @@ -468,7 +543,9 @@ namespace Microsoft.AspNetCore.Mvc.Testing return new DelegatedWebApplicationFactory( ClientOptions, _createServer, + _createHost, _createWebHostBuilder, + _createHostBuilder, _getTestAssemblies, _configureClient, builder => diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Infrastructure/MvcTestFixture.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Infrastructure/MvcTestFixture.cs index cf1ed53098..1c85f8412d 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Infrastructure/MvcTestFixture.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Infrastructure/MvcTestFixture.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; @@ -44,5 +45,22 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests CultureInfo.CurrentUICulture = originalUICulture; } } + + protected override IHost CreateHost(IHostBuilder builder) + { + var originalCulture = CultureInfo.CurrentCulture; + var originalUICulture = CultureInfo.CurrentUICulture; + try + { + CultureInfo.CurrentCulture = new CultureInfo("en-GB"); + CultureInfo.CurrentUICulture = new CultureInfo("en-US"); + return base.CreateHost(builder); + } + finally + { + CultureInfo.CurrentCulture = originalCulture; + CultureInfo.CurrentUICulture = originalUICulture; + } + } } } diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Microsoft.AspNetCore.Mvc.FunctionalTests.csproj b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Microsoft.AspNetCore.Mvc.FunctionalTests.csproj index 0318f58efb..b4e4e33ab0 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Microsoft.AspNetCore.Mvc.FunctionalTests.csproj +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Microsoft.AspNetCore.Mvc.FunctionalTests.csproj @@ -38,6 +38,7 @@ + diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureInheritanceTests.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureInheritanceTests.cs index 02c2e622c3..09a11fb4f8 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureInheritanceTests.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureInheritanceTests.cs @@ -7,6 +7,7 @@ using System.Reflection; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Hosting; using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests @@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests public class TestingInfrastructureInheritanceTests { [Fact] - public void TestingInfrastructure_WithWebHostBuilderRespectsCustomizations() + public void TestingInfrastructure_WebHost_WithWebHostBuilderRespectsCustomizations() { // Act var factory = new CustomizedFactory(); @@ -28,13 +29,36 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.True(factory.CreateServerCalled); Assert.True(factory.CreateWebHostBuilderCalled); Assert.True(factory.GetTestAssembliesCalled); + Assert.True(factory.CreateHostBuilderCalled); + Assert.False(factory.CreateHostCalled); + } + + [Fact] + public void TestingInfrastructure_GenericHost_WithWithHostBuilderRespectsCustomizations() + { + // Act + var factory = new CustomizedFactory(); + var customized = factory + .WithWebHostBuilder(builder => factory.ConfigureWebHostCalled.Add("Customization")) + .WithWebHostBuilder(builder => factory.ConfigureWebHostCalled.Add("FurtherCustomization")); + var client = customized.CreateClient(); + + // Assert + Assert.Equal(new[] { "ConfigureWebHost", "Customization", "FurtherCustomization" }, factory.ConfigureWebHostCalled.ToArray()); + Assert.True(factory.GetTestAssembliesCalled); + Assert.True(factory.CreateHostBuilderCalled); + Assert.True(factory.CreateHostCalled); + Assert.False(factory.CreateServerCalled); + Assert.False(factory.CreateWebHostBuilderCalled); } private class CustomizedFactory : WebApplicationFactory where TEntryPoint : class { public bool GetTestAssembliesCalled { get; private set; } public bool CreateWebHostBuilderCalled { get; private set; } + public bool CreateHostBuilderCalled { get; private set; } public bool CreateServerCalled { get; private set; } + public bool CreateHostCalled { get; private set; } public IList ConfigureWebHostCalled { get; private set; } = new List(); protected override void ConfigureWebHost(IWebHostBuilder builder) @@ -49,12 +73,24 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests return base.CreateServer(builder); } + protected override IHost CreateHost(IHostBuilder builder) + { + CreateHostCalled = true; + return base.CreateHost(builder); + } + protected override IWebHostBuilder CreateWebHostBuilder() { CreateWebHostBuilderCalled = true; return base.CreateWebHostBuilder(); } + protected override IHostBuilder CreateHostBuilder() + { + CreateHostBuilderCalled = true; + return base.CreateHostBuilder(); + } + protected override IEnumerable GetTestAssemblies() { GetTestAssembliesCalled = true; diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureTests.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureTests.cs index 341fce0f54..4efe202470 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureTests.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureTests.cs @@ -119,6 +119,18 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal(5, await response.Content.ReadAsAsync()); } + [Fact] + public async Task TestingInfrastructure_WorksWithGenericHost() + { + var factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => + builder.ConfigureTestServices(s => s.AddSingleton())); + + var response = await factory.CreateClient().GetStringAsync("Testing/Builder"); + + Assert.Equal("GenericTest", response); + } + private class OverridenService : TestService { public OverridenService() @@ -127,6 +139,14 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests } } + private class OverridenGenericService : GenericHostWebSite.TestGenericService + { + public OverridenGenericService() + { + Message = "GenericTest"; + } + } + private class TestHandler : DelegatingHandler { public TestHandler() diff --git a/src/Mvc/test/WebSites/BasicWebSite/BasicWebSite.csproj b/src/Mvc/test/WebSites/BasicWebSite/BasicWebSite.csproj index a46afe57e6..d452f269a8 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/BasicWebSite.csproj +++ b/src/Mvc/test/WebSites/BasicWebSite/BasicWebSite.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.0 @@ -16,14 +16,6 @@ - - - - - diff --git a/src/Mvc/test/WebSites/BasicWebSite/Program.cs b/src/Mvc/test/WebSites/BasicWebSite/Program.cs index 2de761fdc5..11818853eb 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/Program.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/Program.cs @@ -17,7 +17,6 @@ namespace BasicWebSite new WebHostBuilder() .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup() - .ConfigureServices(s => s.AddSingleton(new TestService { Message = "true" })) .UseKestrel() .UseIISIntegration(); } diff --git a/src/Mvc/test/WebSites/BasicWebSite/Startup.cs b/src/Mvc/test/WebSites/BasicWebSite/Startup.cs index 930837a49f..8147a6b774 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/Startup.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/Startup.cs @@ -16,6 +16,8 @@ namespace BasicWebSite // Set up application services public void ConfigureServices(IServiceCollection services) { + services.AddSingleton(new TestService { Message = "true" }); + services.AddAuthentication() .AddScheme("Api", _ => { }); services.AddTransient(); diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/Controllers/TestingController.cs b/src/Mvc/test/WebSites/GenericHostWebSite/Controllers/TestingController.cs new file mode 100644 index 0000000000..cf254f717b --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/Controllers/TestingController.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace GenericHostWebSite.Controllers +{ + public class TestingController : Controller + { + public TestingController(TestGenericService service) + { + Service = service; + } + + public TestGenericService Service { get; } + + [HttpGet("Testing/Builder")] + public string Get() => Service.Message; + + [HttpPost("Testing/RedirectHandler/{value}")] + public IActionResult RedirectHandler( + [FromRoute]int value, + [FromBody] Number number, + [FromHeader(Name = "X-Pass-Thru")] string passThruValue) + { + Response.Headers.Add("X-Pass-Thru", passThruValue); + if (value < number.Value) + { + return RedirectToActionPreserveMethod( + nameof(RedirectHandler), + "Testing", + new { value = value + 1 }); + } + + return Ok(new RedirectHandlerResponse { Url = value, Body = number.Value }); + } + + [HttpGet("Testing/RedirectHandler/Headers")] + public IActionResult RedirectHandlerHeaders() + { + if (!Request.Headers.TryGetValue("X-Added-Header", out var value)) + { + return Content("No header present"); + } + else + { + return RedirectToAction(nameof(RedirectHandlerHeadersRedirect)); + } + } + + [HttpGet("Testing/RedirectHandler/Headers/Redirect")] + public IActionResult RedirectHandlerHeadersRedirect() + { + if (Request.Headers.TryGetValue("X-Added-Header", out var value)) + { + return Content("true"); + } + else + { + return Content("false"); + } + } + + [HttpGet("Testing/AntiforgerySimulator/{value}")] + public IActionResult AntiforgerySimulator([FromRoute]int value) + { + Response.Cookies.Append( + "AntiforgerySimulator", + $"Cookie-{value.ToString(CultureInfo.InvariantCulture)}"); + + return Ok(); + } + + + [HttpPost("Testing/PostRedirectGet/Post/{value}")] + public IActionResult PostRedirectGetPost([FromRoute]int value) + { + var compareValue = $"Cookie-{value.ToString(CultureInfo.InvariantCulture)}"; + if (!Request.Cookies.ContainsKey("AntiforgerySimulator")) + { + return BadRequest("Missing AntiforgerySimulator cookie"); + } + + if (!string.Equals(compareValue, Request.Cookies["AntiforgerySimulator"])) + { + return BadRequest("Values don't match"); + } + + TempData["Value"] = value + 1; + Response.Cookies.Append("Message", $"Value-{(value + 1).ToString(CultureInfo.InvariantCulture)}"); + + return RedirectToAction(nameof(PostRedirectGetGet)); + } + + [HttpGet("Testing/PostRedirectGet/Get/{value}")] + public IActionResult PostRedirectGetGet([FromRoute]int value) + { + return Ok(new PostRedirectGetGetResponse + { + TempDataValue = (int)TempData["Value"], + CookieValue = Request.Cookies["Message"] + }); + } + + [HttpPut("Testing/Put/{value}")] + public IActionResult PutNoBody([FromRoute]int value) + { + if (value < 5) + { + return RedirectToActionPermanentPreserveMethod(nameof(PutNoBody), "Testing", new { value = value + 1 }); + } + else + { + return Ok(value); + } + } + } + + public class PostRedirectGetGetResponse + { + public int TempDataValue { get; set; } + public string CookieValue { get; set; } + } + + public class RedirectHandlerResponse + { + public int Url { get; set; } + public int Body { get; set; } + } + + public class Number + { + public int Value { get; set; } + } +} diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/GenericHostWebSite.csproj b/src/Mvc/test/WebSites/GenericHostWebSite/GenericHostWebSite.csproj new file mode 100644 index 0000000000..e4c1a38652 --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/GenericHostWebSite.csproj @@ -0,0 +1,27 @@ + + + + netcoreapp3.0 + true + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/Program.cs b/src/Mvc/test/WebSites/GenericHostWebSite/Program.cs new file mode 100644 index 0000000000..81389a1494 --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/Program.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace GenericHostWebSite +{ + public class Program + { + public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); + + // Do not change. This is the pattern our test infrastructure uses to initialize a IHostBuilder from + // a users app. + public static IHostBuilder CreateHostBuilder(string[] args) => + new HostBuilder() + .UseContentRoot(Directory.GetCurrentDirectory()) + .ConfigureWebHost(webHostBuilder => + { + webHostBuilder + .UseStartup() + .UseKestrel() + .UseIISIntegration(); + }); + } + + public class TestGenericService + { + public string Message { get; set; } + } +} diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/Startup.cs b/src/Mvc/test/WebSites/GenericHostWebSite/Startup.cs new file mode 100644 index 0000000000..7250470c07 --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/Startup.cs @@ -0,0 +1,58 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.Extensions.DependencyInjection; + +namespace GenericHostWebSite +{ + public class Startup + { + // Set up application services + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(new TestGenericService { Message = "true" }); + + services + .AddMvc(options => + { + // Remove when all URL generation tests are passing - https://github.com/aspnet/Routing/issues/590 + options.EnableEndpointRouting = false; + }) + .SetCompatibilityVersion(CompatibilityVersion.Latest) + .AddNewtonsoftJson() + .AddXmlDataContractSerializerFormatters(); + + services.AddLogging(); + services.AddHttpContextAccessor(); + services.AddScoped(); + services.AddSingleton(); + } + + public void Configure(IApplicationBuilder app) + { + app.UseDeveloperExceptionPage(); + + app.UseStaticFiles(); + + // Add MVC to the request pipeline + app.UseMvc(routes => + { + routes.MapRoute( + "areaRoute", + "{area:exists}/{controller}/{action}", + new { controller = "Home", action = "Index" }); + + routes.MapRoute("ActionAsMethod", "{controller}/{action}", + defaults: new { controller = "Home", action = "Index" }); + + routes.MapRoute("PageRoute", "{controller}/{action}/{page}"); + }); + } + } +} diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/_bower.json b/src/Mvc/test/WebSites/GenericHostWebSite/_bower.json new file mode 100644 index 0000000000..984cfb20bf --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/_bower.json @@ -0,0 +1,14 @@ +{ + "name": "GenericHostWebSite", + "description": "Web site demonstrating various validations.", + "private": true, + "dependencies": { + "jquery-validation-unobtrusive": "3.2.6" + }, + "exportsOverride": { + "jquery-validation-unobtrusive": { + "": "jquery.validate.unobtrusive.min.js" + }, + "*": { } + } +} \ No newline at end of file diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/_bower.readme b/src/Mvc/test/WebSites/GenericHostWebSite/_bower.readme new file mode 100644 index 0000000000..a4fdaba27e --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/_bower.readme @@ -0,0 +1,7 @@ +To recreate minified JavaScript file, + +1. Update jquery-validation-unobtrusive version in _bower.json if necessary. +2. Rename or copy _bower.json to bower.json, _gruntfile.js to gruntfile.js, and _package.json to package.json. +3. Run build from the repo root. (Minimum command is `./build.sh --quiet run-grunt`.) +4. Remove bower.json, gruntfile.js and package.json. +5. Check in _bower.json and new jquery.validate.unobtrusive.min.js file. \ No newline at end of file diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/_gruntfile.js b/src/Mvc/test/WebSites/GenericHostWebSite/_gruntfile.js new file mode 100644 index 0000000000..22b35580a7 --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/_gruntfile.js @@ -0,0 +1,20 @@ +module.exports = function (grunt) { + grunt.initConfig({ + bower: { + install: { + options: { + targetDir: "wwwroot/lib", + layout: "byComponent", + cleanTargetDir: false + } + } + } + }); + + // This command registers the default task which will install bower packages into wwwroot/lib + grunt.registerTask("default", ["bower:install"]); + + // The following line loads the grunt plugins. + // This line needs to be at the end of this file. + grunt.loadNpmTasks("grunt-bower-task"); +}; \ No newline at end of file diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/_package.json b/src/Mvc/test/WebSites/GenericHostWebSite/_package.json new file mode 100644 index 0000000000..45df438fd2 --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/_package.json @@ -0,0 +1,10 @@ +{ + "version": "0.0.0", + "name": "GenericHostWebSite", + "description": "Web site demonstrating various validations.", + "private": true, + "devDependencies": { + "grunt": "^0.4.5", + "grunt-bower-task": "^0.4.0" + } +} \ No newline at end of file diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/readme.md b/src/Mvc/test/WebSites/GenericHostWebSite/readme.md new file mode 100644 index 0000000000..978f55e18d --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/readme.md @@ -0,0 +1,4 @@ +GenericHostWebSite +=== + +This web site illustrates the use of the Generic Host APIs in Program.cs. diff --git a/src/Mvc/test/WebSites/GenericHostWebSite/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js b/src/Mvc/test/WebSites/GenericHostWebSite/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js new file mode 100644 index 0000000000..be9a38a4cf --- /dev/null +++ b/src/Mvc/test/WebSites/GenericHostWebSite/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js @@ -0,0 +1,5 @@ +/* +** Unobtrusive validation support library for jQuery and jQuery Validate +** Copyright (C) Microsoft Corporation. All rights reserved. +*/ +!function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); \ No newline at end of file diff --git a/src/Shared/Hosting.WebHostBuilderFactory/Directory.Build.props b/src/Shared/Hosting.WebHostBuilderFactory/Directory.Build.props deleted file mode 100644 index 29e5392951..0000000000 --- a/src/Shared/Hosting.WebHostBuilderFactory/Directory.Build.props +++ /dev/null @@ -1,8 +0,0 @@ - - - - Internal.WebHostBuilderFactory.Sources - true - false - - diff --git a/src/Shared/Hosting.WebHostBuilderFactory/FactoryResolutionResult.cs b/src/Shared/Hosting.WebHostBuilderFactory/FactoryResolutionResult.cs deleted file mode 100644 index 745cca7ebd..0000000000 --- a/src/Shared/Hosting.WebHostBuilderFactory/FactoryResolutionResult.cs +++ /dev/null @@ -1,54 +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; - -namespace Microsoft.AspNetCore.Hosting.WebHostBuilderFactory -{ - internal class FactoryResolutionResult - { - public FactoryResolutionResultKind ResultKind { get; set; } - public Type ProgramType { get; set; } - public Func WebHostFactory { get; set; } - public Func WebHostBuilderFactory { get; set; } - - internal static FactoryResolutionResult NoBuildWebHost(Type programType) => - new FactoryResolutionResult - { - ProgramType = programType, - ResultKind = FactoryResolutionResultKind.NoBuildWebHost - }; - - internal static FactoryResolutionResult NoCreateWebHostBuilder(Type programType) => - new FactoryResolutionResult - { - ProgramType = programType, - ResultKind = FactoryResolutionResultKind.NoCreateWebHostBuilder - }; - - internal static FactoryResolutionResult NoEntryPoint() => - new FactoryResolutionResult - { - ResultKind = FactoryResolutionResultKind.NoEntryPoint - }; - - internal static FactoryResolutionResult Succeded(Func factory, Type programType) => new FactoryResolutionResult - { - ProgramType = programType, - ResultKind = FactoryResolutionResultKind.Success, - WebHostFactory = factory - }; - - internal static FactoryResolutionResult Succeded(Func factory, Type programType) => new FactoryResolutionResult - { - ProgramType = programType, - ResultKind = FactoryResolutionResultKind.Success, - WebHostBuilderFactory = factory, - WebHostFactory = args => - { - var builder = factory(args); - return (TWebHost)builder.GetType().GetMethod("Build").Invoke(builder, Array.Empty()); - } - }; - } -} diff --git a/src/Shared/Hosting.WebHostBuilderFactory/FactoryResolutionResultKind.cs b/src/Shared/Hosting.WebHostBuilderFactory/FactoryResolutionResultKind.cs deleted file mode 100644 index bb970d21a4..0000000000 --- a/src/Shared/Hosting.WebHostBuilderFactory/FactoryResolutionResultKind.cs +++ /dev/null @@ -1,14 +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. - - -namespace Microsoft.AspNetCore.Hosting.WebHostBuilderFactory -{ - internal enum FactoryResolutionResultKind - { - Success, - NoEntryPoint, - NoCreateWebHostBuilder, - NoBuildWebHost - } -} diff --git a/src/Shared/Hosting.WebHostBuilderFactory/WebHostFactoryResolver.cs b/src/Shared/Hosting.WebHostBuilderFactory/WebHostFactoryResolver.cs deleted file mode 100644 index 916b15e020..0000000000 --- a/src/Shared/Hosting.WebHostBuilderFactory/WebHostFactoryResolver.cs +++ /dev/null @@ -1,68 +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.Reflection; - -namespace Microsoft.AspNetCore.Hosting.WebHostBuilderFactory -{ - internal class WebHostFactoryResolver - { - public static readonly string CreateWebHostBuilder = nameof(CreateWebHostBuilder); - public static readonly string BuildWebHost = nameof(BuildWebHost); - - public static FactoryResolutionResult ResolveWebHostBuilderFactory(Assembly assembly) - { - var programType = assembly?.EntryPoint?.DeclaringType; - if (programType == null) - { - return FactoryResolutionResult.NoEntryPoint(); - } - - var factory = programType.GetTypeInfo().GetDeclaredMethod(CreateWebHostBuilder); - if (factory == null || - !typeof(TWebhostBuilder).IsAssignableFrom(factory.ReturnType) || - factory.GetParameters().Length != 1 || - !typeof(string []).Equals(factory.GetParameters()[0].ParameterType)) - { - return FactoryResolutionResult.NoCreateWebHostBuilder(programType); - } - - return FactoryResolutionResult.Succeded(args => (TWebhostBuilder)factory.Invoke(null, new object[] { args }), programType); - } - - public static FactoryResolutionResult ResolveWebHostFactory(Assembly assembly) - { - // We want to give priority to BuildWebHost over CreateWebHostBuilder for backwards - // compatibility with existing projects that follow the old pattern. - var findResult = ResolveWebHostBuilderFactory(assembly); - switch (findResult.ResultKind) - { - case FactoryResolutionResultKind.NoEntryPoint: - return findResult; - case FactoryResolutionResultKind.Success: - case FactoryResolutionResultKind.NoCreateWebHostBuilder: - var buildWebHostMethod = findResult.ProgramType.GetTypeInfo().GetDeclaredMethod(BuildWebHost); - if (buildWebHostMethod == null || - !typeof(TWebhost).IsAssignableFrom(buildWebHostMethod.ReturnType) || - buildWebHostMethod.GetParameters().Length != 1 || - !typeof(string[]).Equals(buildWebHostMethod.GetParameters()[0].ParameterType)) - { - if (findResult.ResultKind == FactoryResolutionResultKind.Success) - { - return findResult; - } - - return FactoryResolutionResult.NoBuildWebHost(findResult.ProgramType); - } - else - { - return FactoryResolutionResult.Succeded(args => (TWebhost)buildWebHostMethod.Invoke(null, new object[] { args }), findResult.ProgramType); - } - case FactoryResolutionResultKind.NoBuildWebHost: - default: - throw new InvalidOperationException(); - } - } - } -}