From 2b07e88a581ef2ad1cccd6a68170cf5aba77c6e7 Mon Sep 17 00:00:00 2001 From: glennc Date: Thu, 13 Apr 2017 14:46:33 -0700 Subject: [PATCH] Add overloads to ConfigureServices to accept the WebHostBuilderContext and make the context accessible in more locations. --- .../IWebHostBuilder.cs | 20 ++++++- .../exceptions.net45.json | 14 ++++- .../exceptions.netcore.json | 16 +++++- .../WebHostBuilder.cs | 55 +++++++++++++------ .../WebHostBuilderExtensions.cs | 34 ++++++------ .../WebHostBuilderTests.cs | 27 ++++++++- 6 files changed, 126 insertions(+), 40 deletions(-) diff --git a/src/Microsoft.AspNetCore.Hosting.Abstractions/IWebHostBuilder.cs b/src/Microsoft.AspNetCore.Hosting.Abstractions/IWebHostBuilder.cs index b37fb88b55..7a9a183721 100644 --- a/src/Microsoft.AspNetCore.Hosting.Abstractions/IWebHostBuilder.cs +++ b/src/Microsoft.AspNetCore.Hosting.Abstractions/IWebHostBuilder.cs @@ -13,6 +13,15 @@ namespace Microsoft.AspNetCore.Hosting /// public interface IWebHostBuilder { + /// + /// The used during building. + /// + /// + /// Some properties of this type will be null whilst it is being built, most noteably the will + /// be null inside the method. + /// + WebHostBuilderContext Context { get; } + /// /// Builds an which hosts a web application. /// @@ -32,6 +41,13 @@ namespace Microsoft.AspNetCore.Hosting /// The . IWebHostBuilder ConfigureServices(Action configureServices); + /// + /// Specify the delegate that is used to configure the services of the web application. + /// + /// The delegate that configures the . + /// The . + IWebHostBuilder ConfigureServices(Action configureServices); + /// /// Adds a delegate for configuring the provided . This may be called multiple times. /// @@ -44,7 +60,7 @@ namespace Microsoft.AspNetCore.Hosting /// /// The delegate that configures the . /// The . - IWebHostBuilder ConfigureLogging(Action configureLogging) where T : ILoggerFactory; + IWebHostBuilder ConfigureLogging(Action configureLogging) where T : ILoggerFactory; /// /// Add or replace a setting in the configuration. @@ -75,6 +91,6 @@ namespace Microsoft.AspNetCore.Hosting /// /// The delegate for configuring the that will be used to construct an . /// The . - IWebHostBuilder ConfigureConfiguration(Action configureDelegate); + IWebHostBuilder ConfigureAppConfiguration(Action configureDelegate); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Hosting.Abstractions/exceptions.net45.json b/src/Microsoft.AspNetCore.Hosting.Abstractions/exceptions.net45.json index 8e5b3d3882..e10a179c25 100644 --- a/src/Microsoft.AspNetCore.Hosting.Abstractions/exceptions.net45.json +++ b/src/Microsoft.AspNetCore.Hosting.Abstractions/exceptions.net45.json @@ -2,7 +2,7 @@ { "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", - "NewMemberId": "Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureLogging(System.Action configureLogging) where T0 : Microsoft.Extensions.Logging.ILoggerFactory", + "NewMemberId": "Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureLogging(System.Action configureLogging) where T0 : Microsoft.Extensions.Logging.ILoggerFactory", "Kind": "Addition" }, { @@ -35,5 +35,17 @@ "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHost : System.IDisposable", "NewMemberId": "System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken)", "Kind": "Addition" + }, + { + "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", + "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", + "NewMemberId": "Microsoft.AspNetCore.Hosting.WebHostBuilderContext get_Context()", + "Kind": "Addition" + }, + { + "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", + "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", + "NewMemberId": "Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureServices(System.Action configureServices)", + "Kind": "Addition" } ] \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Hosting.Abstractions/exceptions.netcore.json b/src/Microsoft.AspNetCore.Hosting.Abstractions/exceptions.netcore.json index 8e5b3d3882..553e277848 100644 --- a/src/Microsoft.AspNetCore.Hosting.Abstractions/exceptions.netcore.json +++ b/src/Microsoft.AspNetCore.Hosting.Abstractions/exceptions.netcore.json @@ -2,7 +2,7 @@ { "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", - "NewMemberId": "Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureLogging(System.Action configureLogging) where T0 : Microsoft.Extensions.Logging.ILoggerFactory", + "NewMemberId": "Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureLogging(System.Action configureLogging) where T0 : Microsoft.Extensions.Logging.ILoggerFactory", "Kind": "Addition" }, { @@ -14,7 +14,7 @@ { "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", - "NewMemberId": "Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureConfiguration(System.Action configureDelegate)", + "NewMemberId": "Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureAppConfiguration(System.Action configureDelegate)", "Kind": "Addition" }, { @@ -35,5 +35,17 @@ "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHost : System.IDisposable", "NewMemberId": "System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken)", "Kind": "Addition" + }, + { + "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", + "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", + "NewMemberId": "Microsoft.AspNetCore.Hosting.WebHostBuilderContext get_Context()", + "Kind": "Addition" + }, + { + "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", + "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.IWebHostBuilder", + "NewMemberId": "Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureServices(System.Action configureServices)", + "Kind": "Addition" } ] \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs b/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs index e3c81f7eb1..b04522fa07 100644 --- a/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs +++ b/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs @@ -25,14 +25,17 @@ namespace Microsoft.AspNetCore.Hosting public class WebHostBuilder : IWebHostBuilder { private readonly IHostingEnvironment _hostingEnvironment; - private readonly List> _configureServicesDelegates; - private readonly List> _configureLoggingDelegates; + private readonly List> _configureServicesDelegates; + private readonly List> _configureLoggingDelegates; private IConfiguration _config; private WebHostOptions _options; private bool _webHostBuilt; private Func _createLoggerFactoryDelegate; private List> _configureConfigurationBuilderDelegates; + private WebHostBuilderContext _hostingContext; + + public WebHostBuilderContext Context { get { return _hostingContext; } } /// /// Initializes a new instance of the class. @@ -40,8 +43,8 @@ namespace Microsoft.AspNetCore.Hosting public WebHostBuilder() { _hostingEnvironment = new HostingEnvironment(); - _configureServicesDelegates = new List>(); - _configureLoggingDelegates = new List>(); + _configureServicesDelegates = new List>(); + _configureLoggingDelegates = new List>(); _configureConfigurationBuilderDelegates = new List>(); _config = new ConfigurationBuilder() @@ -113,6 +116,23 @@ namespace Microsoft.AspNetCore.Hosting throw new ArgumentNullException(nameof(configureServices)); } + _configureServicesDelegates.Add((_, collection) => configureServices(collection)); + return this; + } + + /// + /// Adds a delegate for configuring additional services for the host or web application. This may be called + /// multiple times. + /// + /// A delegate for configuring the . + /// The . + public IWebHostBuilder ConfigureServices(Action configureServices) + { + if (configureServices == null) + { + throw new ArgumentNullException(nameof(configureServices)); + } + _configureServicesDelegates.Add(configureServices); return this; } @@ -129,7 +149,7 @@ namespace Microsoft.AspNetCore.Hosting throw new ArgumentNullException(nameof(configureLogging)); } - _configureLoggingDelegates.Add(configureLogging); + _configureLoggingDelegates.Add((_, factory) => configureLogging(factory)); return this; } @@ -155,17 +175,17 @@ namespace Microsoft.AspNetCore.Hosting /// /// The delegate that configures the . /// The . - public IWebHostBuilder ConfigureLogging(Action configureLogging) where T : ILoggerFactory + public IWebHostBuilder ConfigureLogging(Action configureLogging) where T : ILoggerFactory { if (configureLogging == null) { throw new ArgumentNullException(nameof(configureLogging)); } - _configureLoggingDelegates.Add(factory => + _configureLoggingDelegates.Add((context, factory) => { if (factory is T typedFactory) { - configureLogging(typedFactory); + configureLogging(context, typedFactory); } }); return this; @@ -176,7 +196,7 @@ namespace Microsoft.AspNetCore.Hosting /// /// The delegate for configuring the that will be used to construct an . /// The . - public IWebHostBuilder ConfigureConfiguration(Action configureDelegate) + public IWebHostBuilder ConfigureAppConfiguration(Action configureDelegate) { if (configureDelegate == null) { @@ -241,14 +261,15 @@ namespace Microsoft.AspNetCore.Hosting var appEnvironment = PlatformServices.Default.Application; var contentRootPath = ResolveContentRootPath(_options.ContentRootPath, appEnvironment.ApplicationBasePath); var applicationName = _options.ApplicationName ?? appEnvironment.ApplicationName; - var hostingContext = new WebHostBuilderContext + + _hostingContext = new WebHostBuilderContext { Configuration = _config }; // Initialize the hosting environment _hostingEnvironment.Initialize(applicationName, contentRootPath, _options); - hostingContext.HostingEnvironment = _hostingEnvironment; + _hostingContext.HostingEnvironment = _hostingEnvironment; var services = new ServiceCollection(); services.AddSingleton(_hostingEnvironment); @@ -259,17 +280,17 @@ namespace Microsoft.AspNetCore.Hosting foreach (var configureConfiguration in _configureConfigurationBuilderDelegates) { - configureConfiguration(hostingContext, builder); + configureConfiguration(_hostingContext, builder); } var configuration = builder.Build(); services.AddSingleton(configuration); - hostingContext.Configuration = configuration; + _hostingContext.Configuration = configuration; // The configured ILoggerFactory is added as a singleton here. AddLogging below will not add an additional one. - var loggerFactory = _createLoggerFactoryDelegate?.Invoke(hostingContext) ?? new LoggerFactory(configuration.GetSection("Logging")); + var loggerFactory = _createLoggerFactoryDelegate?.Invoke(_hostingContext) ?? new LoggerFactory(configuration.GetSection("Logging")); services.AddSingleton(loggerFactory); - hostingContext.LoggerFactory = loggerFactory; + _hostingContext.LoggerFactory = loggerFactory; var exceptions = new List(); @@ -307,7 +328,7 @@ namespace Microsoft.AspNetCore.Hosting // Kept for back-compat, will remove once ConfigureLogging is removed. foreach (var configureLogging in _configureLoggingDelegates) { - configureLogging(loggerFactory); + configureLogging(_hostingContext, loggerFactory); } //This is required to add ILogger of T. @@ -362,7 +383,7 @@ namespace Microsoft.AspNetCore.Hosting foreach (var configureServices in _configureServicesDelegates) { - configureServices(services); + configureServices(_hostingContext, services); } return services; diff --git a/src/Microsoft.AspNetCore.Hosting/WebHostBuilderExtensions.cs b/src/Microsoft.AspNetCore.Hosting/WebHostBuilderExtensions.cs index 50a451a331..d7cdd3f4cc 100644 --- a/src/Microsoft.AspNetCore.Hosting/WebHostBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Hosting/WebHostBuilderExtensions.cs @@ -95,26 +95,28 @@ namespace Microsoft.AspNetCore.Hosting } /// - /// Configures and use a for the web host. + /// Adds a delegate for configuring the provided . This may be called multiple times. /// - /// The to configure. - /// A callback used to configure the that will be added as a singleton and used by the application. + /// The to configure. + /// The delegate that configures the . /// The . - public static IWebHostBuilder UseLoggerFactory(this IWebHostBuilder hostBuilder, Action configure) + public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action configureLogging) { - if (configure == null) - { - throw new ArgumentNullException(nameof(configure)); - } - - hostBuilder.UseLoggerFactory(context => - { - var loggerFactory = new LoggerFactory(); - configure(context, loggerFactory); - return loggerFactory; - }); - + hostBuilder.ConfigureLogging(configureLogging); return hostBuilder; } + + /// + /// Adds a delegate for configuring the provided . This may be called multiple times. + /// + /// The to configure. + /// The delegate that configures the . + /// The . + public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action configureLogging) where T : ILoggerFactory + { + hostBuilder.ConfigureLogging((_, factory) => configureLogging(factory)); + return hostBuilder; + } + } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs index 7d9934a8a9..4889ed7ceb 100644 --- a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs +++ b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs @@ -257,6 +257,29 @@ namespace Microsoft.AspNetCore.Hosting Assert.Same(loggerFactory, host.Services.GetService()); } + [Fact] + public void HostingContextCanBeUsed() + { + var hostBuilder = new WebHostBuilder() + .ConfigureAppConfiguration((context, configBuilder) => configBuilder + .AddInMemoryCollection( + new KeyValuePair[] + { + new KeyValuePair("key1", "value1") + })) + .ConfigureLogging((context, factory) => + { + Assert.Equal("value1", context.Configuration["key1"]); + }) + .UseServer(new TestServer()) + .UseStartup(); + + hostBuilder.Build(); + + //Verify property on builder is set. + Assert.Equal("value1", hostBuilder.Context.Configuration["key1"]); + } + [Fact] public void ConfigureLoggingCalledIfLoggerFactoryTypeMatches() { @@ -322,7 +345,7 @@ namespace Microsoft.AspNetCore.Hosting { var hostBuilder = new WebHostBuilder() .UseSetting("key1", "value1") - .ConfigureConfiguration((context, configBuilder) => + .ConfigureAppConfiguration((context, configBuilder) => { var config = configBuilder.Build(); Assert.Equal("value1", config["key1"]); @@ -336,7 +359,7 @@ namespace Microsoft.AspNetCore.Hosting public void CanConfigureConfigurationAndRetrieveFromDI() { var hostBuilder = new WebHostBuilder() - .ConfigureConfiguration((_, configBuilder) => + .ConfigureAppConfiguration((_, configBuilder) => { configBuilder .AddInMemoryCollection(