React to WebHostBuilderFactory changes (#6460)

This commit is contained in:
Chris Ross 2019-01-15 08:09:27 -08:00 committed by GitHub
parent 09b50850bc
commit 6a44aca6a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 527 additions and 478 deletions

View File

@ -97,9 +97,6 @@ This can be done once #4246 is complete, and done in conjunction with converting
<PackageArtifact Include="Microsoft.AspNetCore.Server.IntegrationTesting.IIS" Category="noship" />
<PackageArtifact Include="Microsoft.AspNetCore.Server.IntegrationTesting" Category="noship" />
<!-- This package is produced for use in aspnet/EntityFrameworkCore to ensure EF tools can load a service collection from and app using ASP.NET's Program/Startup patterns/ -->
<PackageArtifact Include="Internal.WebHostBuilderFactory.Sources" Category="noship"/>
<!-- These packages are produced temporarily while we finish refactoring the way this repo builds. See https://github.com/aspnet/AspNetCore/issues/4246 -->
<PackageArtifact Include="Microsoft.AspNetCore.Antiforgery" Category="noship" />
<PackageArtifact Include="Microsoft.AspNetCore.Authentication.Abstractions" Category="noship" />

View File

@ -34,10 +34,6 @@
<BuildJava>true</BuildJava>
</PropertyGroup>
<ItemGroup>
<SharedSourceDirectories Include="$(SharedSourcesFolder)Hosting.WebHostBuilderFactory\" />
</ItemGroup>
<!-- These projects are always excluded, even when -projects is specified on command line. -->
<ItemGroup>
<!-- These projects use 'legacy' csproj, which is not supported by dotnet-msbuild. -->

View File

@ -65,6 +65,7 @@ and are generated based on the last package release.
<LatestPackageReference Include="Microsoft.Extensions.HashCodeCombiner.Sources" Version="$(MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(MicrosoftExtensionsHostingAbstractionsPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Hosting" Version="$(MicrosoftExtensionsHostingPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.HostFactoryResolver.Sources" Version="$(MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="$(MicrosoftExtensionsLocalizationAbstractionsPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Localization" Version="$(MicrosoftExtensionsLocalizationPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)" />

View File

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

View File

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

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core web server for writing and running tests.</Description>
@ -9,12 +9,9 @@
<IsProductPackage>true</IsProductPackage>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(SharedSourceRoot)Hosting.WebHostBuilderFactory\**\*.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.Extensions.HostFactoryResolver.Sources" PrivateAssets="All" />
<Reference Include="System.IO.Pipelines" />
</ItemGroup>

View File

@ -146,7 +146,7 @@ namespace Microsoft.AspNetCore.TestHost
if (!_disposed)
{
_disposed = true;
_hostInstance.Dispose();
_hostInstance?.Dispose();
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@ -33,9 +33,17 @@ namespace Microsoft.AspNetCore.TestHost
throw new ArgumentNullException(nameof(servicesConfiguration));
}
webHostBuilder.ConfigureServices(
s => s.AddSingleton<IStartupConfigureServicesFilter>(
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<IStartupConfigureServicesFilter>(
new ConfigureTestServicesStartupConfigureServicesFilter(servicesConfiguration)));
}
return webHostBuilder;
}

View File

@ -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<IWebHost,IWebHostBuilder>(assembly);
if (result.ResultKind != FactoryResolutionResultKind.Success)
{
return null;
}
return result.WebHostBuilderFactory(args);
var factory = HostFactoryResolver.ResolveWebHostBuilderFactory<IWebHostBuilder>(assembly);
return factory?.Invoke(args);
}
public static IWebHostBuilder CreateFromTypesAssemblyEntryPoint<T>(string[] args) =>

View File

@ -1,22 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(SharedSourceRoot)Hosting.WebHostBuilderFactory\**\*.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\testassets\BuildWebHostPatternTestSite\BuildWebHostPatternTestSite.csproj" />
<ProjectReference Include="..\testassets\IStartupInjectionAssemblyName\IStartupInjectionAssemblyName.csproj" />
<ProjectReference Include="..\testassets\CreateWebHostBuilderInvalidSignature\CreateWebHostBuilderInvalidSignature.csproj" />
<ProjectReference Include="..\testassets\BuildWebHostInvalidSignature\BuildWebHostInvalidSignature.csproj" />
</ItemGroup>
</Project>

View File

@ -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<IWebHost, IWebHostBuilder>(typeof(IStartupInjectionAssemblyName.Startup).Assembly);
// Assert
Assert.Equal(FactoryResolutionResultKind.Success, resolverResult.ResultKind);
Assert.NotNull(resolverResult.WebHostBuilderFactory);
Assert.NotNull(resolverResult.WebHostFactory);
Assert.IsAssignableFrom<IWebHostBuilder>(resolverResult.WebHostBuilderFactory(Array.Empty<string>()));
}
[Fact]
public void CanFindWebHost_CreateWebHostBuilderPattern()
{
// Arrange & Act
var resolverResult = WebHostFactoryResolver.ResolveWebHostFactory<IWebHost, IWebHostBuilder>(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<IWebHost, IWebHostBuilder>(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<IWebHost, IWebHostBuilder>(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<IWebHost, IWebHostBuilder>(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<IWebHost, IWebHostBuilder>(typeof(BuildWebHostPatternTestSite.Startup).Assembly);
// Assert
Assert.Equal(FactoryResolutionResultKind.Success, resolverResult.ResultKind);
Assert.Null(resolverResult.WebHostBuilderFactory);
Assert.NotNull(resolverResult.WebHostFactory);
}
}
}

View File

@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.AspNetCore.TestHost" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>

View File

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

View File

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

View File

@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.AspNetCore.TestHost" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>

View File

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

View File

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

View File

@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.AspNetCore.TestHost" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>

View File

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

View File

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

View File

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

View File

@ -11,10 +11,9 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.TestHost" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Mvc.Core" />
<Reference Include="Microsoft.Extensions.HostFactoryResolver.Sources" PrivateAssets="All" />
<Reference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<ItemGroup>

View File

@ -25,18 +25,18 @@ namespace Microsoft.AspNetCore.Mvc.Testing
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidAssemblyEntryPoint"), p0);
/// <summary>
/// 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.
/// </summary>
internal static string MissingCreateWebHostBuilderMethod
internal static string MissingBuilderMethod
{
get => GetString("MissingCreateWebHostBuilderMethod");
get => GetString("MissingBuilderMethod");
}
/// <summary>
/// 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.
/// </summary>
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);
/// <summary>
/// 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 '&lt;PreserveCompilationContext&gt;true&lt;/PreserveCompilationContext&gt;'. 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.

View File

@ -120,8 +120,8 @@
<data name="InvalidAssemblyEntryPoint" xml:space="preserve">
<value>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.</value>
</data>
<data name="MissingCreateWebHostBuilderMethod" xml:space="preserve">
<value>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.</value>
<data name="MissingBuilderMethod" xml:space="preserve">
<value>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.</value>
</data>
<data name="MissingDepsFile" xml:space="preserve">
<value>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 '&lt;PreserveCompilationContext&gt;true&lt;/PreserveCompilationContext&gt;'. 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.</value>

View File

@ -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<IWebHostBuilder> _configuration;
private IList<HttpClient> _clients = new List<HttpClient>();
private List<WebApplicationFactory<TEntryPoint>> _derivedFactories =
@ -66,7 +71,14 @@ namespace Microsoft.AspNetCore.Mvc.Testing
/// <summary>
/// Gets the <see cref="TestServer"/> created by this <see cref="WebApplicationFactory{TEntryPoint}"/>.
/// </summary>
public TestServer Server => _server;
public TestServer Server
{
get
{
EnsureServer();
return _server;
}
}
/// <summary>
/// Gets the <see cref="IReadOnlyList{WebApplicationFactory}"/> 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<IServer>();
return;
}
var builder = CreateWebHostBuilder();
SetContentRoot(builder);
@ -266,11 +293,30 @@ namespace Microsoft.AspNetCore.Mvc.Testing
}
}
/// <summary>
/// Creates a <see cref="IHostBuilder"/> used to set up <see cref="TestServer"/>.
/// </summary>
/// <remarks>
/// The default implementation of this method looks for a <c>public static IHostBuilder CreateHostBuilder(string[] args)</c>
/// method defined on the entry point of the assembly of <typeparamref name="TEntryPoint" /> and invokes it passing an empty string
/// array as arguments.
/// </remarks>
/// <returns>A <see cref="IHostBuilder"/> instance.</returns>
protected virtual IHostBuilder CreateHostBuilder()
{
var hostBuilder = HostFactoryResolver.ResolveHostBuilderFactory<IHostBuilder>(typeof(TEntryPoint).Assembly)?.Invoke(Array.Empty<string>());
if (hostBuilder != null)
{
hostBuilder.UseEnvironment(EnvironmentName.Development);
}
return hostBuilder;
}
/// <summary>
/// Creates a <see cref="IWebHostBuilder"/> used to set up <see cref="TestServer"/>.
/// </summary>
/// <remarks>
/// The default implementation of this method looks for a <c>public static IWebHostBuilder CreateDefaultBuilder(string[] args)</c>
/// The default implementation of this method looks for a <c>public static IWebHostBuilder CreateWebHostBuilder(string[] args)</c>
/// method defined on the entry point of the assembly of <typeparamref name="TEntryPoint" /> and invokes it passing an empty string
/// array as arguments.
/// </remarks>
@ -280,26 +326,44 @@ namespace Microsoft.AspNetCore.Mvc.Testing
var builder = WebHostBuilderFactory.CreateFromTypesAssemblyEntryPoint<TEntryPoint>(Array.Empty<string>());
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<TEntryPoint>).Name,
nameof(CreateHostBuilder),
nameof(CreateWebHostBuilder)));
}
else
{
return builder.UseEnvironment("Development");
return builder.UseEnvironment(EnvironmentName.Development);
}
}
/// <summary>
/// Creates the <see cref="TestServer"/> with the bootstrapped application in <paramref name="builder"/>.
/// This is only called for applications using <see cref="IWebHostBuilder"/>. Applications based on
/// <see cref="IHostBuilder"/> will use <see cref="CreateHost"/> instead.
/// </summary>
/// <param name="builder">The <see cref="IWebHostBuilder"/> used to
/// create the server.</param>
/// <returns>The <see cref="TestServer"/> with the bootstrapped application.</returns>
protected virtual TestServer CreateServer(IWebHostBuilder builder) => new TestServer(builder);
/// <summary>
/// Creates the <see cref="IHost"/> with the bootstrapped application in <paramref name="builder"/>.
/// This is only called for applications using <see cref="IHostBuilder"/>. Applications based on
/// <see cref="IWebHostBuilder"/> will use <see cref="CreateServer"/> instead.
/// </summary>
/// <param name="builder">The <see cref="IHostBuilder"/> used to create the host.</param>
/// <returns>The <see cref="IHost"/> with the bootstrapped application.</returns>
protected virtual IHost CreateHost(IHostBuilder builder)
{
var host = builder.Build();
host.Start();
return host;
}
/// <summary>
/// Gives a fixture an opportunity to configure the application before it gets built.
/// </summary>
@ -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<TEntryPoint>
{
private readonly Func<IWebHostBuilder, TestServer> _createServer;
private readonly Func<IHostBuilder, IHost> _createHost;
private readonly Func<IWebHostBuilder> _createWebHostBuilder;
private readonly Func<IHostBuilder> _createHostBuilder;
private readonly Func<IEnumerable<Assembly>> _getTestAssemblies;
private readonly Action<HttpClient> _configureClient;
public DelegatedWebApplicationFactory(
WebApplicationFactoryClientOptions options,
Func<IWebHostBuilder, TestServer> createServer,
Func<IHostBuilder, IHost> createHost,
Func<IWebHostBuilder> createWebHostBuilder,
Func<IHostBuilder> createHostBuilder,
Func<IEnumerable<Assembly>> getTestAssemblies,
Action<HttpClient> configureClient,
Action<IWebHostBuilder> 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<Assembly> 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 =>

View File

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

View File

@ -38,6 +38,7 @@
<ProjectReference Include="..\WebSites\ErrorPageMiddlewareWebSite\ErrorPageMiddlewareWebSite.csproj" />
<ProjectReference Include="..\WebSites\FilesWebSite\FilesWebSite.csproj" />
<ProjectReference Include="..\WebSites\FormatterWebSite\FormatterWebSite.csproj" />
<ProjectReference Include="..\WebSites\GenericHostWebSite\GenericHostWebSite.csproj" />
<ProjectReference Include="..\WebSites\HtmlGenerationWebSite\HtmlGenerationWebSite.csproj" />
<ProjectReference Include="..\WebSites\RazorBuildWebSite\RazorBuildWebSite.csproj" />
<ProjectReference Include="..\WebSites\RazorPagesWebSite\RazorPagesWebSite.csproj" />

View File

@ -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<BasicWebSite.Startup>();
@ -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<GenericHostWebSite.Startup>();
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<TEntryPoint> : WebApplicationFactory<TEntryPoint> 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<string> ConfigureWebHostCalled { get; private set; } = new List<string>();
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<Assembly> GetTestAssemblies()
{
GetTestAssembliesCalled = true;

View File

@ -119,6 +119,18 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Equal(5, await response.Content.ReadAsAsync<int>());
}
[Fact]
public async Task TestingInfrastructure_WorksWithGenericHost()
{
var factory = new WebApplicationFactory<GenericHostWebSite.Program>()
.WithWebHostBuilder(builder =>
builder.ConfigureTestServices(s => s.AddSingleton<GenericHostWebSite.TestGenericService, OverridenGenericService>()));
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()

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
@ -16,14 +16,6 @@
<Reference Include="Microsoft.AspNetCore.Authentication" />
<Reference Include="Microsoft.AspNetCore.Localization.Routing" />
<!--
Explicitly referencing routing here to make it easy to integrate breaking changes. Localization.Routing brings in a transitive
reference to routing, which makes it hard to work with builds from a feature branch.
-->
<Reference Include="Microsoft.AspNetCore.Routing.Abstractions" NoWarn="NU1605" />
<Reference Include="Microsoft.AspNetCore.Routing" NoWarn="NU1605" />
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
<Reference Include="Microsoft.AspNetCore.Session" />

View File

@ -17,7 +17,6 @@ namespace BasicWebSite
new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.ConfigureServices(s => s.AddSingleton(new TestService { Message = "true" }))
.UseKestrel()
.UseIISIntegration();
}

View File

@ -16,6 +16,8 @@ namespace BasicWebSite
// Set up application services
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new TestService { Message = "true" });
services.AddAuthentication()
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("Api", _ => { });
services.AddTransient<IAuthorizationHandler, ManagerHandler>();

View File

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

View File

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IsTestAssetProject>true</IsTestAssetProject>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Common\TestResponseGenerator.cs" Link="TestResponseGenerator.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Mvc" />
<Reference Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" />
<Reference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
<Reference Include="Microsoft.AspNetCore.Localization.Routing" />
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
<Reference Include="Microsoft.AspNetCore.Session" />
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
<Reference Include="Microsoft.AspNetCore.Diagnostics" />
<Reference Include="Microsoft.AspNetCore.CookiePolicy" />
<Reference Include="Microsoft.Extensions.Hosting" />
<Reference Include="Microsoft.NET.Sdk.Razor" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@ -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<Startup>()
.UseKestrel()
.UseIISIntegration();
});
}
public class TestGenericService
{
public string Message { get; set; }
}
}

View File

@ -0,0 +1,58 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using 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<TestResponseGenerator>();
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
}
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}");
});
}
}
}

View File

@ -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"
},
"*": { }
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,4 @@
GenericHostWebSite
===
This web site illustrates the use of the Generic Host APIs in Program.cs.

File diff suppressed because one or more lines are too long

View File

@ -1,8 +0,0 @@
<Project>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
<PropertyGroup>
<PackageId>Internal.WebHostBuilderFactory.Sources</PackageId>
<IsSharedSourcePackage>true</IsSharedSourcePackage>
<IncludeSymbols>false</IncludeSymbols>
</PropertyGroup>
</Project>

View File

@ -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<TWebHost,TWebHostBuilder>
{
public FactoryResolutionResultKind ResultKind { get; set; }
public Type ProgramType { get; set; }
public Func<string[], TWebHost> WebHostFactory { get; set; }
public Func<string[], TWebHostBuilder> WebHostBuilderFactory { get; set; }
internal static FactoryResolutionResult<TWebHost, TWebHostBuilder> NoBuildWebHost(Type programType) =>
new FactoryResolutionResult<TWebHost, TWebHostBuilder>
{
ProgramType = programType,
ResultKind = FactoryResolutionResultKind.NoBuildWebHost
};
internal static FactoryResolutionResult<TWebHost, TWebHostBuilder> NoCreateWebHostBuilder(Type programType) =>
new FactoryResolutionResult<TWebHost, TWebHostBuilder>
{
ProgramType = programType,
ResultKind = FactoryResolutionResultKind.NoCreateWebHostBuilder
};
internal static FactoryResolutionResult<TWebHost, TWebHostBuilder> NoEntryPoint() =>
new FactoryResolutionResult<TWebHost, TWebHostBuilder>
{
ResultKind = FactoryResolutionResultKind.NoEntryPoint
};
internal static FactoryResolutionResult<TWebHost, TWebHostBuilder> Succeded(Func<string[], TWebHost> factory, Type programType) => new FactoryResolutionResult<TWebHost, TWebHostBuilder>
{
ProgramType = programType,
ResultKind = FactoryResolutionResultKind.Success,
WebHostFactory = factory
};
internal static FactoryResolutionResult<TWebHost, TWebHostBuilder> Succeded(Func<string[], TWebHostBuilder> factory, Type programType) => new FactoryResolutionResult<TWebHost, TWebHostBuilder>
{
ProgramType = programType,
ResultKind = FactoryResolutionResultKind.Success,
WebHostBuilderFactory = factory,
WebHostFactory = args =>
{
var builder = factory(args);
return (TWebHost)builder.GetType().GetMethod("Build").Invoke(builder, Array.Empty<object>());
}
};
}
}

View File

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

View File

@ -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<TWebhost,TWebhostBuilder> ResolveWebHostBuilderFactory<TWebhost, TWebhostBuilder>(Assembly assembly)
{
var programType = assembly?.EntryPoint?.DeclaringType;
if (programType == null)
{
return FactoryResolutionResult<TWebhost, TWebhostBuilder>.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<TWebhost, TWebhostBuilder>.NoCreateWebHostBuilder(programType);
}
return FactoryResolutionResult<TWebhost, TWebhostBuilder>.Succeded(args => (TWebhostBuilder)factory.Invoke(null, new object[] { args }), programType);
}
public static FactoryResolutionResult<TWebhost, TWebhostBuilder> ResolveWebHostFactory<TWebhost, TWebhostBuilder>(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<TWebhost, TWebhostBuilder>(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<TWebhost, TWebhostBuilder>.NoBuildWebHost(findResult.ProgramType);
}
else
{
return FactoryResolutionResult<TWebhost, TWebhostBuilder>.Succeded(args => (TWebhost)buildWebHostMethod.Invoke(null, new object[] { args }), findResult.ProgramType);
}
case FactoryResolutionResultKind.NoBuildWebHost:
default:
throw new InvalidOperationException();
}
}
}
}