From 83c4bd889af807b636edee7fd2aec786aec8ea4d Mon Sep 17 00:00:00 2001
From: Eric Erhardt <eric.erhardt@microsoft.com>
Date: Fri, 18 Nov 2022 18:14:17 -0600
Subject: [PATCH 1/7] Allow minimal host to be created without default
 HostBuilder behavior

This adds a new Hosting API to reduce startup and app size, and ensures the default behavior is NativeAOT compatible.

Fix #32485
---
 .../src/PublicAPI.Unshipped.txt               |   3 +
 src/DefaultBuilder/src/WebApplication.cs      |  23 +
 .../src/WebApplicationBuilder.cs              | 128 +++-
 src/DefaultBuilder/src/WebHost.cs             |  14 +-
 .../WebApplicationTests.cs                    | 656 +++++++++++-------
 .../src/GenericHost/SlimWebHostBuilder.cs     | 186 +++++
 .../GenericHostWebHostBuilderExtensions.cs    |  31 +-
 .../Hosting/src/PublicAPI.Unshipped.txt       |   1 +
 8 files changed, 774 insertions(+), 268 deletions(-)
 create mode 100644 src/Hosting/Hosting/src/GenericHost/SlimWebHostBuilder.cs

diff --git a/src/DefaultBuilder/src/PublicAPI.Unshipped.txt b/src/DefaultBuilder/src/PublicAPI.Unshipped.txt
index 7dc5c58110bf..c4dde0ab6378 100644
--- a/src/DefaultBuilder/src/PublicAPI.Unshipped.txt
+++ b/src/DefaultBuilder/src/PublicAPI.Unshipped.txt
@@ -1 +1,4 @@
 #nullable enable
+static Microsoft.AspNetCore.Builder.WebApplication.CreateSlimBuilder() -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
+static Microsoft.AspNetCore.Builder.WebApplication.CreateSlimBuilder(Microsoft.AspNetCore.Builder.WebApplicationOptions! options) -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
+static Microsoft.AspNetCore.Builder.WebApplication.CreateSlimBuilder(string![]! args) -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
diff --git a/src/DefaultBuilder/src/WebApplication.cs b/src/DefaultBuilder/src/WebApplication.cs
index 1a9db8c6df1e..6056b3ff4d02 100644
--- a/src/DefaultBuilder/src/WebApplication.cs
+++ b/src/DefaultBuilder/src/WebApplication.cs
@@ -98,6 +98,13 @@ public static WebApplication Create(string[]? args = null) =>
     public static WebApplicationBuilder CreateBuilder() =>
         new(new());
 
+    /// <summary>
+    /// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with minimal defaults.
+    /// </summary>
+    /// <returns>The <see cref="WebApplicationBuilder"/>.</returns>
+    public static WebApplicationBuilder CreateSlimBuilder() =>
+        new(new(), slim: true);
+
     /// <summary>
     /// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with preconfigured defaults.
     /// </summary>
@@ -106,6 +113,14 @@ public static WebApplicationBuilder CreateBuilder() =>
     public static WebApplicationBuilder CreateBuilder(string[] args) =>
         new(new() { Args = args });
 
+    /// <summary>
+    /// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with minimal defaults.
+    /// </summary>
+    /// <param name="args">Command line arguments</param>
+    /// <returns>The <see cref="WebApplicationBuilder"/>.</returns>
+    public static WebApplicationBuilder CreateSlimBuilder(string[] args) =>
+        new(new() { Args = args }, slim: true);
+
     /// <summary>
     /// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with preconfigured defaults.
     /// </summary>
@@ -114,6 +129,14 @@ public static WebApplicationBuilder CreateBuilder(string[] args) =>
     public static WebApplicationBuilder CreateBuilder(WebApplicationOptions options) =>
         new(options);
 
+    /// <summary>
+    /// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with minimal defaults.
+    /// </summary>
+    /// <param name="options">The <see cref="WebApplicationOptions"/> to configure the <see cref="WebApplicationBuilder"/>.</param>
+    /// <returns>The <see cref="WebApplicationBuilder"/>.</returns>
+    public static WebApplicationBuilder CreateSlimBuilder(WebApplicationOptions options) =>
+        new(options, slim: true);
+
     /// <summary>
     /// Start the application.
     /// </summary>
diff --git a/src/DefaultBuilder/src/WebApplicationBuilder.cs b/src/DefaultBuilder/src/WebApplicationBuilder.cs
index 3da1ac4e83a7..5792ed94169a 100644
--- a/src/DefaultBuilder/src/WebApplicationBuilder.cs
+++ b/src/DefaultBuilder/src/WebApplicationBuilder.cs
@@ -86,6 +86,70 @@ internal WebApplicationBuilder(WebApplicationOptions options, Action<IHostBuilde
         WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services);
     }
 
+    internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<IHostBuilder>? configureDefaults = null)
+    {
+        Debug.Assert(slim, "should only be called with slim: true");
+
+        var configuration = new ConfigurationManager();
+
+        // TODO: Remove when DI no longer has RequiresDynamicCodeAttribute https://github.com/dotnet/runtime/pull/79425
+#pragma warning disable IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
+        _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings
+        {
+            Args = options.Args,
+            ApplicationName = options.ApplicationName,
+            EnvironmentName = options.EnvironmentName,
+            ContentRootPath = options.ContentRootPath,
+            Configuration = configuration,
+        });
+#pragma warning restore IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
+
+        // Set WebRootPath if necessary
+        if (options.WebRootPath is not null)
+        {
+            Configuration.AddInMemoryCollection(new[]
+            {
+                new KeyValuePair<string, string?>(WebHostDefaults.WebRootKey, options.WebRootPath),
+            });
+        }
+
+        // Run methods to configure web host defaults early to populate services
+        var bootstrapHostBuilder = new BootstrapHostBuilder(_hostApplicationBuilder);
+
+        // This is for testing purposes
+        configureDefaults?.Invoke(bootstrapHostBuilder);
+
+        bootstrapHostBuilder.ConfigureSlimWebHost(
+            webHostBuilder =>
+            {
+                AspNetCore.WebHost.UseKestrel(webHostBuilder);
+
+                webHostBuilder.Configure(ConfigureEmptyApplication);
+
+                webHostBuilder.UseSetting(WebHostDefaults.ApplicationKey, _hostApplicationBuilder.Environment.ApplicationName ?? "");
+                webHostBuilder.UseSetting(WebHostDefaults.PreventHostingStartupKey, Configuration[WebHostDefaults.PreventHostingStartupKey]);
+                webHostBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, Configuration[WebHostDefaults.HostingStartupAssembliesKey]);
+                webHostBuilder.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, Configuration[WebHostDefaults.HostingStartupExcludeAssembliesKey]);
+            },
+            options =>
+            {
+                // We've already applied "ASPNETCORE_" environment variables to hosting config
+                options.SuppressEnvironmentConfiguration = true;
+            });
+
+        // This applies the config from ConfigureWebHostDefaults
+        // Grab the GenericWebHostService ServiceDescriptor so we can append it after any user-added IHostedServices during Build();
+        _genericWebHostServiceDescriptor = bootstrapHostBuilder.RunDefaultCallbacks();
+
+        // Grab the WebHostBuilderContext from the property bag to use in the ConfigureWebHostBuilder. Then
+        // grab the IWebHostEnvironment from the webHostContext. This also matches the instance in the IServiceCollection.
+        var webHostContext = (WebHostBuilderContext)bootstrapHostBuilder.Properties[typeof(WebHostBuilderContext)];
+        Environment = webHostContext.HostingEnvironment;
+
+        Host = new ConfigureHostBuilder(bootstrapHostBuilder.Context, Configuration, Services);
+        WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services);
+    }
+
     /// <summary>
     /// Provides information about the web hosting environment an application is running.
     /// </summary>
@@ -133,6 +197,46 @@ public WebApplication Build()
     }
 
     private void ConfigureApplication(WebHostBuilderContext context, IApplicationBuilder app)
+    {
+        ConfigureApplicationCore(
+            context,
+            app,
+            processAuthMiddlewares: () =>
+            {
+                Debug.Assert(_builtApplication is not null);
+
+                // Process authorization and authentication middlewares independently to avoid
+                // registering middlewares for services that do not exist
+                var serviceProviderIsService = _builtApplication.Services.GetService<IServiceProviderIsService>();
+                if (serviceProviderIsService?.IsService(typeof(IAuthenticationSchemeProvider)) is true)
+                {
+                    // Don't add more than one instance of the middleware
+                    if (!_builtApplication.Properties.ContainsKey(AuthenticationMiddlewareSetKey))
+                    {
+                        // The Use invocations will set the property on the outer pipeline,
+                        // but we want to set it on the inner pipeline as well.
+                        _builtApplication.Properties[AuthenticationMiddlewareSetKey] = true;
+                        app.UseAuthentication();
+                    }
+                }
+
+                if (serviceProviderIsService?.IsService(typeof(IAuthorizationHandlerProvider)) is true)
+                {
+                    if (!_builtApplication.Properties.ContainsKey(AuthorizationMiddlewareSetKey))
+                    {
+                        _builtApplication.Properties[AuthorizationMiddlewareSetKey] = true;
+                        app.UseAuthorization();
+                    }
+                }
+            });
+    }
+
+    private void ConfigureEmptyApplication(WebHostBuilderContext context, IApplicationBuilder app)
+    {
+        ConfigureApplicationCore(context, app, processAuthMiddlewares: null);
+    }
+
+    private void ConfigureApplicationCore(WebHostBuilderContext context, IApplicationBuilder app, Action? processAuthMiddlewares)
     {
         Debug.Assert(_builtApplication is not null);
 
@@ -173,29 +277,7 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui
             }
         }
 
-        // Process authorization and authentication middlewares independently to avoid
-        // registering middlewares for services that do not exist
-        var serviceProviderIsService = _builtApplication.Services.GetService<IServiceProviderIsService>();
-        if (serviceProviderIsService?.IsService(typeof(IAuthenticationSchemeProvider)) is true)
-        {
-            // Don't add more than one instance of the middleware
-            if (!_builtApplication.Properties.ContainsKey(AuthenticationMiddlewareSetKey))
-            {
-                // The Use invocations will set the property on the outer pipeline,
-                // but we want to set it on the inner pipeline as well.
-                _builtApplication.Properties[AuthenticationMiddlewareSetKey] = true;
-                app.UseAuthentication();
-            }
-        }
-
-        if (serviceProviderIsService?.IsService(typeof(IAuthorizationHandlerProvider)) is true)
-        {
-            if (!_builtApplication.Properties.ContainsKey(AuthorizationMiddlewareSetKey))
-            {
-                _builtApplication.Properties[AuthorizationMiddlewareSetKey] = true;
-                app.UseAuthorization();
-            }
-        }
+        processAuthMiddlewares?.Invoke();
 
         // Wire the source pipeline to run in the destination pipeline
         app.Use(next =>
diff --git a/src/DefaultBuilder/src/WebHost.cs b/src/DefaultBuilder/src/WebHost.cs
index 156efd0e326e..4a49c3ef8e3c 100644
--- a/src/DefaultBuilder/src/WebHost.cs
+++ b/src/DefaultBuilder/src/WebHost.cs
@@ -222,6 +222,16 @@ internal static void ConfigureWebDefaults(IWebHostBuilder builder)
                 StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);
             }
         });
+
+        UseKestrel(builder);
+
+        builder
+            .UseIIS()
+            .UseIISIntegration();
+    }
+
+    internal static void UseKestrel(IWebHostBuilder builder)
+    {
         builder.UseKestrel((builderContext, options) =>
         {
             options.Configure(builderContext.Configuration.GetSection("Kestrel"), reloadOnChange: true);
@@ -248,9 +258,7 @@ internal static void ConfigureWebDefaults(IWebHostBuilder builder)
             services.AddTransient<IConfigureOptions<ForwardedHeadersOptions>, ForwardedHeadersOptionsSetup>();
 
             services.AddRouting();
-        })
-        .UseIIS()
-        .UseIISIntegration();
+        });
     }
 
     /// <summary>
diff --git a/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs b/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs
index ea386a85e0b2..9d94502ca80f 100644
--- a/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs
+++ b/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs
@@ -36,20 +36,77 @@ namespace Microsoft.AspNetCore.Tests;
 
 public class WebApplicationTests
 {
-    [Fact]
-    public async Task WebApplicationBuilder_New()
+    public delegate WebApplicationBuilder CreateBuilderFunc();
+    public delegate WebApplicationBuilder CreateBuilderArgsFunc(string[] args);
+    public delegate WebApplicationBuilder CreateBuilderOptionsFunc(WebApplicationOptions options);
+    public delegate WebApplicationBuilder WebApplicationBuilderConstructorFunc(WebApplicationOptions options, Action<IHostBuilder> configureDefaults);
+
+    private static WebApplicationBuilder CreateBuilder() => WebApplication.CreateBuilder();
+    private static WebApplicationBuilder CreateSlimBuilder() => WebApplication.CreateSlimBuilder();
+
+    public static IEnumerable<object[]> CreateBuilderFuncs
+    {
+        get
+        {
+            yield return new[] { (CreateBuilderFunc)CreateBuilder };
+            yield return new[] { (CreateBuilderFunc)CreateSlimBuilder };
+        }
+    }
+
+    private static WebApplicationBuilder CreateBuilderArgs(string[] args) => WebApplication.CreateBuilder(args);
+    private static WebApplicationBuilder CreateSlimBuilderArgs(string[] args) => WebApplication.CreateSlimBuilder(args);
+
+    public static IEnumerable<object[]> CreateBuilderArgsFuncs
+    {
+        get
+        {
+            yield return new[] { (CreateBuilderArgsFunc)CreateBuilderArgs };
+            yield return new[] { (CreateBuilderArgsFunc)CreateSlimBuilderArgs };
+        }
+    }
+
+    private static WebApplicationBuilder CreateBuilderOptions(WebApplicationOptions options) => WebApplication.CreateBuilder(options);
+    private static WebApplicationBuilder CreateSlimBuilderOptions(WebApplicationOptions options) => WebApplication.CreateSlimBuilder(options);
+
+    public static IEnumerable<object[]> CreateBuilderOptionsFuncs
+    {
+        get
+        {
+            yield return new[] { (CreateBuilderOptionsFunc)CreateBuilderOptions };
+            yield return new[] { (CreateBuilderOptionsFunc)CreateSlimBuilderOptions };
+        }
+    }
+
+    private static WebApplicationBuilder WebApplicationBuilderConstructor(WebApplicationOptions options, Action<IHostBuilder> configureDefaults)
+        => new WebApplicationBuilder(options, configureDefaults);
+    private static WebApplicationBuilder WebApplicationSlimBuilderConstructor(WebApplicationOptions options, Action<IHostBuilder> configureDefaults)
+        => new WebApplicationBuilder(options, slim: true, configureDefaults);
+
+    public static IEnumerable<object[]> WebApplicationBuilderConstructorFuncs
+    {
+        get
+        {
+            yield return new[] { (WebApplicationBuilderConstructorFunc)WebApplicationBuilderConstructor };
+            yield return new[] { (WebApplicationBuilderConstructorFunc)WebApplicationSlimBuilderConstructor };
+        }
+    }
+
+    [Theory]
+    [MemberData(nameof(CreateBuilderArgsFuncs))]
+    public async Task WebApplicationBuilder_New(CreateBuilderArgsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new string[] { "--urls", "http://localhost:5001" });
+        var builder = createBuilder(new string[] { "--urls", "http://localhost:5001" });
 
         await using var app = builder.Build();
         var newApp = (app as IApplicationBuilder).New();
         Assert.NotNull(newApp.ServerFeatures);
     }
 
-    [Fact]
-    public async Task WebApplicationBuilderConfiguration_IncludesCommandLineArguments()
+    [Theory]
+    [MemberData(nameof(CreateBuilderArgsFuncs))]
+    public async Task WebApplicationBuilderConfiguration_IncludesCommandLineArguments(CreateBuilderArgsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new string[] { "--urls", "http://localhost:5001" });
+        var builder = createBuilder(new string[] { "--urls", "http://localhost:5001" });
         Assert.Equal("http://localhost:5001", builder.Configuration["urls"]);
 
         var urls = new List<string>();
@@ -68,10 +125,11 @@ public async Task WebApplicationBuilderConfiguration_IncludesCommandLineArgument
         Assert.Equal("http://localhost:5001", url);
     }
 
-    [Fact]
-    public async Task WebApplicationRunAsync_UsesDefaultUrls()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationRunAsync_UsesDefaultUrls(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         var urls = new List<string>();
         var server = new MockAddressesServer(urls);
         builder.Services.AddSingleton<IServer>(server);
@@ -86,10 +144,11 @@ public async Task WebApplicationRunAsync_UsesDefaultUrls()
         Assert.Equal("https://localhost:5001", urls[1]);
     }
 
-    [Fact]
-    public async Task WebApplicationRunUrls_UpdatesIServerAddressesFeature()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationRunUrls_UpdatesIServerAddressesFeature(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         var urls = new List<string>();
         var server = new MockAddressesServer(urls);
         builder.Services.AddSingleton<IServer>(server);
@@ -104,10 +163,11 @@ public async Task WebApplicationRunUrls_UpdatesIServerAddressesFeature()
         await runTask;
     }
 
-    [Fact]
-    public async Task WebApplicationUrls_UpdatesIServerAddressesFeature()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationUrls_UpdatesIServerAddressesFeature(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         var urls = new List<string>();
         var server = new MockAddressesServer(urls);
         builder.Services.AddSingleton<IServer>(server);
@@ -123,10 +183,11 @@ public async Task WebApplicationUrls_UpdatesIServerAddressesFeature()
         Assert.Equal("https://localhost:5003", urls[1]);
     }
 
-    [Fact]
-    public async Task WebApplicationRunUrls_OverridesIServerAddressesFeature()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationRunUrls_OverridesIServerAddressesFeature(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         var urls = new List<string>();
         var server = new MockAddressesServer(urls);
         builder.Services.AddSingleton<IServer>(server);
@@ -144,20 +205,22 @@ public async Task WebApplicationRunUrls_OverridesIServerAddressesFeature()
         await runTask;
     }
 
-    [Fact]
-    public async Task WebApplicationUrls_ThrowsInvalidOperationExceptionIfThereIsNoIServerAddressesFeature()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationUrls_ThrowsInvalidOperationExceptionIfThereIsNoIServerAddressesFeature(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.Services.AddSingleton<IServer>(new MockAddressesServer());
         await using var app = builder.Build();
 
         Assert.Throws<InvalidOperationException>(() => app.Urls);
     }
 
-    [Fact]
-    public async Task HostedServicesRunBeforeTheServerStarts()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task HostedServicesRunBeforeTheServerStarts(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         var startOrder = new List<object>();
         var server = new MockServer(startOrder);
         var hostedService = new HostedService(startOrder);
@@ -215,42 +278,47 @@ public Task StopAsync(CancellationToken cancellationToken)
         }
     }
 
-    [Fact]
-    public async Task WebApplicationRunUrls_ThrowsInvalidOperationExceptionIfThereIsNoIServerAddressesFeature()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationRunUrls_ThrowsInvalidOperationExceptionIfThereIsNoIServerAddressesFeature(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.Services.AddSingleton<IServer>(new MockAddressesServer());
         await using var app = builder.Build();
 
         await Assert.ThrowsAsync<InvalidOperationException>(() => app.RunAsync("http://localhost:5001"));
     }
 
-    [Fact]
-    public async Task WebApplicationRunUrls_ThrowsInvalidOperationExceptionIfServerAddressesFeatureIsReadOnly()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationRunUrls_ThrowsInvalidOperationExceptionIfServerAddressesFeatureIsReadOnly(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.Services.AddSingleton<IServer>(new MockAddressesServer(new List<string>().AsReadOnly()));
         await using var app = builder.Build();
 
         await Assert.ThrowsAsync<InvalidOperationException>(() => app.RunAsync("http://localhost:5001"));
     }
 
-    [Fact]
-    public void WebApplicationBuilderHost_ThrowsWhenBuiltDirectly()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilderHost_ThrowsWhenBuiltDirectly(CreateBuilderFunc createBuilder)
     {
-        Assert.Throws<NotSupportedException>(() => ((IHostBuilder)WebApplication.CreateBuilder().Host).Build());
+        Assert.Throws<NotSupportedException>(() => ((IHostBuilder)createBuilder().Host).Build());
     }
 
-    [Fact]
-    public void WebApplicationBuilderWebHost_ThrowsWhenBuiltDirectly()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilderWebHost_ThrowsWhenBuiltDirectly(CreateBuilderFunc createBuilder)
     {
-        Assert.Throws<NotSupportedException>(() => ((IWebHostBuilder)WebApplication.CreateBuilder().WebHost).Build());
+        Assert.Throws<NotSupportedException>(() => ((IWebHostBuilder)createBuilder().WebHost).Build());
     }
 
-    [Fact]
-    public void WebApplicationBuilderWebHostSettingsThatAffectTheHostCannotBeModified()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilderWebHostSettingsThatAffectTheHostCannotBeModified(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         var webRoot = Path.Combine(contentRoot, "wwwroot");
@@ -266,10 +334,11 @@ public void WebApplicationBuilderWebHostSettingsThatAffectTheHostCannotBeModifie
         Assert.Throws<NotSupportedException>(() => builder.WebHost.UseContentRoot(contentRoot));
     }
 
-    [Fact]
-    public void WebApplicationBuilderWebHostSettingsThatAffectTheHostCannotBeModifiedViaConfigureAppConfiguration()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilderWebHostSettingsThatAffectTheHostCannotBeModifiedViaConfigureAppConfiguration(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         var webRoot = Path.Combine(contentRoot, "wwwroot");
@@ -324,13 +393,14 @@ public void WebApplicationBuilderWebHostSettingsThatAffectTheHostCannotBeModifie
         }));
     }
 
-    [Fact]
-    public void SettingContentRootToSameCanonicalValueWorks()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public void SettingContentRootToSameCanonicalValueWorks(CreateBuilderOptionsFunc createBuilder)
     {
         var contentRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
         Directory.CreateDirectory(contentRoot);
 
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions
+        var builder = createBuilder(new WebApplicationOptions
         {
             ContentRootPath = contentRoot
         });
@@ -344,13 +414,21 @@ public void SettingContentRootToSameCanonicalValueWorks()
         builder.WebHost.UseContentRoot(contentRoot.ToLowerInvariant());
     }
 
+    public static IEnumerable<object[]> CanHandleVariousWebRootPathsData
+    {
+        get
+        {
+            foreach (string webRoot in new[] { "wwwroot2", "./wwwroot2", "./bar/../wwwroot2", "foo/../wwwroot2", "wwwroot2/." })
+            {
+                yield return new object[] { webRoot, (CreateBuilderOptionsFunc)CreateBuilderOptions };
+                yield return new object[] { webRoot, (CreateBuilderOptionsFunc)CreateSlimBuilderOptions };
+            }
+        }
+    }
+
     [Theory]
-    [InlineData("wwwroot2")]
-    [InlineData("./wwwroot2")]
-    [InlineData("./bar/../wwwroot2")]
-    [InlineData("foo/../wwwroot2")]
-    [InlineData("wwwroot2/.")]
-    public void WebApplicationBuilder_CanHandleVariousWebRootPaths(string webRoot)
+    [MemberData(nameof(CanHandleVariousWebRootPathsData))]
+    public void WebApplicationBuilder_CanHandleVariousWebRootPaths(string webRoot, CreateBuilderOptionsFunc createBuilder)
     {
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         Directory.CreateDirectory(contentRoot);
@@ -364,7 +442,7 @@ public void WebApplicationBuilder_CanHandleVariousWebRootPaths(string webRoot)
                 WebRootPath = "wwwroot2"
             };
 
-            var builder = new WebApplicationBuilder(options);
+            var builder = createBuilder(options);
 
             Assert.Equal(contentRoot, builder.Environment.ContentRootPath);
             Assert.Equal(fullWebRootPath, builder.Environment.WebRootPath);
@@ -377,8 +455,9 @@ public void WebApplicationBuilder_CanHandleVariousWebRootPaths(string webRoot)
         }
     }
 
-    [Fact]
-    public void WebApplicationBuilder_CanOverrideWithFullWebRootPaths()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public void WebApplicationBuilder_CanOverrideWithFullWebRootPaths(CreateBuilderOptionsFunc createBuilder)
     {
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         Directory.CreateDirectory(contentRoot);
@@ -392,7 +471,7 @@ public void WebApplicationBuilder_CanOverrideWithFullWebRootPaths()
                 ContentRootPath = contentRoot,
             };
 
-            var builder = new WebApplicationBuilder(options);
+            var builder = createBuilder(options);
 
             Assert.Equal(contentRoot, builder.Environment.ContentRootPath);
             Assert.Equal(fullWebRootPath, builder.Environment.WebRootPath);
@@ -405,13 +484,21 @@ public void WebApplicationBuilder_CanOverrideWithFullWebRootPaths()
         }
     }
 
+    public static IEnumerable<object[]> CanHandleVariousWebRootPaths_OverrideDefaultPathData
+    {
+        get
+        {
+            foreach (string webRoot in new[] { "wwwroot", "./wwwroot", "./bar/../wwwroot", "foo/../wwwroot", "wwwroot/." })
+            {
+                yield return new object[] { webRoot, (CreateBuilderOptionsFunc)CreateBuilderOptions };
+                yield return new object[] { webRoot, (CreateBuilderOptionsFunc)CreateSlimBuilderOptions };
+            }
+        }
+    }
+
     [Theory]
-    [InlineData("wwwroot")]
-    [InlineData("./wwwroot")]
-    [InlineData("./bar/../wwwroot")]
-    [InlineData("foo/../wwwroot")]
-    [InlineData("wwwroot/.")]
-    public void WebApplicationBuilder_CanHandleVariousWebRootPaths_OverrideDefaultPath(string webRoot)
+    [MemberData(nameof(CanHandleVariousWebRootPaths_OverrideDefaultPathData))]
+    public void WebApplicationBuilder_CanHandleVariousWebRootPaths_OverrideDefaultPath(string webRoot, CreateBuilderOptionsFunc createBuilder)
     {
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         Directory.CreateDirectory(contentRoot);
@@ -425,7 +512,7 @@ public void WebApplicationBuilder_CanHandleVariousWebRootPaths_OverrideDefaultPa
                 ContentRootPath = contentRoot
             };
 
-            var builder = new WebApplicationBuilder(options);
+            var builder = createBuilder(options);
 
             Assert.Equal(contentRoot, builder.Environment.ContentRootPath);
             Assert.Equal(fullWebRootPath, builder.Environment.WebRootPath);
@@ -438,12 +525,24 @@ public void WebApplicationBuilder_CanHandleVariousWebRootPaths_OverrideDefaultPa
         }
     }
 
+    public static IEnumerable<object[]> SettingContentRootToRelativePathData
+    {
+        get
+        {
+            // Empty behaves differently to null
+            foreach (string path in new[] { "", "." })
+            {
+                yield return new object[] { path, (CreateBuilderOptionsFunc)CreateBuilderOptions };
+                yield return new object[] { path, (CreateBuilderOptionsFunc)CreateSlimBuilderOptions };
+            }
+        }
+    }
+
     [Theory]
-    [InlineData("")]  // Empty behaves differently to null
-    [InlineData(".")]
-    public void SettingContentRootToRelativePathUsesAppContextBaseDirectoryAsPathBase(string path)
+    [MemberData(nameof(SettingContentRootToRelativePathData))]
+    public void SettingContentRootToRelativePathUsesAppContextBaseDirectoryAsPathBase(string path, CreateBuilderOptionsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions
+        var builder = createBuilder(new WebApplicationOptions
         {
             ContentRootPath = path
         });
@@ -462,8 +561,9 @@ static string NormalizePath(string unnormalizedPath) =>
             Path.TrimEndingDirectorySeparator(Path.GetFullPath(unnormalizedPath));
     }
 
-    [Fact]
-    public void WebApplicationBuilderSettingInvalidApplicationDoesNotThrowWhenAssemblyLoadForUserSecretsFail()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public void WebApplicationBuilderSettingInvalidApplicationDoesNotThrowWhenAssemblyLoadForUserSecretsFail(CreateBuilderOptionsFunc createBuilder)
     {
         var options = new WebApplicationOptions
         {
@@ -472,14 +572,15 @@ public void WebApplicationBuilderSettingInvalidApplicationDoesNotThrowWhenAssemb
         };
 
         // Use secrets fails to load an invalid assembly name but does not throw
-        var webApplication = WebApplication.CreateBuilder(options).Build();
+        var webApplication = createBuilder(options).Build();
 
         Assert.Equal(nameof(WebApplicationTests), webApplication.Environment.ApplicationName);
         Assert.Equal(Environments.Development, webApplication.Environment.EnvironmentName);
     }
 
-    [Fact]
-    public void WebApplicationBuilderCanConfigureHostSettingsUsingWebApplicationOptions()
+    [Theory]
+    [MemberData(nameof(WebApplicationBuilderConstructorFuncs))]
+    public void WebApplicationBuilderCanConfigureHostSettingsUsingWebApplicationOptions(WebApplicationBuilderConstructorFunc createBuilder)
     {
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         Directory.CreateDirectory(contentRoot);
@@ -497,7 +598,7 @@ public void WebApplicationBuilderCanConfigureHostSettingsUsingWebApplicationOpti
                 WebRootPath = webRoot
             };
 
-            var builder = new WebApplicationBuilder(
+            var builder = createBuilder(
                 options,
                 bootstrapBuilder =>
                 {
@@ -520,8 +621,9 @@ public void WebApplicationBuilderCanConfigureHostSettingsUsingWebApplicationOpti
         }
     }
 
-    [Fact]
-    public void WebApplicationBuilderWebApplicationOptionsPropertiesOverridesArgs()
+    [Theory]
+    [MemberData(nameof(WebApplicationBuilderConstructorFuncs))]
+    public void WebApplicationBuilderWebApplicationOptionsPropertiesOverridesArgs(WebApplicationBuilderConstructorFunc createBuilder)
     {
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         Directory.CreateDirectory(contentRoot);
@@ -545,7 +647,7 @@ public void WebApplicationBuilderWebApplicationOptionsPropertiesOverridesArgs()
                 WebRootPath = webRoot
             };
 
-            var builder = new WebApplicationBuilder(
+            var builder = createBuilder(
                 options,
                 bootstrapBuilder =>
                 {
@@ -568,8 +670,9 @@ public void WebApplicationBuilderWebApplicationOptionsPropertiesOverridesArgs()
         }
     }
 
-    [Fact]
-    public void WebApplicationBuilderCanConfigureHostSettingsUsingWebApplicationOptionsArgs()
+    [Theory]
+    [MemberData(nameof(WebApplicationBuilderConstructorFuncs))]
+    public void WebApplicationBuilderCanConfigureHostSettingsUsingWebApplicationOptionsArgs(WebApplicationBuilderConstructorFunc createBuilder)
     {
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         Directory.CreateDirectory(contentRoot);
@@ -590,7 +693,7 @@ public void WebApplicationBuilderCanConfigureHostSettingsUsingWebApplicationOpti
                     }
             };
 
-            var builder = new WebApplicationBuilder(
+            var builder = createBuilder(
                 options,
                 bootstrapBuilder =>
                 {
@@ -613,12 +716,13 @@ public void WebApplicationBuilderCanConfigureHostSettingsUsingWebApplicationOpti
         }
     }
 
-    [Fact]
-    public void WebApplicationBuilderApplicationNameDefaultsToEntryAssembly()
+    [Theory]
+    [MemberData(nameof(WebApplicationBuilderConstructorFuncs))]
+    public void WebApplicationBuilderApplicationNameDefaultsToEntryAssembly(WebApplicationBuilderConstructorFunc createBuilder)
     {
         var assemblyName = Assembly.GetEntryAssembly().GetName().Name;
 
-        var builder = new WebApplicationBuilder(
+        var builder = createBuilder(
             new(),
             bootstrapBuilder =>
             {
@@ -649,8 +753,9 @@ public void WebApplicationBuilderApplicationNameDefaultsToEntryAssembly()
         Assert.Equal(assemblyName, webHostEnv.ApplicationName);
     }
 
-    [Fact]
-    public void WebApplicationBuilderApplicationNameCanBeOverridden()
+    [Theory]
+    [MemberData(nameof(WebApplicationBuilderConstructorFuncs))]
+    public void WebApplicationBuilderApplicationNameCanBeOverridden(WebApplicationBuilderConstructorFunc createBuilder)
     {
         var assemblyName = typeof(WebApplicationTests).Assembly.GetName().Name;
 
@@ -659,7 +764,7 @@ public void WebApplicationBuilderApplicationNameCanBeOverridden()
             ApplicationName = assemblyName
         };
 
-        var builder = new WebApplicationBuilder(
+        var builder = createBuilder(
             options,
             bootstrapBuilder =>
             {
@@ -690,10 +795,11 @@ public void WebApplicationBuilderApplicationNameCanBeOverridden()
         Assert.Equal(assemblyName, webHostEnv.ApplicationName);
     }
 
-    [Fact]
-    public void WebApplicationBuilderCanFlowCommandLineConfigurationToApplication()
+    [Theory]
+    [MemberData(nameof(CreateBuilderArgsFuncs))]
+    public void WebApplicationBuilderCanFlowCommandLineConfigurationToApplication(CreateBuilderArgsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new[] { "--x=1", "--name=Larry", "--age=20", "--environment=Testing" });
+        var builder = createBuilder(new[] { "--x=1", "--name=Larry", "--age=20", "--environment=Testing" });
 
         Assert.Equal("1", builder.Configuration["x"]);
         Assert.Equal("Larry", builder.Configuration["name"]);
@@ -723,10 +829,11 @@ public void WebApplicationBuilderCanFlowCommandLineConfigurationToApplication()
         Assert.Equal("Testing", app.Configuration["environment"]);
     }
 
-    [Fact]
-    public void WebApplicationBuilderHostBuilderSettingsThatAffectTheHostCannotBeModified()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilderHostBuilderSettingsThatAffectTheHostCannotBeModified(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var contentRoot = Path.GetTempPath().ToString();
         var envName = $"{nameof(WebApplicationTests)}_ENV";
@@ -743,10 +850,11 @@ public void WebApplicationBuilderHostBuilderSettingsThatAffectTheHostCannotBeMod
         Assert.Throws<NotSupportedException>(() => builder.Host.UseContentRoot(contentRoot));
     }
 
-    [Fact]
-    public void WebApplicationBuilderWebHostUseSettingCanBeReadByConfiguration()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilderWebHostUseSettingCanBeReadByConfiguration(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         builder.WebHost.UseSetting("A", "value");
         builder.WebHost.UseSetting("B", "another");
@@ -763,8 +871,9 @@ public void WebApplicationBuilderWebHostUseSettingCanBeReadByConfiguration()
         Assert.Equal("another", builder.Configuration["B"]);
     }
 
-    [Fact]
-    public async Task WebApplicationCanObserveConfigurationChangesMadeInBuild()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationCanObserveConfigurationChangesMadeInBuild(CreateBuilderFunc createBuilder)
     {
         // This mimics what WebApplicationFactory<T> does and runs configure
         // services callbacks
@@ -802,7 +911,7 @@ public async Task WebApplicationCanObserveConfigurationChangesMadeInBuild()
             });
         });
 
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         await using var app = builder.Build();
 
@@ -821,8 +930,9 @@ public async Task WebApplicationCanObserveConfigurationChangesMadeInBuild()
         Assert.Equal("F", builder.Configuration["F"]);
     }
 
-    [Fact]
-    public async Task WebApplicationCanObserveSourcesClearedInBuild()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationCanObserveSourcesClearedInBuild(CreateBuilderFunc createBuilder)
     {
         // This mimics what WebApplicationFactory<T> does and runs configure
         // services callbacks
@@ -847,7 +957,7 @@ public async Task WebApplicationCanObserveSourcesClearedInBuild()
             });
         });
 
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         builder.Configuration.AddInMemoryCollection(new Dictionary<string, string>()
             {
@@ -864,8 +974,9 @@ public async Task WebApplicationCanObserveSourcesClearedInBuild()
         Assert.Same(builder.Configuration, app.Configuration);
     }
 
-    [Fact]
-    public async Task WebApplicationCanObserveSourcesClearedInConfiguratHostConfiguration()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public async Task WebApplicationCanObserveSourcesClearedInConfiguratHostConfiguration(CreateBuilderOptionsFunc createBuilder)
     {
         // This mimics what WebApplicationFactory<T> does and runs configure
         // services callbacks
@@ -885,7 +996,7 @@ public async Task WebApplicationCanObserveSourcesClearedInConfiguratHostConfigur
             });
         });
 
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions
+        var builder = createBuilder(new WebApplicationOptions
         {
             ApplicationName = "appName",
             EnvironmentName = "environmentName",
@@ -906,8 +1017,9 @@ public async Task WebApplicationCanObserveSourcesClearedInConfiguratHostConfigur
         Assert.Same(builder.Configuration, app.Configuration);
     }
 
-    [Fact]
-    public async Task WebApplicationCanHandleStreamBackedConfigurationAddedInBuild()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationCanHandleStreamBackedConfigurationAddedInBuild(CreateBuilderFunc createBuilder)
     {
         static Stream CreateStreamFromString(string data) => new MemoryStream(Encoding.UTF8.GetBytes(data));
 
@@ -922,7 +1034,7 @@ public async Task WebApplicationCanHandleStreamBackedConfigurationAddedInBuild()
             hostBuilder.ConfigureAppConfiguration(config => config.AddJsonStream(jsonBStream));
         });
 
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         await using var app = builder.Build();
 
         Assert.Equal("A", app.Configuration["A"]);
@@ -931,8 +1043,9 @@ public async Task WebApplicationCanHandleStreamBackedConfigurationAddedInBuild()
         Assert.Same(builder.Configuration, app.Configuration);
     }
 
-    [Fact]
-    public async Task WebApplicationDisposesConfigurationProvidersAddedInBuild()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationDisposesConfigurationProvidersAddedInBuild(CreateBuilderFunc createBuilder)
     {
         var hostConfigSource = new RandomConfigurationSource();
         var appConfigSource = new RandomConfigurationSource();
@@ -945,7 +1058,7 @@ public async Task WebApplicationDisposesConfigurationProvidersAddedInBuild()
             hostBuilder.ConfigureAppConfiguration(config => config.Add(appConfigSource));
         });
 
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         {
             await using var app = builder.Build();
@@ -966,8 +1079,9 @@ public async Task WebApplicationDisposesConfigurationProvidersAddedInBuild()
         Assert.Equal(1, appConfigSource.ProvidersDisposed);
     }
 
-    [Fact]
-    public async Task WebApplicationMakesOriginalConfigurationProvidersAddedInBuildAccessable()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationMakesOriginalConfigurationProvidersAddedInBuildAccessable(CreateBuilderFunc createBuilder)
     {
         // This mimics what WebApplicationFactory<T> does and runs configure
         // services callbacks
@@ -976,16 +1090,17 @@ public async Task WebApplicationMakesOriginalConfigurationProvidersAddedInBuildA
             hostBuilder.ConfigureAppConfiguration(config => config.Add(new RandomConfigurationSource()));
         });
 
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         await using var app = builder.Build();
 
         Assert.Single(((IConfigurationRoot)app.Configuration).Providers.OfType<RandomConfigurationProvider>());
     }
 
-    [Fact]
-    public void WebApplicationBuilderHostProperties_IsCaseSensitive()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilderHostProperties_IsCaseSensitive(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         builder.Host.Properties["lowercase"] = nameof(WebApplicationTests);
 
@@ -993,10 +1108,11 @@ public void WebApplicationBuilderHostProperties_IsCaseSensitive()
         Assert.False(builder.Host.Properties.ContainsKey("Lowercase"));
     }
 
-    [Fact]
-    public async Task WebApplicationConfiguration_HostFilterOptionsAreReloadable()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationConfiguration_HostFilterOptionsAreReloadable(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         var host = builder.WebHost
             .ConfigureAppConfiguration(configBuilder =>
             {
@@ -1023,10 +1139,11 @@ public async Task WebApplicationConfiguration_HostFilterOptionsAreReloadable()
         Assert.Contains("NewHost", options.AllowedHosts);
     }
 
-    [Fact]
-    public void CanResolveIConfigurationBeforeBuildingApplication()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void CanResolveIConfigurationBeforeBuildingApplication(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         var sp = builder.Services.BuildServiceProvider();
 
         var config = sp.GetService<IConfiguration>();
@@ -1038,10 +1155,11 @@ public void CanResolveIConfigurationBeforeBuildingApplication()
         Assert.Same(app.Configuration, builder.Configuration);
     }
 
-    [Fact]
-    public void ManuallyAddingConfigurationAsServiceWorks()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void ManuallyAddingConfigurationAsServiceWorks(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
         var sp = builder.Services.BuildServiceProvider();
 
@@ -1054,10 +1172,11 @@ public void ManuallyAddingConfigurationAsServiceWorks()
         Assert.Same(app.Configuration, builder.Configuration);
     }
 
-    [Fact]
-    public void AddingMemoryStreamBackedConfigurationWorks()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void AddingMemoryStreamBackedConfigurationWorks(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var jsonConfig = @"{ ""foo"": ""bar"" }";
         using var ms = new MemoryStream();
@@ -1075,10 +1194,11 @@ public void AddingMemoryStreamBackedConfigurationWorks()
         Assert.Equal("bar", app.Configuration["foo"]);
     }
 
-    [Fact]
-    public async Task WebApplicationConfiguration_EnablesForwardedHeadersFromConfig()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationConfiguration_EnablesForwardedHeadersFromConfig(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         builder.Configuration["FORWARDEDHEADERS_ENABLED"] = "true";
         await using var app = builder.Build();
@@ -1105,10 +1225,11 @@ public void WebApplicationCreate_RegistersRouting()
         Assert.NotNull(linkGenerator);
     }
 
-    [Fact]
-    public void WebApplication_CanResolveDefaultServicesFromServiceCollection()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplication_CanResolveDefaultServicesFromServiceCollection(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         // Add the service collection to the service collection
         builder.Services.AddSingleton(builder.Services);
@@ -1124,8 +1245,9 @@ public void WebApplication_CanResolveDefaultServicesFromServiceCollection()
         Assert.Equal(env0.ContentRootPath, env1.ContentRootPath);
     }
 
-    [Fact]
-    public async Task WebApplication_CanResolveServicesAddedAfterBuildFromServiceCollection()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplication_CanResolveServicesAddedAfterBuildFromServiceCollection(CreateBuilderFunc createBuilder)
     {
         // This mimics what WebApplicationFactory<T> does and runs configure
         // services callbacks
@@ -1137,7 +1259,7 @@ public async Task WebApplication_CanResolveServicesAddedAfterBuildFromServiceCol
             });
         });
 
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         // Add the service collection to the service collection
         builder.Services.AddSingleton(builder.Services);
@@ -1152,10 +1274,11 @@ public async Task WebApplication_CanResolveServicesAddedAfterBuildFromServiceCol
         Assert.IsType<Service>(service1);
     }
 
-    [Fact]
-    public async Task WebApplication_CanResolveIConfigurationFromServiceCollection()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplication_CanResolveIConfigurationFromServiceCollection(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         builder.Configuration.AddInMemoryCollection(new Dictionary<string, string>
         {
@@ -1178,10 +1301,11 @@ public async Task WebApplication_CanResolveIConfigurationFromServiceCollection()
         Assert.Equal("bar", app.Configuration["foo"]);
     }
 
-    [Fact]
-    public void WebApplication_CanResolveDefaultServicesFromServiceCollectionInCorrectOrder()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplication_CanResolveDefaultServicesFromServiceCollectionInCorrectOrder(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         // Add the service collection to the service collection
         builder.Services.AddSingleton(builder.Services);
@@ -1205,10 +1329,11 @@ public void WebApplication_CanResolveDefaultServicesFromServiceCollectionInCorre
         Assert.Equal(hostLifetimes1.Length, hostLifetimes0.Length);
     }
 
-    [Fact]
-    public async Task WebApplication_CanCallUseRoutingWithoutUseEndpoints()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplication_CanCallUseRoutingWithoutUseEndpoints(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1243,10 +1368,11 @@ public async Task WebApplication_CanCallUseRoutingWithoutUseEndpoints()
         Assert.Equal("new", await oldResult.Content.ReadAsStringAsync());
     }
 
-    [Fact]
-    public async Task WebApplication_CanCallUseEndpointsWithoutUseRoutingFails()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplication_CanCallUseEndpointsWithoutUseRoutingFails(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1272,11 +1398,12 @@ public void WebApplicationCreate_RegistersEventSourceLogger()
             args.Payload.OfType<string>().Any(p => p.Contains(guid)));
     }
 
-    [Fact]
-    public void WebApplicationBuilder_CanClearDefaultLoggers()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilder_CanClearDefaultLoggers(CreateBuilderFunc createBuilder)
     {
         var listener = new TestEventListener();
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.Logging.ClearProviders();
 
         var app = builder.Build();
@@ -1291,10 +1418,11 @@ public void WebApplicationBuilder_CanClearDefaultLoggers()
             args.Payload.OfType<string>().Any(p => p.Contains(guid)));
     }
 
-    [Fact]
-    public async Task WebApplicationBuilder_StartupFilterCanAddTerminalMiddleware()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationBuilder_StartupFilterCanAddTerminalMiddleware(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         builder.Services.AddSingleton<IStartupFilter, TerminalMiddlewareStartupFilter>();
         await using var app = builder.Build();
@@ -1312,10 +1440,11 @@ public async Task WebApplicationBuilder_StartupFilterCanAddTerminalMiddleware()
         Assert.Equal(418, (int)terminalResult.StatusCode);
     }
 
-    [Fact]
-    public async Task StartupFilter_WithUseRoutingWorks()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task StartupFilter_WithUseRoutingWorks(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         builder.Services.AddSingleton<IStartupFilter, UseRoutingStartupFilter>();
         await using var app = builder.Build();
@@ -1338,10 +1467,11 @@ public async Task StartupFilter_WithUseRoutingWorks()
         Assert.Equal(203, ((int)response.StatusCode));
     }
 
-    [Fact]
-    public async Task CanAddMiddlewareBeforeUseRouting()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task CanAddMiddlewareBeforeUseRouting(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1375,10 +1505,11 @@ public async Task CanAddMiddlewareBeforeUseRouting()
         Assert.Equal("One", chosenEndpoint);
     }
 
-    [Fact]
-    public async Task WebApplicationBuilder_OnlyAddsDefaultServicesOnce()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationBuilder_OnlyAddsDefaultServicesOnce(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         // IWebHostEnvironment is added by ConfigureDefaults
         Assert.Single(builder.Services.Where(descriptor => descriptor.ServiceType == typeof(IConfigureOptions<LoggerFactoryOptions>)));
@@ -1395,11 +1526,12 @@ public async Task WebApplicationBuilder_OnlyAddsDefaultServicesOnce()
         Assert.Single(app.Services.GetRequiredService<IEnumerable<IServer>>());
     }
 
-    [Fact]
-    public void WebApplicationBuilder_EnablesServiceScopeValidationByDefaultInDevelopment()
+    [Theory]
+    [MemberData(nameof(CreateBuilderArgsFuncs))]
+    public void WebApplicationBuilder_EnablesServiceScopeValidationByDefaultInDevelopment(CreateBuilderArgsFunc createBuilder)
     {
         // The environment cannot be reconfigured after the builder is created currently.
-        var builder = WebApplication.CreateBuilder(new[] { "--environment", "Development" });
+        var builder = createBuilder(new[] { "--environment", "Development" });
 
         builder.Services.AddScoped<Service>();
         builder.Services.AddSingleton<Service2>();
@@ -1409,10 +1541,11 @@ public void WebApplicationBuilder_EnablesServiceScopeValidationByDefaultInDevelo
         Assert.ThrowsAny<Exception>(() => builder.Build());
     }
 
-    [Fact]
-    public async Task WebApplicationBuilder_ThrowsExceptionIfServicesAlreadyBuilt()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplicationBuilder_ThrowsExceptionIfServicesAlreadyBuilt(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         await using var app = builder.Build();
 
         Assert.Throws<InvalidOperationException>(() => builder.Services.AddSingleton<IService>(new Service()));
@@ -1423,10 +1556,11 @@ public async Task WebApplicationBuilder_ThrowsExceptionIfServicesAlreadyBuilt()
         Assert.Throws<InvalidOperationException>(() => builder.Services[0] = ServiceDescriptor.Singleton(new Service()));
     }
 
-    [Fact]
-    public void WebApplicationBuilder_ThrowsFromExtensionMethodsNotSupportedByHostAndWebHost()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void WebApplicationBuilder_ThrowsFromExtensionMethodsNotSupportedByHostAndWebHost(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var ex = Assert.Throws<NotSupportedException>(() => builder.WebHost.Configure(app => { }));
         var ex1 = Assert.Throws<NotSupportedException>(() => builder.WebHost.Configure((context, app) => { }));
@@ -1442,17 +1576,20 @@ public void WebApplicationBuilder_ThrowsFromExtensionMethodsNotSupportedByHostAn
 
         var ex5 = Assert.Throws<NotSupportedException>(() => builder.Host.ConfigureWebHost(webHostBuilder => { }));
         var ex6 = Assert.Throws<NotSupportedException>(() => builder.Host.ConfigureWebHost(webHostBuilder => { }, options => { }));
-        var ex7 = Assert.Throws<NotSupportedException>(() => builder.Host.ConfigureWebHostDefaults(webHostBuilder => { }));
+        var ex7 = Assert.Throws<NotSupportedException>(() => builder.Host.ConfigureSlimWebHost(webHostBuilder => { }, options => { }));
+        var ex8 = Assert.Throws<NotSupportedException>(() => builder.Host.ConfigureWebHostDefaults(webHostBuilder => { }));
 
         Assert.Equal("ConfigureWebHost() is not supported by WebApplicationBuilder.Host. Use the WebApplication returned by WebApplicationBuilder.Build() instead.", ex5.Message);
         Assert.Equal("ConfigureWebHost() is not supported by WebApplicationBuilder.Host. Use the WebApplication returned by WebApplicationBuilder.Build() instead.", ex6.Message);
         Assert.Equal("ConfigureWebHost() is not supported by WebApplicationBuilder.Host. Use the WebApplication returned by WebApplicationBuilder.Build() instead.", ex7.Message);
+        Assert.Equal("ConfigureWebHost() is not supported by WebApplicationBuilder.Host. Use the WebApplication returned by WebApplicationBuilder.Build() instead.", ex8.Message);
     }
 
-    [Fact]
-    public async Task EndpointDataSourceOnlyAddsOnce()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task EndpointDataSourceOnlyAddsOnce(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         await using var app = builder.Build();
 
         app.UseRouting();
@@ -1474,10 +1611,11 @@ public async Task EndpointDataSourceOnlyAddsOnce()
         Assert.Equal("Three", ds.Endpoints[2].DisplayName);
     }
 
-    [Fact]
-    public async Task RoutesAddedToCorrectMatcher()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task RoutesAddedToCorrectMatcher(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1509,10 +1647,11 @@ public async Task RoutesAddedToCorrectMatcher()
         Assert.Equal("One", chosenRoute);
     }
 
-    [Fact]
-    public async Task WebApplication_CallsUseRoutingAndUseEndpoints()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task WebApplication_CallsUseRoutingAndUseEndpoints(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1535,10 +1674,11 @@ public async Task WebApplication_CallsUseRoutingAndUseEndpoints()
         Assert.Equal("One", chosenRoute);
     }
 
-    [Fact]
-    public async Task BranchingPipelineHasOwnRoutes()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task BranchingPipelineHasOwnRoutes(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1599,10 +1739,11 @@ public async Task BranchingPipelineHasOwnRoutes()
         Assert.Equal("Four", chosenRoute);
     }
 
-    [Fact]
-    public async Task PropertiesPreservedFromInnerApplication()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task PropertiesPreservedFromInnerApplication(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.Services.AddSingleton<IStartupFilter, PropertyFilter>();
         await using var app = builder.Build();
 
@@ -1611,10 +1752,11 @@ public async Task PropertiesPreservedFromInnerApplication()
         app.Start();
     }
 
-    [Fact]
-    public async Task DeveloperExceptionPageIsOnByDefaltInDevelopment()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public async Task DeveloperExceptionPageIsOnByDefaltInDevelopment(CreateBuilderOptionsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Development });
+        var builder = createBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Development });
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1632,10 +1774,11 @@ public async Task DeveloperExceptionPageIsOnByDefaltInDevelopment()
         Assert.Contains("text/plain", response.Content.Headers.ContentType.MediaType);
     }
 
-    [Fact]
-    public async Task DeveloperExceptionPageDoesNotGetCaughtByStartupFilters()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public async Task DeveloperExceptionPageDoesNotGetCaughtByStartupFilters(CreateBuilderOptionsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Development });
+        var builder = createBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Development });
         builder.WebHost.UseTestServer();
         builder.Services.AddSingleton<IStartupFilter, ThrowingStartupFilter>();
         await using var app = builder.Build();
@@ -1649,10 +1792,11 @@ public async Task DeveloperExceptionPageDoesNotGetCaughtByStartupFilters()
         Assert.Equal("BOOM Filter", ex.Message);
     }
 
-    [Fact]
-    public async Task DeveloperExceptionPageIsNotOnInProduction()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public async Task DeveloperExceptionPageIsNotOnInProduction(CreateBuilderOptionsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Production });
+        var builder = createBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Production });
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1670,6 +1814,7 @@ public async Task DeveloperExceptionPageIsNotOnInProduction()
     [Fact]
     public async Task HostingStartupRunsWhenApplicationIsNotEntryPoint()
     {
+        // NOTE: CreateSlimBuilder doesn't support Startups
         var builder = WebApplication.CreateBuilder(new WebApplicationOptions { ApplicationName = typeof(WebApplicationTests).Assembly.FullName });
         await using var app = builder.Build();
 
@@ -1679,6 +1824,7 @@ public async Task HostingStartupRunsWhenApplicationIsNotEntryPoint()
     [Fact]
     public async Task HostingStartupRunsWhenApplicationIsNotEntryPointWithArgs()
     {
+        // NOTE: CreateSlimBuilder doesn't support Startups
         var builder = WebApplication.CreateBuilder(new[] { "--applicationName", typeof(WebApplicationTests).Assembly.FullName });
         await using var app = builder.Build();
 
@@ -1693,16 +1839,18 @@ public async Task HostingStartupRunsWhenApplicationIsNotEntryPointApplicationNam
             Args = new[] { "--applicationName", typeof(WebApplication).Assembly.FullName },
             ApplicationName = typeof(WebApplicationTests).Assembly.FullName,
         };
+        // NOTE: CreateSlimBuilder doesn't support Startups
         var builder = WebApplication.CreateBuilder(options);
         await using var app = builder.Build();
 
         Assert.Equal("value", app.Configuration["testhostingstartup:config"]);
     }
 
-    [Fact]
-    public async Task DeveloperExceptionPageWritesBadRequestDetailsToResponseByDefaltInDevelopment()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public async Task DeveloperExceptionPageWritesBadRequestDetailsToResponseByDefaltInDevelopment(CreateBuilderOptionsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Development });
+        var builder = createBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Development });
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1723,10 +1871,11 @@ public async Task DeveloperExceptionPageWritesBadRequestDetailsToResponseByDefal
         Assert.Contains("notAnInt", responseBody);
     }
 
-    [Fact]
-    public async Task NoExceptionAreThrownForBadRequestsInProduction()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public async Task NoExceptionAreThrownForBadRequestsInProduction(CreateBuilderOptionsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Production });
+        var builder = createBuilder(new WebApplicationOptions() { EnvironmentName = Environments.Production });
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1746,10 +1895,11 @@ public async Task NoExceptionAreThrownForBadRequestsInProduction()
         Assert.Equal(string.Empty, responseBody);
     }
 
-    [Fact]
-    public void PropertiesArePropagated()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void PropertiesArePropagated(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.Host.Properties["hello"] = "world";
         var callbacks = 0;
 
@@ -1777,8 +1927,9 @@ public void PropertiesArePropagated()
         Assert.Equal(0b00000111, callbacks);
     }
 
-    [Fact]
-    public void EmptyAppConfiguration()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void EmptyAppConfiguration(CreateBuilderFunc createBuilder)
     {
         var wwwroot = Path.Combine(AppContext.BaseDirectory, "wwwroot");
         bool createdDirectory = false;
@@ -1790,7 +1941,7 @@ public void EmptyAppConfiguration()
 
         try
         {
-            var builder = WebApplication.CreateBuilder();
+            var builder = createBuilder();
 
             builder.WebHost.ConfigureAppConfiguration((ctx, config) => { });
 
@@ -1807,10 +1958,11 @@ public void EmptyAppConfiguration()
         }
     }
 
-    [Fact]
-    public void HostConfigurationNotAffectedByConfiguration()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void HostConfigurationNotAffectedByConfiguration(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var contentRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
         var envName = $"{nameof(WebApplicationTests)}_ENV";
@@ -1836,10 +1988,11 @@ public void HostConfigurationNotAffectedByConfiguration()
         Assert.NotEqual(contentRoot, hostEnv.ContentRootPath);
     }
 
-    [Fact]
-    public void ClearingConfigurationDoesNotAffectHostConfiguration()
+    [Theory]
+    [MemberData(nameof(CreateBuilderOptionsFuncs))]
+    public void ClearingConfigurationDoesNotAffectHostConfiguration(CreateBuilderOptionsFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder(new WebApplicationOptions
+        var builder = createBuilder(new WebApplicationOptions
         {
             ApplicationName = typeof(WebApplicationOptions).Assembly.FullName,
             EnvironmentName = Environments.Staging,
@@ -1865,10 +2018,11 @@ public void ClearingConfigurationDoesNotAffectHostConfiguration()
         Assert.Equal(Path.GetTempPath(), hostEnv.ContentRootPath);
     }
 
-    [Fact]
-    public void ConfigurationGetDebugViewWorks()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void ConfigurationGetDebugViewWorks(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         builder.Configuration.AddInMemoryCollection(new Dictionary<string, string>
         {
@@ -1881,10 +2035,11 @@ public void ConfigurationGetDebugViewWorks()
         Assert.Contains("foo=bar (MemoryConfigurationProvider)", ((IConfigurationRoot)app.Configuration).GetDebugView());
     }
 
-    [Fact]
-    public void ConfigurationCanBeReloaded()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void ConfigurationCanBeReloaded(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         ((IConfigurationBuilder)builder.Configuration).Sources.Add(new RandomConfigurationSource());
 
@@ -1897,10 +2052,11 @@ public void ConfigurationCanBeReloaded()
         Assert.NotEqual(value0, value1);
     }
 
-    [Fact]
-    public void ConfigurationSourcesAreBuiltOnce()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void ConfigurationSourcesAreBuiltOnce(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var configSource = new RandomConfigurationSource();
         ((IConfigurationBuilder)builder.Configuration).Sources.Add(configSource);
@@ -1910,10 +2066,11 @@ public void ConfigurationSourcesAreBuiltOnce()
         Assert.Equal(1, configSource.ProvidersBuilt);
     }
 
-    [Fact]
-    public void ConfigurationProvidersAreLoadedOnceAfterBuild()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void ConfigurationProvidersAreLoadedOnceAfterBuild(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var configSource = new RandomConfigurationSource();
         ((IConfigurationBuilder)builder.Configuration).Sources.Add(configSource);
@@ -1923,10 +2080,11 @@ public void ConfigurationProvidersAreLoadedOnceAfterBuild()
         Assert.Equal(1, configSource.ProvidersLoaded);
     }
 
-    [Fact]
-    public void ConfigurationProvidersAreDisposedWithWebApplication()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void ConfigurationProvidersAreDisposedWithWebApplication(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         var configSource = new RandomConfigurationSource();
         ((IConfigurationBuilder)builder.Configuration).Sources.Add(configSource);
@@ -1940,10 +2098,11 @@ public void ConfigurationProvidersAreDisposedWithWebApplication()
         Assert.Equal(1, configSource.ProvidersDisposed);
     }
 
-    [Fact]
-    public void ConfigurationProviderTypesArePreserved()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void ConfigurationProviderTypesArePreserved(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         ((IConfigurationBuilder)builder.Configuration).Sources.Add(new RandomConfigurationSource());
 
@@ -1952,10 +2111,11 @@ public void ConfigurationProviderTypesArePreserved()
         Assert.Single(((IConfigurationRoot)app.Configuration).Providers.OfType<RandomConfigurationProvider>());
     }
 
-    [Fact]
-    public async Task CanUseMiddleware()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public async Task CanUseMiddleware(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
@@ -1972,10 +2132,11 @@ public async Task CanUseMiddleware()
         Assert.Equal("Hello World", response);
     }
 
-    [Fact]
-    public void CanObserveDefaultServicesInServiceCollection()
+    [Theory]
+    [MemberData(nameof(CreateBuilderFuncs))]
+    public void CanObserveDefaultServicesInServiceCollection(CreateBuilderFunc createBuilder)
     {
-        var builder = WebApplication.CreateBuilder();
+        var builder = createBuilder();
 
         Assert.Contains(builder.Services, service => service.ServiceType == typeof(HostBuilderContext));
         Assert.Contains(builder.Services, service => service.ServiceType == typeof(IHostApplicationLifetime));
@@ -1985,20 +2146,32 @@ public void CanObserveDefaultServicesInServiceCollection()
         Assert.Contains(builder.Services, service => service.ServiceType == typeof(ILogger<>));
     }
 
-    [Fact]
-    public async Task RegisterAuthMiddlewaresCorrectly()
+    [Theory]
+    [InlineData(true)]
+    [InlineData(false)]
+    public async Task RegisterAuthMiddlewaresCorrectly(bool useSlimBuilder)
     {
         var helloEndpointCalled = false;
         var customMiddlewareExecuted = false;
         var username = "foobar";
 
-        var builder = WebApplication.CreateBuilder();
+        var builder = useSlimBuilder ?
+            WebApplication.CreateSlimBuilder() :
+            WebApplication.CreateBuilder();
+
         builder.Services.AddAuthorization();
         builder.Services.AddAuthentication("testSchemeName")
             .AddScheme<AuthenticationSchemeOptions, UberHandler>("testSchemeName", "testDisplayName", _ => { });
         builder.WebHost.UseTestServer();
         await using var app = builder.Build();
 
+        if (useSlimBuilder)
+        {
+            // NOTE: CreateSlimBuilder doesn't support auto registration of auth middleware, so need to do it explicitly
+            app.UseAuthentication();
+            app.UseAuthorization();
+        }
+
         app.Use(next =>
         {
             return async context =>
@@ -2031,6 +2204,7 @@ public async Task RegisterAuthMiddlewaresCorrectly()
     [Fact]
     public async Task SupportsDisablingMiddlewareAutoRegistration()
     {
+        // NOTE: CreateSlimBuilder doesn't support auto registration of auth middleware
         var builder = WebApplication.CreateBuilder();
         builder.Services.AddAuthorization();
         builder.Services.AddAuthentication("testSchemeName")
diff --git a/src/Hosting/Hosting/src/GenericHost/SlimWebHostBuilder.cs b/src/Hosting/Hosting/src/GenericHost/SlimWebHostBuilder.cs
new file mode 100644
index 000000000000..e109b45898a9
--- /dev/null
+++ b/src/Hosting/Hosting/src/GenericHost/SlimWebHostBuilder.cs
@@ -0,0 +1,186 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting.Builder;
+using Microsoft.AspNetCore.Hosting.Infrastructure;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Hosting;
+
+namespace Microsoft.AspNetCore.Hosting;
+
+internal sealed class SlimWebHostBuilder : IWebHostBuilder, ISupportsStartup, ISupportsUseDefaultServiceProvider
+{
+    private readonly IHostBuilder _builder;
+    private readonly IConfiguration _config;
+
+    public SlimWebHostBuilder(IHostBuilder builder, WebHostBuilderOptions options)
+    {
+        _builder = builder;
+        var configBuilder = new ConfigurationBuilder()
+            .AddInMemoryCollection();
+
+        if (!options.SuppressEnvironmentConfiguration)
+        {
+            configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_");
+        }
+
+        _config = configBuilder.Build();
+
+        _builder.ConfigureHostConfiguration(config =>
+        {
+            config.AddConfiguration(_config);
+        });
+
+        _builder.ConfigureServices((context, services) =>
+        {
+            var webhostContext = GetWebHostBuilderContext(context);
+            var webHostOptions = (WebHostOptions)context.Properties[typeof(WebHostOptions)];
+
+            // Add the IHostingEnvironment and IApplicationLifetime from Microsoft.AspNetCore.Hosting
+            services.AddSingleton(webhostContext.HostingEnvironment);
+#pragma warning disable CS0618 // Type or member is obsolete
+            services.AddSingleton((AspNetCore.Hosting.IHostingEnvironment)webhostContext.HostingEnvironment);
+            services.AddSingleton<IApplicationLifetime, GenericWebHostApplicationLifetime>();
+#pragma warning restore CS0618 // Type or member is obsolete
+
+            services.Configure<GenericWebHostServiceOptions>(options =>
+            {
+                // Set the options
+                options.WebHostOptions = webHostOptions;
+            });
+
+            // REVIEW: This is bad since we don't own this type. Anybody could add one of these and it would mess things up
+            // We need to flow this differently
+            services.TryAddSingleton(sp => new DiagnosticListener("Microsoft.AspNetCore"));
+            services.TryAddSingleton<DiagnosticSource>(sp => sp.GetRequiredService<DiagnosticListener>());
+            services.TryAddSingleton(sp => new ActivitySource("Microsoft.AspNetCore"));
+            services.TryAddSingleton(DistributedContextPropagator.Current);
+
+            services.TryAddSingleton<IHttpContextFactory, DefaultHttpContextFactory>();
+            services.TryAddScoped<IMiddlewareFactory, MiddlewareFactory>();
+            services.TryAddSingleton<IApplicationBuilderFactory, ApplicationBuilderFactory>();
+        });
+    }
+
+    public IWebHost Build()
+    {
+        throw new NotSupportedException($"Building this implementation of {nameof(IWebHostBuilder)} is not supported.");
+    }
+
+    public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate)
+    {
+        _builder.ConfigureAppConfiguration((context, builder) =>
+        {
+            var webhostBuilderContext = GetWebHostBuilderContext(context);
+            configureDelegate(webhostBuilderContext, builder);
+        });
+
+        return this;
+    }
+
+    public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
+    {
+        return ConfigureServices((context, services) => configureServices(services));
+    }
+
+    public IWebHostBuilder ConfigureServices(Action<WebHostBuilderContext, IServiceCollection> configureServices)
+    {
+        _builder.ConfigureServices((context, builder) =>
+        {
+            var webhostBuilderContext = GetWebHostBuilderContext(context);
+            configureServices(webhostBuilderContext, builder);
+        });
+
+        return this;
+    }
+
+    public IWebHostBuilder UseDefaultServiceProvider(Action<WebHostBuilderContext, ServiceProviderOptions> configure)
+    {
+        _builder.UseServiceProviderFactory(context =>
+        {
+            var webHostBuilderContext = GetWebHostBuilderContext(context);
+            var options = new ServiceProviderOptions();
+            configure(webHostBuilderContext, options);
+            // TODO: Remove when DI no longer has RequiresDynamicCodeAttribute https://github.com/dotnet/runtime/pull/79425
+#pragma warning disable IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
+            return new DefaultServiceProviderFactory(options);
+#pragma warning restore IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
+        });
+
+        return this;
+    }
+
+    public IWebHostBuilder Configure(Action<IApplicationBuilder> configure)
+    {
+        throw new NotSupportedException();
+    }
+
+    public IWebHostBuilder UseStartup([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods)] Type startupType)
+    {
+        throw new NotSupportedException();
+    }
+
+    public IWebHostBuilder UseStartup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TStartup>(Func<WebHostBuilderContext, TStartup> startupFactory)
+    {
+        throw new NotSupportedException();
+    }
+
+    public IWebHostBuilder Configure(Action<WebHostBuilderContext, IApplicationBuilder> configure)
+    {
+        var startupAssemblyName = configure.GetMethodInfo().DeclaringType!.Assembly.GetName().Name!;
+
+        UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName);
+
+        _builder.ConfigureServices((context, services) =>
+        {
+            services.Configure<GenericWebHostServiceOptions>(options =>
+            {
+                var webhostBuilderContext = GetWebHostBuilderContext(context);
+                options.ConfigureApplication = app => configure(webhostBuilderContext, app);
+            });
+        });
+
+        return this;
+    }
+
+    private WebHostBuilderContext GetWebHostBuilderContext(HostBuilderContext context)
+    {
+        if (!context.Properties.TryGetValue(typeof(WebHostBuilderContext), out var contextVal))
+        {
+            // Use _config as a fallback for WebHostOptions in case the chained source was removed from the hosting IConfigurationBuilder.
+            var options = new WebHostOptions(context.Configuration, fallbackConfiguration: _config, environment: context.HostingEnvironment);
+            var webHostBuilderContext = new WebHostBuilderContext
+            {
+                Configuration = context.Configuration,
+                HostingEnvironment = new HostingEnvironment(),
+            };
+            webHostBuilderContext.HostingEnvironment.Initialize(context.HostingEnvironment.ContentRootPath, options, baseEnvironment: context.HostingEnvironment);
+            context.Properties[typeof(WebHostBuilderContext)] = webHostBuilderContext;
+            context.Properties[typeof(WebHostOptions)] = options;
+            return webHostBuilderContext;
+        }
+
+        // Refresh config, it's periodically updated/replaced
+        var webHostContext = (WebHostBuilderContext)contextVal;
+        webHostContext.Configuration = context.Configuration;
+        return webHostContext;
+    }
+
+    public string? GetSetting(string key)
+    {
+        return _config[key];
+    }
+
+    public IWebHostBuilder UseSetting(string key, string? value)
+    {
+        _config[key] = value;
+        return this;
+    }
+}
diff --git a/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs b/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs
index 7bd6f86a49af..f874d54f3995 100644
--- a/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs
+++ b/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs
@@ -33,6 +33,35 @@ public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action<IW
     /// <param name="configureWebHostBuilder">The delegate that configures the <see cref="WebHostBuilderOptions"/>.</param>
     /// <returns>The <see cref="IHostBuilder"/>.</returns>
     public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action<IWebHostBuilder> configure, Action<WebHostBuilderOptions> configureWebHostBuilder)
+    {
+        return ConfigureWebHost(
+            builder,
+            (hostBuilder, options) => new GenericWebHostBuilder(hostBuilder, options),
+            configure,
+            configureWebHostBuilder);
+    }
+
+    /// <summary>
+    /// Adds and configures an ASP.NET Core web application with minimal dependencies.
+    /// </summary>
+    /// <param name="builder">The <see cref="IHostBuilder"/> to add the <see cref="IWebHostBuilder"/> to.</param>
+    /// <param name="configure">The delegate that configures the <see cref="IWebHostBuilder"/>.</param>
+    /// <param name="configureWebHostBuilder">The delegate that configures the <see cref="WebHostBuilderOptions"/>.</param>
+    /// <returns>The <see cref="IHostBuilder"/>.</returns>
+    public static IHostBuilder ConfigureSlimWebHost(this IHostBuilder builder, Action<IWebHostBuilder> configure, Action<WebHostBuilderOptions> configureWebHostBuilder)
+    {
+        return ConfigureWebHost(
+            builder,
+            (hostBuilder, options) => new SlimWebHostBuilder(hostBuilder, options),
+            configure,
+            configureWebHostBuilder);
+    }
+
+    private static IHostBuilder ConfigureWebHost(
+        this IHostBuilder builder,
+        Func<IHostBuilder, WebHostBuilderOptions, IWebHostBuilder> createWebHostBuilder,
+        Action<IWebHostBuilder> configure,
+        Action<WebHostBuilderOptions> configureWebHostBuilder)
     {
         ArgumentNullException.ThrowIfNull(configure);
         ArgumentNullException.ThrowIfNull(configureWebHostBuilder);
@@ -45,7 +74,7 @@ public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action<IW
 
         var webHostBuilderOptions = new WebHostBuilderOptions();
         configureWebHostBuilder(webHostBuilderOptions);
-        var webhostBuilder = new GenericWebHostBuilder(builder, webHostBuilderOptions);
+        var webhostBuilder = createWebHostBuilder(builder, webHostBuilderOptions);
         configure(webhostBuilder);
         builder.ConfigureServices((context, services) => services.AddHostedService<GenericWebHostService>());
         return builder;
diff --git a/src/Hosting/Hosting/src/PublicAPI.Unshipped.txt b/src/Hosting/Hosting/src/PublicAPI.Unshipped.txt
index 7dc5c58110bf..de9a58f9e603 100644
--- a/src/Hosting/Hosting/src/PublicAPI.Unshipped.txt
+++ b/src/Hosting/Hosting/src/PublicAPI.Unshipped.txt
@@ -1 +1,2 @@
 #nullable enable
+static Microsoft.Extensions.Hosting.GenericHostWebHostBuilderExtensions.ConfigureSlimWebHost(this Microsoft.Extensions.Hosting.IHostBuilder! builder, System.Action<Microsoft.AspNetCore.Hosting.IWebHostBuilder!>! configure, System.Action<Microsoft.Extensions.Hosting.WebHostBuilderOptions!>! configureWebHostBuilder) -> Microsoft.Extensions.Hosting.IHostBuilder!

From 743349d6395358897cea9fc4bf4835bb3bc16c21 Mon Sep 17 00:00:00 2001
From: Eric Erhardt <eric.erhardt@microsoft.com>
Date: Wed, 18 Jan 2023 17:06:32 -0600
Subject: [PATCH 2/7] Use the new slim hosting API in the api template.

---
 .../Web.ProjectTemplates/content/Api-CSharp/Program.Main.cs     | 2 +-
 .../Web.ProjectTemplates/content/Api-CSharp/Program.cs          | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/Api-CSharp/Program.Main.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/Api-CSharp/Program.Main.cs
index 1e7082c4f9cb..dc6deae4de45 100644
--- a/src/ProjectTemplates/Web.ProjectTemplates/content/Api-CSharp/Program.Main.cs
+++ b/src/ProjectTemplates/Web.ProjectTemplates/content/Api-CSharp/Program.Main.cs
@@ -9,7 +9,7 @@ public class Program
 {
     public static void Main(string[] args)
     {
-        var builder = WebApplication.CreateBuilder(args);
+        var builder = WebApplication.CreateSlimBuilder(args);
         builder.Logging.AddConsole();
 
         #if (NativeAot)
diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/Api-CSharp/Program.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/Api-CSharp/Program.cs
index be0ffccde6fa..5f12bdd3c5ba 100644
--- a/src/ProjectTemplates/Web.ProjectTemplates/content/Api-CSharp/Program.cs
+++ b/src/ProjectTemplates/Web.ProjectTemplates/content/Api-CSharp/Program.cs
@@ -3,7 +3,7 @@
 #endif
 using Company.ApiApplication1;
 
-var builder = WebApplication.CreateBuilder(args);
+var builder = WebApplication.CreateSlimBuilder(args);
 builder.Logging.AddConsole();
 
 #if (NativeAot)

From ef62c6d2eca2487095fe88f76cd3f9949f42c077 Mon Sep 17 00:00:00 2001
From: Eric Erhardt <eric.erhardt@microsoft.com>
Date: Wed, 18 Jan 2023 18:26:18 -0600
Subject: [PATCH 3/7] Makes changes for the latest code.

Refactor the WebHostBuilder classes to share more code.
---
 .../src/WebApplicationBuilder.cs              |   3 -
 .../src/GenericHost/GenericWebHostBuilder.cs  |  95 +---------------
 .../src/GenericHost/SlimWebHostBuilder.cs     |  99 +---------------
 .../src/GenericHost/WebHostBuilderBase.cs     | 107 ++++++++++++++++++
 .../GenericHostWebHostBuilderExtensions.cs    |   4 +-
 5 files changed, 113 insertions(+), 195 deletions(-)
 create mode 100644 src/Hosting/Hosting/src/GenericHost/WebHostBuilderBase.cs

diff --git a/src/DefaultBuilder/src/WebApplicationBuilder.cs b/src/DefaultBuilder/src/WebApplicationBuilder.cs
index 5792ed94169a..c911651c45ee 100644
--- a/src/DefaultBuilder/src/WebApplicationBuilder.cs
+++ b/src/DefaultBuilder/src/WebApplicationBuilder.cs
@@ -92,8 +92,6 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
 
         var configuration = new ConfigurationManager();
 
-        // TODO: Remove when DI no longer has RequiresDynamicCodeAttribute https://github.com/dotnet/runtime/pull/79425
-#pragma warning disable IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
         _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings
         {
             Args = options.Args,
@@ -102,7 +100,6 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
             ContentRootPath = options.ContentRootPath,
             Configuration = configuration,
         });
-#pragma warning restore IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
 
         // Set WebRootPath if necessary
         if (options.WebRootPath is not null)
diff --git a/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs b/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs
index 0116dd0c8410..d89ddfe9331c 100644
--- a/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs
+++ b/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs
@@ -18,10 +18,8 @@
 
 namespace Microsoft.AspNetCore.Hosting;
 
-internal sealed class GenericWebHostBuilder : IWebHostBuilder, ISupportsStartup, ISupportsUseDefaultServiceProvider
+internal sealed class GenericWebHostBuilder : WebHostBuilderBase, ISupportsStartup
 {
-    private readonly IHostBuilder _builder;
-    private readonly IConfiguration _config;
     private object? _startupObject;
     private readonly object _startupKey = new object();
 
@@ -29,18 +27,8 @@ internal sealed class GenericWebHostBuilder : IWebHostBuilder, ISupportsStartup,
     private HostingStartupWebHostBuilder? _hostingStartupWebHostBuilder;
 
     public GenericWebHostBuilder(IHostBuilder builder, WebHostBuilderOptions options)
+        : base(builder, options)
     {
-        _builder = builder;
-        var configBuilder = new ConfigurationBuilder()
-            .AddInMemoryCollection();
-
-        if (!options.SuppressEnvironmentConfiguration)
-        {
-            configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_");
-        }
-
-        _config = configBuilder.Build();
-
         _builder.ConfigureHostConfiguration(config =>
         {
             config.AddConfiguration(_config);
@@ -172,51 +160,6 @@ private void ExecuteHostingStartups()
         }
     }
 
-    public IWebHost Build()
-    {
-        throw new NotSupportedException($"Building this implementation of {nameof(IWebHostBuilder)} is not supported.");
-    }
-
-    public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate)
-    {
-        _builder.ConfigureAppConfiguration((context, builder) =>
-        {
-            var webhostBuilderContext = GetWebHostBuilderContext(context);
-            configureDelegate(webhostBuilderContext, builder);
-        });
-
-        return this;
-    }
-
-    public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
-    {
-        return ConfigureServices((context, services) => configureServices(services));
-    }
-
-    public IWebHostBuilder ConfigureServices(Action<WebHostBuilderContext, IServiceCollection> configureServices)
-    {
-        _builder.ConfigureServices((context, builder) =>
-        {
-            var webhostBuilderContext = GetWebHostBuilderContext(context);
-            configureServices(webhostBuilderContext, builder);
-        });
-
-        return this;
-    }
-
-    public IWebHostBuilder UseDefaultServiceProvider(Action<WebHostBuilderContext, ServiceProviderOptions> configure)
-    {
-        _builder.UseServiceProviderFactory(context =>
-        {
-            var webHostBuilderContext = GetWebHostBuilderContext(context);
-            var options = new ServiceProviderOptions();
-            configure(webHostBuilderContext, options);
-            return new DefaultServiceProviderFactory(options);
-        });
-
-        return this;
-    }
-
     public IWebHostBuilder UseStartup([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupType)
     {
         var startupAssemblyName = startupType.Assembly.GetName().Name;
@@ -412,40 +355,6 @@ public IWebHostBuilder Configure(Action<WebHostBuilderContext, IApplicationBuild
         return this;
     }
 
-    private WebHostBuilderContext GetWebHostBuilderContext(HostBuilderContext context)
-    {
-        if (!context.Properties.TryGetValue(typeof(WebHostBuilderContext), out var contextVal))
-        {
-            // Use _config as a fallback for WebHostOptions in case the chained source was removed from the hosting IConfigurationBuilder.
-            var options = new WebHostOptions(context.Configuration, fallbackConfiguration: _config, environment: context.HostingEnvironment);
-            var webHostBuilderContext = new WebHostBuilderContext
-            {
-                Configuration = context.Configuration,
-                HostingEnvironment = new HostingEnvironment(),
-            };
-            webHostBuilderContext.HostingEnvironment.Initialize(context.HostingEnvironment.ContentRootPath, options, baseEnvironment: context.HostingEnvironment);
-            context.Properties[typeof(WebHostBuilderContext)] = webHostBuilderContext;
-            context.Properties[typeof(WebHostOptions)] = options;
-            return webHostBuilderContext;
-        }
-
-        // Refresh config, it's periodically updated/replaced
-        var webHostContext = (WebHostBuilderContext)contextVal;
-        webHostContext.Configuration = context.Configuration;
-        return webHostContext;
-    }
-
-    public string? GetSetting(string key)
-    {
-        return _config[key];
-    }
-
-    public IWebHostBuilder UseSetting(string key, string? value)
-    {
-        _config[key] = value;
-        return this;
-    }
-
     // This exists just so that we can use ActivatorUtilities.CreateInstance on the Startup class
     private sealed class HostServiceProvider : IServiceProvider
     {
diff --git a/src/Hosting/Hosting/src/GenericHost/SlimWebHostBuilder.cs b/src/Hosting/Hosting/src/GenericHost/SlimWebHostBuilder.cs
index e109b45898a9..3ddeeba68fed 100644
--- a/src/Hosting/Hosting/src/GenericHost/SlimWebHostBuilder.cs
+++ b/src/Hosting/Hosting/src/GenericHost/SlimWebHostBuilder.cs
@@ -15,24 +15,11 @@
 
 namespace Microsoft.AspNetCore.Hosting;
 
-internal sealed class SlimWebHostBuilder : IWebHostBuilder, ISupportsStartup, ISupportsUseDefaultServiceProvider
+internal sealed class SlimWebHostBuilder : WebHostBuilderBase, ISupportsStartup
 {
-    private readonly IHostBuilder _builder;
-    private readonly IConfiguration _config;
-
     public SlimWebHostBuilder(IHostBuilder builder, WebHostBuilderOptions options)
+        : base(builder, options)
     {
-        _builder = builder;
-        var configBuilder = new ConfigurationBuilder()
-            .AddInMemoryCollection();
-
-        if (!options.SuppressEnvironmentConfiguration)
-        {
-            configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_");
-        }
-
-        _config = configBuilder.Build();
-
         _builder.ConfigureHostConfiguration(config =>
         {
             config.AddConfiguration(_config);
@@ -69,54 +56,6 @@ public SlimWebHostBuilder(IHostBuilder builder, WebHostBuilderOptions options)
         });
     }
 
-    public IWebHost Build()
-    {
-        throw new NotSupportedException($"Building this implementation of {nameof(IWebHostBuilder)} is not supported.");
-    }
-
-    public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate)
-    {
-        _builder.ConfigureAppConfiguration((context, builder) =>
-        {
-            var webhostBuilderContext = GetWebHostBuilderContext(context);
-            configureDelegate(webhostBuilderContext, builder);
-        });
-
-        return this;
-    }
-
-    public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
-    {
-        return ConfigureServices((context, services) => configureServices(services));
-    }
-
-    public IWebHostBuilder ConfigureServices(Action<WebHostBuilderContext, IServiceCollection> configureServices)
-    {
-        _builder.ConfigureServices((context, builder) =>
-        {
-            var webhostBuilderContext = GetWebHostBuilderContext(context);
-            configureServices(webhostBuilderContext, builder);
-        });
-
-        return this;
-    }
-
-    public IWebHostBuilder UseDefaultServiceProvider(Action<WebHostBuilderContext, ServiceProviderOptions> configure)
-    {
-        _builder.UseServiceProviderFactory(context =>
-        {
-            var webHostBuilderContext = GetWebHostBuilderContext(context);
-            var options = new ServiceProviderOptions();
-            configure(webHostBuilderContext, options);
-            // TODO: Remove when DI no longer has RequiresDynamicCodeAttribute https://github.com/dotnet/runtime/pull/79425
-#pragma warning disable IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
-            return new DefaultServiceProviderFactory(options);
-#pragma warning restore IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
-        });
-
-        return this;
-    }
-
     public IWebHostBuilder Configure(Action<IApplicationBuilder> configure)
     {
         throw new NotSupportedException();
@@ -149,38 +88,4 @@ public IWebHostBuilder Configure(Action<WebHostBuilderContext, IApplicationBuild
 
         return this;
     }
-
-    private WebHostBuilderContext GetWebHostBuilderContext(HostBuilderContext context)
-    {
-        if (!context.Properties.TryGetValue(typeof(WebHostBuilderContext), out var contextVal))
-        {
-            // Use _config as a fallback for WebHostOptions in case the chained source was removed from the hosting IConfigurationBuilder.
-            var options = new WebHostOptions(context.Configuration, fallbackConfiguration: _config, environment: context.HostingEnvironment);
-            var webHostBuilderContext = new WebHostBuilderContext
-            {
-                Configuration = context.Configuration,
-                HostingEnvironment = new HostingEnvironment(),
-            };
-            webHostBuilderContext.HostingEnvironment.Initialize(context.HostingEnvironment.ContentRootPath, options, baseEnvironment: context.HostingEnvironment);
-            context.Properties[typeof(WebHostBuilderContext)] = webHostBuilderContext;
-            context.Properties[typeof(WebHostOptions)] = options;
-            return webHostBuilderContext;
-        }
-
-        // Refresh config, it's periodically updated/replaced
-        var webHostContext = (WebHostBuilderContext)contextVal;
-        webHostContext.Configuration = context.Configuration;
-        return webHostContext;
-    }
-
-    public string? GetSetting(string key)
-    {
-        return _config[key];
-    }
-
-    public IWebHostBuilder UseSetting(string key, string? value)
-    {
-        _config[key] = value;
-        return this;
-    }
 }
diff --git a/src/Hosting/Hosting/src/GenericHost/WebHostBuilderBase.cs b/src/Hosting/Hosting/src/GenericHost/WebHostBuilderBase.cs
new file mode 100644
index 000000000000..c104ed40002a
--- /dev/null
+++ b/src/Hosting/Hosting/src/GenericHost/WebHostBuilderBase.cs
@@ -0,0 +1,107 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+namespace Microsoft.AspNetCore.Hosting;
+
+internal abstract class WebHostBuilderBase : IWebHostBuilder, ISupportsUseDefaultServiceProvider
+{
+    private protected readonly IHostBuilder _builder;
+    private protected readonly IConfiguration _config;
+
+    public WebHostBuilderBase(IHostBuilder builder, WebHostBuilderOptions options)
+    {
+        _builder = builder;
+        var configBuilder = new ConfigurationBuilder()
+            .AddInMemoryCollection();
+
+        if (!options.SuppressEnvironmentConfiguration)
+        {
+            configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_");
+        }
+
+        _config = configBuilder.Build();
+    }
+
+    public IWebHost Build()
+    {
+        throw new NotSupportedException($"Building this implementation of {nameof(IWebHostBuilder)} is not supported.");
+    }
+
+    public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate)
+    {
+        _builder.ConfigureAppConfiguration((context, builder) =>
+        {
+            var webhostBuilderContext = GetWebHostBuilderContext(context);
+            configureDelegate(webhostBuilderContext, builder);
+        });
+
+        return this;
+    }
+
+    public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
+    {
+        return ConfigureServices((context, services) => configureServices(services));
+    }
+
+    public IWebHostBuilder ConfigureServices(Action<WebHostBuilderContext, IServiceCollection> configureServices)
+    {
+        _builder.ConfigureServices((context, builder) =>
+        {
+            var webhostBuilderContext = GetWebHostBuilderContext(context);
+            configureServices(webhostBuilderContext, builder);
+        });
+
+        return this;
+    }
+
+    public IWebHostBuilder UseDefaultServiceProvider(Action<WebHostBuilderContext, ServiceProviderOptions> configure)
+    {
+        _builder.UseServiceProviderFactory(context =>
+        {
+            var webHostBuilderContext = GetWebHostBuilderContext(context);
+            var options = new ServiceProviderOptions();
+            configure(webHostBuilderContext, options);
+            return new DefaultServiceProviderFactory(options);
+        });
+
+        return this;
+    }
+
+    protected WebHostBuilderContext GetWebHostBuilderContext(HostBuilderContext context)
+    {
+        if (!context.Properties.TryGetValue(typeof(WebHostBuilderContext), out var contextVal))
+        {
+            // Use _config as a fallback for WebHostOptions in case the chained source was removed from the hosting IConfigurationBuilder.
+            var options = new WebHostOptions(context.Configuration, fallbackConfiguration: _config, environment: context.HostingEnvironment);
+            var webHostBuilderContext = new WebHostBuilderContext
+            {
+                Configuration = context.Configuration,
+                HostingEnvironment = new HostingEnvironment(),
+            };
+            webHostBuilderContext.HostingEnvironment.Initialize(context.HostingEnvironment.ContentRootPath, options, baseEnvironment: context.HostingEnvironment);
+            context.Properties[typeof(WebHostBuilderContext)] = webHostBuilderContext;
+            context.Properties[typeof(WebHostOptions)] = options;
+            return webHostBuilderContext;
+        }
+
+        // Refresh config, it's periodically updated/replaced
+        var webHostContext = (WebHostBuilderContext)contextVal;
+        webHostContext.Configuration = context.Configuration;
+        return webHostContext;
+    }
+
+    public string? GetSetting(string key)
+    {
+        return _config[key];
+    }
+
+    public IWebHostBuilder UseSetting(string key, string? value)
+    {
+        _config[key] = value;
+        return this;
+    }
+}
diff --git a/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs b/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs
index f874d54f3995..ea37f73aa036 100644
--- a/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs
+++ b/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs
@@ -36,7 +36,7 @@ public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action<IW
     {
         return ConfigureWebHost(
             builder,
-            (hostBuilder, options) => new GenericWebHostBuilder(hostBuilder, options),
+            static (hostBuilder, options) => new GenericWebHostBuilder(hostBuilder, options),
             configure,
             configureWebHostBuilder);
     }
@@ -52,7 +52,7 @@ public static IHostBuilder ConfigureSlimWebHost(this IHostBuilder builder, Actio
     {
         return ConfigureWebHost(
             builder,
-            (hostBuilder, options) => new SlimWebHostBuilder(hostBuilder, options),
+            static (hostBuilder, options) => new SlimWebHostBuilder(hostBuilder, options),
             configure,
             configureWebHostBuilder);
     }

From 2073eeb4e7ebb2849e79267023fb7bd8d26113df Mon Sep 17 00:00:00 2001
From: Eric Erhardt <eric.erhardt@microsoft.com>
Date: Wed, 18 Jan 2023 18:29:15 -0600
Subject: [PATCH 4/7] PR feedback.

---
 src/DefaultBuilder/src/WebApplicationBuilder.cs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/DefaultBuilder/src/WebApplicationBuilder.cs b/src/DefaultBuilder/src/WebApplicationBuilder.cs
index c911651c45ee..eab1eb2b7bb1 100644
--- a/src/DefaultBuilder/src/WebApplicationBuilder.cs
+++ b/src/DefaultBuilder/src/WebApplicationBuilder.cs
@@ -94,6 +94,7 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
 
         _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings
         {
+            DisableDefaults = true,
             Args = options.Args,
             ApplicationName = options.ApplicationName,
             EnvironmentName = options.EnvironmentName,

From 2216e6edb77eb30b06e4790de55425e72134838c Mon Sep 17 00:00:00 2001
From: Eric Erhardt <eric.erhardt@microsoft.com>
Date: Thu, 19 Jan 2023 18:12:48 -0600
Subject: [PATCH 5/7] Revert DisableDefaults changes.

It is breaking too much functionality that will need to be reimplemented from the Extensions.HostBuilder.
---
 src/DefaultBuilder/src/WebApplicationBuilder.cs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/DefaultBuilder/src/WebApplicationBuilder.cs b/src/DefaultBuilder/src/WebApplicationBuilder.cs
index eab1eb2b7bb1..c911651c45ee 100644
--- a/src/DefaultBuilder/src/WebApplicationBuilder.cs
+++ b/src/DefaultBuilder/src/WebApplicationBuilder.cs
@@ -94,7 +94,6 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
 
         _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings
         {
-            DisableDefaults = true,
             Args = options.Args,
             ApplicationName = options.ApplicationName,
             EnvironmentName = options.EnvironmentName,

From 0a58daacc0ae6032b63e9b6468674b7ecd57d6d9 Mon Sep 17 00:00:00 2001
From: Eric Erhardt <eric.erhardt@microsoft.com>
Date: Thu, 19 Jan 2023 22:01:08 -0600
Subject: [PATCH 6/7] Add back DisableDefaults = true with passing tests.

---
 .../src/WebApplicationBuilder.cs              | 28 +++++++++++++++
 .../WebApplicationTests.cs                    | 36 ++++++++++++++++---
 2 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/src/DefaultBuilder/src/WebApplicationBuilder.cs b/src/DefaultBuilder/src/WebApplicationBuilder.cs
index c911651c45ee..344c4480ca67 100644
--- a/src/DefaultBuilder/src/WebApplicationBuilder.cs
+++ b/src/DefaultBuilder/src/WebApplicationBuilder.cs
@@ -92,8 +92,17 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
 
         var configuration = new ConfigurationManager();
 
+        // add the default host configuration sources, so they are picked up by the HostApplicationBuilder constructor.
+        // These won't be added by HostApplicationBuilder since DisableDefaults = true.
+        configuration.AddEnvironmentVariables(prefix: "DOTNET_");
+        if (options.Args is { Length: > 0 } args)
+        {
+            configuration.AddCommandLine(args);
+        }
+
         _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings
         {
+            DisableDefaults = true,
             Args = options.Args,
             ApplicationName = options.ApplicationName,
             EnvironmentName = options.EnvironmentName,
@@ -101,6 +110,10 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
             Configuration = configuration,
         });
 
+        // configure the ServiceProvider explicitly because DisableDefaults means HostApplicationBuilder won't.
+        var serviceProviderFactory = GetServiceProviderFactory(_hostApplicationBuilder);
+        _hostApplicationBuilder.ConfigureContainer(serviceProviderFactory);
+
         // Set WebRootPath if necessary
         if (options.WebRootPath is not null)
         {
@@ -147,6 +160,21 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
         WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services);
     }
 
+    private static DefaultServiceProviderFactory GetServiceProviderFactory(HostApplicationBuilder hostApplicationBuilder)
+    {
+        if (hostApplicationBuilder.Environment.IsDevelopment())
+        {
+            return new DefaultServiceProviderFactory(
+                new ServiceProviderOptions
+                {
+                    ValidateScopes = true,
+                    ValidateOnBuild = true,
+                });
+        }
+
+        return new DefaultServiceProviderFactory();
+    }
+
     /// <summary>
     /// Provides information about the web hosting environment an application is running.
     /// </summary>
diff --git a/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs b/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs
index 9d94502ca80f..104e13788f2c 100644
--- a/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs
+++ b/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/WebApplicationTests.cs
@@ -1505,14 +1505,33 @@ public async Task CanAddMiddlewareBeforeUseRouting(CreateBuilderFunc createBuild
         Assert.Equal("One", chosenEndpoint);
     }
 
+    public static IEnumerable<object[]> OnlyAddsDefaultServicesOnceData
+    {
+        get
+        {
+            // The slim builder doesn't add logging services by default
+            yield return new object[] { (CreateBuilderFunc)CreateBuilder, true };
+            yield return new object[] { (CreateBuilderFunc)CreateSlimBuilder, false };
+        }
+    }
+
     [Theory]
-    [MemberData(nameof(CreateBuilderFuncs))]
-    public async Task WebApplicationBuilder_OnlyAddsDefaultServicesOnce(CreateBuilderFunc createBuilder)
+    [MemberData(nameof(OnlyAddsDefaultServicesOnceData))]
+    public async Task WebApplicationBuilder_OnlyAddsDefaultServicesOnce(CreateBuilderFunc createBuilder, bool hasLogging)
     {
         var builder = createBuilder();
 
         // IWebHostEnvironment is added by ConfigureDefaults
-        Assert.Single(builder.Services.Where(descriptor => descriptor.ServiceType == typeof(IConfigureOptions<LoggerFactoryOptions>)));
+        var loggingDescriptors = builder.Services.Where(descriptor => descriptor.ServiceType == typeof(IConfigureOptions<LoggerFactoryOptions>));
+        if (hasLogging)
+        {
+            Assert.Single(loggingDescriptors);
+        }
+        else
+        {
+            Assert.Empty(loggingDescriptors);
+        }
+
         // IWebHostEnvironment is added by ConfigureWebHostDefaults
         Assert.Single(builder.Services.Where(descriptor => descriptor.ServiceType == typeof(IWebHostEnvironment)));
         Assert.Single(builder.Services.Where(descriptor => descriptor.ServiceType == typeof(IOptionsChangeTokenSource<HostFilteringOptions>)));
@@ -1520,7 +1539,16 @@ public async Task WebApplicationBuilder_OnlyAddsDefaultServicesOnce(CreateBuilde
 
         await using var app = builder.Build();
 
-        Assert.Single(app.Services.GetRequiredService<IEnumerable<IConfigureOptions<LoggerFactoryOptions>>>());
+        var loggingServices = app.Services.GetRequiredService<IEnumerable<IConfigureOptions<LoggerFactoryOptions>>>();
+        if (hasLogging)
+        {
+            Assert.Single(loggingServices);
+        }
+        else
+        {
+            Assert.Empty(loggingServices);
+        }
+
         Assert.Single(app.Services.GetRequiredService<IEnumerable<IWebHostEnvironment>>());
         Assert.Single(app.Services.GetRequiredService<IEnumerable<IOptionsChangeTokenSource<HostFilteringOptions>>>());
         Assert.Single(app.Services.GetRequiredService<IEnumerable<IServer>>());

From 1df71850ea1e5934a8d550914fec5b0bcd06af0b Mon Sep 17 00:00:00 2001
From: Eric Erhardt <eric.erhardt@microsoft.com>
Date: Fri, 20 Jan 2023 17:41:24 -0600
Subject: [PATCH 7/7] PR feedback

Explicitly add ASPNETCORE environment variables.
---
 src/DefaultBuilder/src/WebApplicationBuilder.cs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/DefaultBuilder/src/WebApplicationBuilder.cs b/src/DefaultBuilder/src/WebApplicationBuilder.cs
index 344c4480ca67..0f7bca59694c 100644
--- a/src/DefaultBuilder/src/WebApplicationBuilder.cs
+++ b/src/DefaultBuilder/src/WebApplicationBuilder.cs
@@ -92,6 +92,8 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
 
         var configuration = new ConfigurationManager();
 
+        configuration.AddEnvironmentVariables(prefix: "ASPNETCORE_");
+
         // add the default host configuration sources, so they are picked up by the HostApplicationBuilder constructor.
         // These won't be added by HostApplicationBuilder since DisableDefaults = true.
         configuration.AddEnvironmentVariables(prefix: "DOTNET_");
@@ -110,7 +112,7 @@ internal WebApplicationBuilder(WebApplicationOptions options, bool slim, Action<
             Configuration = configuration,
         });
 
-        // configure the ServiceProvider explicitly because DisableDefaults means HostApplicationBuilder won't.
+        // configure the ServiceProviderOptions here since DisableDefaults = true means HostApplicationBuilder won't.
         var serviceProviderFactory = GetServiceProviderFactory(_hostApplicationBuilder);
         _hostApplicationBuilder.ConfigureContainer(serviceProviderFactory);