-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve HostBuilder and WebApplicationBuilder Configuration integration #61634
Comments
Tagging subscribers to this area: @eerhardt, @maryamariyan Issue DetailsToday The synchronization is not perfect and can lead to bugs like dotnet/aspnetcore#38185. We should look into adding an API to
|
@halter73 - Do you have an idea of what the API would look like? Can you update the issue to use the API proposal template? |
Here's an API proposal that's an alternative to diff --git a/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs b/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs
index 742dde5a32a..0434b96536f 100644
--- a/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs
+++ b/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs
@@ -25,9 +25,31 @@ public partial class ConsoleLifetimeOptions
}
public static partial class Host
{
+ public static Microsoft.Extensions.Hosting.HostApplicationBuilder CreateApplicationBuilder() { throw null; }
+ public static Microsoft.Extensions.Hosting.HostApplicationBuilder CreateApplicationBuilder(string[] args) { throw null; }
public static Microsoft.Extensions.Hosting.IHostBuilder CreateDefaultBuilder() { throw null; }
public static Microsoft.Extensions.Hosting.IHostBuilder CreateDefaultBuilder(string[] args) { throw null; }
}
+ public partial class HostApplicationBuilder
+ {
+ public HostApplicationBuilder(Microsoft.Extensions.Hosting.HostApplicationOptions options) { }
+ public Microsoft.Extensions.Configuration.ConfigurationManager Configuration { get { throw null; } }
+ public Microsoft.Extensions.Hosting.IHostEnvironment Environment { get { throw null; } }
+ public Microsoft.Extensions.Logging.ILoggingBuilder Logging { get { throw null; } }
+ public Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get { throw null; } }
+ public Microsoft.Extensions.Hosting.IHost Build() { throw null; }
+ public Microsoft.Extensions.Hosting.IHost Build<TContainerBuilder>(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder> serviceProviderFactory) { throw null; }
+ }
+ public partial class HostApplicationOptions
+ {
+ public HostApplicationOptions() { }
+ public string ApplicationName { get { throw null; } set { } }
+ public string[] Args { get { throw null; } set { } }
+ public string ContentRootPath { get { throw null; } set { } }
+ public bool DisableDefaults { get { throw null; } set { } }
+ public string EnvironmentName { get { throw null; } set { } }
+ public Microsoft.Extensions.Configuration.ConfigurationManager InitialConfiguration { get { throw null; } set { } }
+ }
public partial class HostBuilder : Microsoft.Extensions.Hosting.IHostBuilder
{
public HostBuilder() { } Sample Usagevar builder = Host.CreateApplicationBuilder(args);
builder.Configuration.AddJsonFile("myconfig.json");
Console.WriteLine($"MyConfigVariable = ${builder.Configuration["MyConfigVariable"]}");
builder.Services.AddHostedService<MyHostedService>();
var minConsoleLogLevel = builder.Environment.IsDevelopment() ? LogLevel.Trace : LogLevel.Warning;
builder.Logging.AddFilter<ConsoleLoggerProvider>(level => level >= minConsoleLogLevel);
builder.Build().Run(); Equivalent HostBuilder Samplevar builder = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(hostConfig =>
{
hostConfig.AddJsonFile("myconfig.json");
})
.ConfigureServices((context, services) =>
{
Console.WriteLine($"MyConfigVariable = ${context.Configuration["MyConfigVariable"]}");
services.AddHostedService<MyHostedService>();
})
.ConfigureLogging((context, logging) =>
{
var minConsoleLogLevel = context.HostingEnvironment.IsDevelopment() ? LogLevel.Trace : LogLevel.Warning;
logging.AddFilter<ConsoleLoggerProvider>(level => level >= minConsoleLogLevel);
});
builder.Build().Run(); I've started experimenting with this API here. And you can see how it might be consumed from WebApplicationBuilder here. It seems like we can share a fair amount of logic with the existing HostBuilder and share the same Host. I'm going to close #61635 because it's resolved by the same API. The name of the new types are |
I have been looking at the implementation of I would like to apply the same logic for Console Apps using GenericHost. What I see is that I would need to copy multiple times the sources back and forth between the Generic Host's configuration builder and |
namespace Microsoft.Extensions.Hosting
{
public static partial class Host
{
public static HostApplicationBuilder CreateApplicationBuilder();
public static HostApplicationBuilder CreateApplicationBuilder(string[] args);
public static IHostBuilder CreateDefaultBuilder();
public static IHostBuilder CreateDefaultBuilder(string[] args);
}
public sealed class HostApplicationBuilder
{
public HostApplicationBuilder();
public HostApplicationBuilder(string[] args);
public HostApplicationBuilder(HostApplicationBuilderSettings settings);
public ConfigurationManager Configuration { get; }
public IHostEnvironment Environment { get; }
public ILoggingBuilder Logging { get; }
public IServiceCollection Services { get; }
public IHost Build();
public void ConfigureContainer<TBuilder>(IServiceProviderFactory<TBuilder> factory, Action<TBuilder>? configure = null) where TBuilder : notnull;
}
public sealed class HostApplicationBuilderSettings
{
public HostApplicationBuilderSettings();
public string ApplicationName { get; set; }
public string[] Args { get; set; }
public string ContentRootPath { get; set; }
public bool DisableDefaults { get; set; }
public string EnvironmentName { get; set; }
public ConfigurationManager Configuration { get; set; }
}
} |
With the new runtime/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHostBuilderExtensions.cs Line 32 in 9293aab
and Line 45 in 9293aab
So these extensions can be used with the new model. |
My suggestion for these would be to add The only exception is namespace Microsoft.Extensions.Hosting
{
public static class SystemdServiceCollectionExtensions
{
public static IServiceCollection UseSystemd(this IServiceCollection services);
}
public static class WindowsServiceLifetimeServiceCollectionExtensions
{
public static IServiceCollection UseWindowsService(this IServiceCollection services);
public static IServiceCollection UseWindowsService(this IServiceCollection services, Action<WindowsServiceLifetimeOptions> configure);
}
} Should I open a new issue with the API proposal or just put this back in the queue? |
I think either? |
Instead of making new types for the feature parity extension methods, we think it's best to put them on their (slightly inappropriately named) existing types. namespace Microsoft.Extensions.Hosting
{
public static partial class Host
{
public static HostApplicationBuilder CreateApplicationBuilder();
public static HostApplicationBuilder CreateApplicationBuilder(string[] args);
public static IHostBuilder CreateDefaultBuilder();
public static IHostBuilder CreateDefaultBuilder(string[] args);
}
public sealed class HostApplicationBuilder
{
public HostApplicationBuilder();
public HostApplicationBuilder(string[] args);
public HostApplicationBuilder(HostApplicationBuilderSettings settings);
public ConfigurationManager Configuration { get; }
public IHostEnvironment Environment { get; }
public ILoggingBuilder Logging { get; }
public IServiceCollection Services { get; }
public IHost Build();
public void ConfigureContainer<TBuilder>(IServiceProviderFactory<TBuilder> factory, Action<TBuilder>? configure = null) where TBuilder : notnull;
}
public sealed class HostApplicationBuilderSettings
{
public HostApplicationBuilderSettings();
public string ApplicationName { get; set; }
public string[] Args { get; set; }
public string ContentRootPath { get; set; }
public bool DisableDefaults { get; set; }
public string EnvironmentName { get; set; }
public ConfigurationManager Configuration { get; set; }
}
public partial static class SystemdHostBuilderExtensions
{
public static IServiceCollection UseSystemd(this IServiceCollection services);
}
public partial static class WindowsServiceLifetimeHostBuilderExtensions
{
public static IServiceCollection UseWindowsService(this IServiceCollection services);
public static IServiceCollection UseWindowsService(this IServiceCollection services, Action<WindowsServiceLifetimeOptions> configure);
}
} |
The |
Correct. While it was nice to be able to add a web host to any arbitrary Is the some scenario that you have @WeihanLi where you'd want to use |
@halter73 thanks for your reply, just to confirm, |
Why not instead add a new type |
@nvmkpk What would that solve? |
@davidfowl It would provide a common base implementation for |
Is that related to this issue? |
Yes, rather than making changes to |
This issue is about configuration... |
Yes but that is to make it easier to use in |
I want to make a slight change to the approved I want to rename these extension methods to Here's the proposed diff from the already-approved API: namespace Microsoft.Extensions.Hosting
{
public static class SystemdServiceCollectionExtensions
{
- public static IServiceCollection UseSystemd(this IServiceCollection services);
+ public static IServiceCollection AddSystemd(this IServiceCollection services);
}
public static class WindowsServiceLifetimeServiceCollectionExtensions
{
- public static IServiceCollection UseWindowsService(this IServiceCollection services);
+ public static IServiceCollection AddWindowsService(this IServiceCollection services);
- public static IServiceCollection UseWindowsService(this IServiceCollection services, Action<WindowsServiceLifetimeOptions> configure);
+ public static IServiceCollection AddWindowsService(this IServiceCollection services, Action<WindowsServiceLifetimeOptions> configure);
}
} Sample Usagevar builder = Host.CreateApplicationBuilder(args);
builder.Services.AddWindowsService();
builder.Services.AddHostedService<MyHostedService>();
builder.Build().Run(); |
Thank you @halter73 |
The rename looks good as proposed. namespace Microsoft.Extensions.Hosting
{
public static class SystemdServiceCollectionExtensions
{
- public static IServiceCollection UseSystemd(this IServiceCollection services);
+ public static IServiceCollection AddSystemd(this IServiceCollection services);
}
public static class WindowsServiceLifetimeServiceCollectionExtensions
{
- public static IServiceCollection UseWindowsService(this IServiceCollection services);
+ public static IServiceCollection AddWindowsService(this IServiceCollection services);
- public static IServiceCollection UseWindowsService(this IServiceCollection services, Action<WindowsServiceLifetimeOptions> configure);
+ public static IServiceCollection AddWindowsService(this IServiceCollection services, Action<WindowsServiceLifetimeOptions> configure);
}
} |
Thanks again for the help @eerhardt! |
Today
WebApplicationBuilder
has some hacky logic to synchronize theWebApplicationBuilder.Configuration
ConfigurationManager
and theHostBuilder
's appIConfiguration
in case any custom configuration sources have been added via HostFactoryResolver. This logic can be found here.The synchronization is not perfect and can lead to bugs like dotnet/aspnetcore#38185. We should look into adding an API to
HostBuilder
to shareIConfigurationBuilder
(s) with theWebApplicationBuilder
.The text was updated successfully, but these errors were encountered: