From 4cdc970055ef2ad77887109c4acde89278e0ce18 Mon Sep 17 00:00:00 2001 From: John Luo Date: Sun, 26 Mar 2017 01:07:39 -0700 Subject: [PATCH] Server addresses configuration enhancements Add PreferHostingUrls to IServerAdressesFeature Add extension to IWebHostBuilder to set this flag --- ...ingAbstractionsWebHostBuilderExtensions.cs | 12 + .../WebHostDefaults.cs | 1 + .../Features/IServerAddressesFeature.cs | 2 + .../exceptions.net45.json | 14 + .../exceptions.netcore.json | 14 + .../Internal/HostingEnvironmentExtensions.cs | 2 +- .../Internal/WebHost.cs | 5 +- .../Internal/WebHostOptions.cs | 9 +- .../Server/Features/ServerAddressesFeature.cs | 2 + .../WebHostConfigurationsTests.cs | 4 +- .../WebHostTests.cs | 428 ++++++++++-------- 11 files changed, 301 insertions(+), 192 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Hosting.Server.Abstractions/exceptions.net45.json create mode 100644 src/Microsoft.AspNetCore.Hosting.Server.Abstractions/exceptions.netcore.json diff --git a/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs b/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs index 767ed9263f..0d4b659d94 100644 --- a/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs @@ -145,6 +145,18 @@ namespace Microsoft.AspNetCore.Hosting return hostBuilder.UseSetting(WebHostDefaults.ServerUrlsKey, string.Join(ServerUrlsSeparator, urls)); } + /// + /// Indicate whether the host should listen on the URLs configured on the + /// instead of those configured on the . + /// + /// The to configure. + /// true to prefer URLs configured on the ; otherwise false. + /// The . + public static IWebHostBuilder PreferHostingUrls(this IWebHostBuilder hostBuilder, bool preferHostingUrls) + { + return hostBuilder.UseSetting(WebHostDefaults.PreferHostingUrls, preferHostingUrls ? "true" : "false"); + } + /// /// Start the web host and listen on the specified urls. /// diff --git a/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs b/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs index 6e75cf89af..98a10ebd0f 100644 --- a/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs +++ b/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs @@ -15,5 +15,6 @@ namespace Microsoft.AspNetCore.Hosting public static readonly string CaptureStartupErrorsKey = "captureStartupErrors"; public static readonly string ServerUrlsKey = "urls"; public static readonly string ContentRootKey = "contentRoot"; + public static readonly string PreferHostingUrls = "preferHostingUrls"; } } diff --git a/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/Features/IServerAddressesFeature.cs b/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/Features/IServerAddressesFeature.cs index 7c781b8485..24a9a267a5 100644 --- a/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/Features/IServerAddressesFeature.cs +++ b/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/Features/IServerAddressesFeature.cs @@ -8,5 +8,7 @@ namespace Microsoft.AspNetCore.Hosting.Server.Features public interface IServerAddressesFeature { ICollection Addresses { get; } + + bool PreferHostingUrls { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/exceptions.net45.json b/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/exceptions.net45.json new file mode 100644 index 0000000000..b26478ae79 --- /dev/null +++ b/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/exceptions.net45.json @@ -0,0 +1,14 @@ +[ + { + "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature", + "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature", + "NewMemberId": "System.Boolean get_PreferHostingUrls()", + "Kind": "Addition" + }, + { + "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature", + "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature", + "NewMemberId": "System.Void set_PreferHostingUrls(System.Boolean value)", + "Kind": "Addition" + } +] \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/exceptions.netcore.json b/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/exceptions.netcore.json new file mode 100644 index 0000000000..b26478ae79 --- /dev/null +++ b/src/Microsoft.AspNetCore.Hosting.Server.Abstractions/exceptions.netcore.json @@ -0,0 +1,14 @@ +[ + { + "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature", + "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature", + "NewMemberId": "System.Boolean get_PreferHostingUrls()", + "Kind": "Addition" + }, + { + "OldTypeId": "public interface Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature", + "NewTypeId": "public interface Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature", + "NewMemberId": "System.Void set_PreferHostingUrls(System.Boolean value)", + "Kind": "Addition" + } +] \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/HostingEnvironmentExtensions.cs b/src/Microsoft.AspNetCore.Hosting/Internal/HostingEnvironmentExtensions.cs index 50be22800b..7cb729714e 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/HostingEnvironmentExtensions.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/HostingEnvironmentExtensions.cs @@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal { hostingEnvironment.WebRootFileProvider = new NullFileProvider(); } - + hostingEnvironment.EnvironmentName = options.Environment ?? hostingEnvironment.EnvironmentName; diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs b/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs index 61653045f3..52e09b7591 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs @@ -249,12 +249,15 @@ namespace Microsoft.AspNetCore.Hosting.Internal { Server = _applicationServices.GetRequiredService(); - var addresses = Server.Features?.Get()?.Addresses; + var serverAddressesFeature = Server.Features?.Get(); + var addresses = serverAddressesFeature?.Addresses; if (addresses != null && !addresses.IsReadOnly && addresses.Count == 0) { var urls = _config[WebHostDefaults.ServerUrlsKey] ?? _config[DeprecatedServerUrlsKey]; if (!string.IsNullOrEmpty(urls)) { + serverAddressesFeature.PreferHostingUrls = _options.PreferHostingUrls; + foreach (var value in urls.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { addresses.Add(value); diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/WebHostOptions.cs b/src/Microsoft.AspNetCore.Hosting/Internal/WebHostOptions.cs index 4bc64f7af4..0a2f216e9a 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/WebHostOptions.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/WebHostOptions.cs @@ -9,9 +9,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal { public class WebHostOptions { - public WebHostOptions() - { - } + public WebHostOptions() { } public WebHostOptions(IConfiguration configuration) { @@ -28,6 +26,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal WebRoot = configuration[WebHostDefaults.WebRootKey]; ContentRootPath = configuration[WebHostDefaults.ContentRootKey]; HostingStartupAssemblies = configuration[WebHostDefaults.HostingStartupAssembliesKey]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0]; + PreferHostingUrls = ParseBool(configuration, WebHostDefaults.PreferHostingUrls); } public string ApplicationName { get; set; } @@ -39,13 +38,15 @@ namespace Microsoft.AspNetCore.Hosting.Internal public bool CaptureStartupErrors { get; set; } public string Environment { get; set; } - + public string StartupAssembly { get; set; } public string WebRoot { get; set; } public string ContentRootPath { get; set; } + public bool PreferHostingUrls { get; set; } + private static bool ParseBool(IConfiguration configuration, string key) { return string.Equals("true", configuration[key], StringComparison.OrdinalIgnoreCase) diff --git a/src/Microsoft.AspNetCore.Hosting/Server/Features/ServerAddressesFeature.cs b/src/Microsoft.AspNetCore.Hosting/Server/Features/ServerAddressesFeature.cs index 4f8e1bdb3d..098ec8cdb0 100644 --- a/src/Microsoft.AspNetCore.Hosting/Server/Features/ServerAddressesFeature.cs +++ b/src/Microsoft.AspNetCore.Hosting/Server/Features/ServerAddressesFeature.cs @@ -8,5 +8,7 @@ namespace Microsoft.AspNetCore.Hosting.Server.Features public class ServerAddressesFeature : IServerAddressesFeature { public ICollection Addresses { get; } = new List(); + + public bool PreferHostingUrls { get; set; } } } diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostConfigurationsTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostConfigurationsTests.cs index 5f4291d75e..ab9339496c 100644 --- a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostConfigurationsTests.cs +++ b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostConfigurationsTests.cs @@ -20,7 +20,8 @@ namespace Microsoft.AspNetCore.Hosting.Tests { "startupAssembly", "MyProjectReference" }, { "environment", "Development"}, { "detailederrors", "true"}, - { "captureStartupErrors", "true" } + { "captureStartupErrors", "true" }, + { "preferHostingUrls", "true" } }; var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build()); @@ -31,6 +32,7 @@ namespace Microsoft.AspNetCore.Hosting.Tests Assert.Equal("Development", config.Environment); Assert.True(config.CaptureStartupErrors); Assert.True(config.DetailedErrors); + Assert.True(config.PreferHostingUrls); } [Fact] diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs index 5cb06f69e6..6a6c833c86 100644 --- a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs +++ b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs @@ -67,15 +67,19 @@ namespace Microsoft.AspNetCore.Hosting } [Fact] - public void NoDefaultAddressesIfNotConfigured() + public void NoDefaultAddressesAndDoNotPreferHostingUrlsIfNotConfigured() { - var host = CreateBuilder().UseServer(this).Build(); - host.Start(); - Assert.Equal(false, host.ServerFeatures.Get().Addresses.Any()); + using (var host = CreateBuilder().UseServer(this).Build()) + { + host.Start(); + var serverAddressesFeature = host.ServerFeatures.Get(); + Assert.False(serverAddressesFeature.Addresses.Any()); + Assert.False(serverAddressesFeature.PreferHostingUrls); + } } [Fact] - public void UsesLegacyConfigurationForAddresses() + public void UsesLegacyConfigurationForAddressesAndDoNotPreferHostingUrlsIfNotConfigured() { var data = new Dictionary { @@ -84,13 +88,17 @@ namespace Microsoft.AspNetCore.Hosting var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build(); - var host = CreateBuilder(config).UseServer(this).Build(); - host.Start(); - Assert.Equal("http://localhost:5002", host.ServerFeatures.Get().Addresses.First()); + using (var host = CreateBuilder(config).UseServer(this).Build()) + { + host.Start(); + var serverAddressFeature = host.ServerFeatures.Get(); + Assert.Equal("http://localhost:5002", serverAddressFeature.Addresses.First()); + Assert.False(serverAddressFeature.PreferHostingUrls); + } } [Fact] - public void UsesConfigurationForAddresses() + public void UsesConfigurationForAddressesAndDoNotPreferHostingUrlsIfNotConfigured() { var data = new Dictionary { @@ -99,13 +107,17 @@ namespace Microsoft.AspNetCore.Hosting var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build(); - var host = CreateBuilder(config).UseServer(this).Build(); - host.Start(); - Assert.Equal("http://localhost:5003", host.ServerFeatures.Get().Addresses.First()); + using (var host = CreateBuilder(config).UseServer(this).Build()) + { + host.Start(); + var serverAddressFeature = host.ServerFeatures.Get(); + Assert.Equal("http://localhost:5003", serverAddressFeature.Addresses.First()); + Assert.False(serverAddressFeature.PreferHostingUrls); + } } [Fact] - public void UsesNewConfigurationOverLegacyConfigForAddresses() + public void UsesNewConfigurationOverLegacyConfigForAddressesAndDoNotPreferHostingUrlsIfNotConfigured() { var data = new Dictionary { @@ -115,121 +127,157 @@ namespace Microsoft.AspNetCore.Hosting var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build(); - var host = CreateBuilder(config).UseServer(this).Build(); - host.Start(); - Assert.Equal("http://localhost:5009", host.ServerFeatures.Get().Addresses.First()); + using (var host = CreateBuilder(config).UseServer(this).Build()) + { + host.Start(); + var serverAddressFeature = host.ServerFeatures.Get(); + Assert.Equal("http://localhost:5009", serverAddressFeature.Addresses.First()); + Assert.False(serverAddressFeature.PreferHostingUrls); + } + } + + [Fact] + public void DoNotPreferHostingUrlsWhenNoAddressConfigured() + { + using (var host = CreateBuilder().UseServer(this).PreferHostingUrls(true).Build()) + { + host.Start(); + var serverAddressesFeature = host.ServerFeatures.Get(); + Assert.Empty(serverAddressesFeature.Addresses); + Assert.False(serverAddressesFeature.PreferHostingUrls); + } + } + + [Fact] + public void PreferHostingUrlsWhenAddressIsConfigured() + { + var data = new Dictionary + { + { "urls", "http://localhost:5003" } + }; + + var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build(); + + using (var host = CreateBuilder(config).UseServer(this).PreferHostingUrls(true).Build()) + { + host.Start(); + Assert.True(host.ServerFeatures.Get().PreferHostingUrls); + } } [Fact] public void WebHostCanBeStarted() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .UseStartup("Microsoft.AspNetCore.Hosting.Tests") - .Start(); + .Start()) + { + Assert.NotNull(host); + Assert.Equal(1, _startInstances.Count); + Assert.Equal(0, _startInstances[0].DisposeCalls); - Assert.NotNull(host); - Assert.Equal(1, _startInstances.Count); - Assert.Equal(0, _startInstances[0].DisposeCalls); + host.Dispose(); - host.Dispose(); - - Assert.Equal(0, _startInstances[0].DisposeCalls); + Assert.Equal(0, _startInstances[0].DisposeCalls); + } } [Fact] public void WebHostShutsDownWhenTokenTriggers() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .UseStartup("Microsoft.AspNetCore.Hosting.Tests") - .Build(); + .Build()) + { + var lifetime = host.Services.GetRequiredService(); - var lifetime = host.Services.GetRequiredService(); + var cts = new CancellationTokenSource(); - var cts = new CancellationTokenSource(); + Task.Run(() => host.Run(cts.Token)); - Task.Run(() => host.Run(cts.Token)); + // Wait on the host to be started + lifetime.ApplicationStarted.WaitHandle.WaitOne(); - // Wait on the host to be started - lifetime.ApplicationStarted.WaitHandle.WaitOne(); + Assert.Equal(1, _startInstances.Count); + Assert.Equal(0, _startInstances[0].DisposeCalls); - Assert.Equal(1, _startInstances.Count); - Assert.Equal(0, _startInstances[0].DisposeCalls); + cts.Cancel(); - cts.Cancel(); + // Wait on the host to shutdown + lifetime.ApplicationStopped.WaitHandle.WaitOne(); - // Wait on the host to shutdown - lifetime.ApplicationStopped.WaitHandle.WaitOne(); - - Assert.Equal(0, _startInstances[0].DisposeCalls); + Assert.Equal(0, _startInstances[0].DisposeCalls); + } } [Fact] public void WebHostApplicationLifetimeEventsOrderedCorrectlyDuringShutdown() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .UseStartup("Microsoft.AspNetCore.Hosting.Tests") - .Build(); - - var lifetime = host.Services.GetRequiredService(); - var applicationStartedEvent = new ManualResetEventSlim(false); - var applicationStoppingEvent = new ManualResetEventSlim(false); - var applicationStoppedEvent = new ManualResetEventSlim(false); - var applicationStartedCompletedBeforeApplicationStopping = false; - var applicationStoppingCompletedBeforeApplicationStopped = false; - var applicationStoppedCompletedBeforeRunCompleted = false; - - lifetime.ApplicationStarted.Register(() => + .Build()) { - applicationStartedEvent.Set(); - }); + var lifetime = host.Services.GetRequiredService(); + var applicationStartedEvent = new ManualResetEventSlim(false); + var applicationStoppingEvent = new ManualResetEventSlim(false); + var applicationStoppedEvent = new ManualResetEventSlim(false); + var applicationStartedCompletedBeforeApplicationStopping = false; + var applicationStoppingCompletedBeforeApplicationStopped = false; + var applicationStoppedCompletedBeforeRunCompleted = false; - lifetime.ApplicationStopping.Register(() => - { - // Check whether the applicationStartedEvent has been set - applicationStartedCompletedBeforeApplicationStopping = applicationStartedEvent.IsSet; + lifetime.ApplicationStarted.Register(() => + { + applicationStartedEvent.Set(); + }); - // Simulate work. - Thread.Sleep(1000); + lifetime.ApplicationStopping.Register(() => + { + // Check whether the applicationStartedEvent has been set + applicationStartedCompletedBeforeApplicationStopping = applicationStartedEvent.IsSet; - applicationStoppingEvent.Set(); - }); + // Simulate work. + Thread.Sleep(1000); - lifetime.ApplicationStopped.Register(() => - { - // Check whether the applicationStoppingEvent has been set - applicationStoppingCompletedBeforeApplicationStopped = applicationStoppingEvent.IsSet; - applicationStoppedEvent.Set(); - }); + applicationStoppingEvent.Set(); + }); - var runHostAndVerifyApplicationStopped = Task.Run(() => - { - host.Run(); - // Check whether the applicationStoppingEvent has been set - applicationStoppedCompletedBeforeRunCompleted = applicationStoppedEvent.IsSet; - }); + lifetime.ApplicationStopped.Register(() => + { + // Check whether the applicationStoppingEvent has been set + applicationStoppingCompletedBeforeApplicationStopped = applicationStoppingEvent.IsSet; + applicationStoppedEvent.Set(); + }); - // Wait until application has started to shut down the host - Assert.True(applicationStartedEvent.Wait(5000)); + var runHostAndVerifyApplicationStopped = Task.Run(() => + { + host.Run(); + // Check whether the applicationStoppingEvent has been set + applicationStoppedCompletedBeforeRunCompleted = applicationStoppedEvent.IsSet; + }); - // Trigger host shutdown on a separate thread - Task.Run(() => lifetime.StopApplication()); + // Wait until application has started to shut down the host + Assert.True(applicationStartedEvent.Wait(5000)); - // Wait for all events and host.Run() to complete - Assert.True(runHostAndVerifyApplicationStopped.Wait(5000)); + // Trigger host shutdown on a separate thread + Task.Run(() => lifetime.StopApplication()); - // Verify Ordering - Assert.True(applicationStartedCompletedBeforeApplicationStopping); - Assert.True(applicationStoppingCompletedBeforeApplicationStopped); - Assert.True(applicationStoppedCompletedBeforeRunCompleted); + // Wait for all events and host.Run() to complete + Assert.True(runHostAndVerifyApplicationStopped.Wait(5000)); + + // Verify Ordering + Assert.True(applicationStartedCompletedBeforeApplicationStopping); + Assert.True(applicationStoppingCompletedBeforeApplicationStopped); + Assert.True(applicationStoppedCompletedBeforeRunCompleted); + } } [Fact] public void WebHostDisposesServiceProvider() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .ConfigureServices(s => { @@ -237,33 +285,34 @@ namespace Microsoft.AspNetCore.Hosting s.AddSingleton(); }) .UseStartup("Microsoft.AspNetCore.Hosting.Tests") - .Build(); + .Build()) + { + host.Start(); - host.Start(); + var singleton = (FakeService)host.Services.GetService(); + var transient = (FakeService)host.Services.GetService(); - var singleton = (FakeService)host.Services.GetService(); - var transient = (FakeService)host.Services.GetService(); + Assert.False(singleton.Disposed); + Assert.False(transient.Disposed); - Assert.False(singleton.Disposed); - Assert.False(transient.Disposed); + host.Dispose(); - host.Dispose(); - - Assert.True(singleton.Disposed); - Assert.True(transient.Disposed); + Assert.True(singleton.Disposed); + Assert.True(transient.Disposed); + } } [Fact] public void WebHostNotifiesApplicationStarted() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) - .Build(); - var applicationLifetime = host.Services.GetService(); - - Assert.False(applicationLifetime.ApplicationStarted.IsCancellationRequested); - using (host) + .Build()) { + var applicationLifetime = host.Services.GetService(); + + Assert.False(applicationLifetime.ApplicationStarted.IsCancellationRequested); + host.Start(); Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested); } @@ -272,17 +321,16 @@ namespace Microsoft.AspNetCore.Hosting [Fact] public void WebHostNotifiesAllIApplicationLifetimeCallbacksEvenIfTheyThrow() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) - .Build(); - var applicationLifetime = host.Services.GetService(); - - var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted); - var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping); - var stopped = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopped); - - using (host) + .Build()) { + var applicationLifetime = host.Services.GetService(); + + var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted); + var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping); + var stopped = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopped); + host.Start(); Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested); Assert.True(started.All(s => s)); @@ -298,16 +346,14 @@ namespace Microsoft.AspNetCore.Hosting bool[] events1 = null; bool[] events2 = null; - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .ConfigureServices(services => { events1 = RegisterCallbacksThatThrow(services); events2 = RegisterCallbacksThatThrow(services); }) - .Build(); - - using (host) + .Build()) { host.Start(); Assert.True(events1[0]); @@ -323,7 +369,7 @@ namespace Microsoft.AspNetCore.Hosting { var stoppingCalls = 0; - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .ConfigureServices(services => { @@ -338,12 +384,11 @@ namespace Microsoft.AspNetCore.Hosting services.AddSingleton(new DelegateHostedService(started, stopping)); }) - .Build(); - var lifetime = host.Services.GetRequiredService(); - lifetime.StopApplication(); - - using (host) + .Build()) { + var lifetime = host.Services.GetRequiredService(); + lifetime.StopApplication(); + host.Start(); Assert.Equal(0, stoppingCalls); @@ -353,40 +398,44 @@ namespace Microsoft.AspNetCore.Hosting [Fact] public void HostedServiceCanInjectApplicationLifetime() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .ConfigureServices(services => { services.AddSingleton(); }) - .Build(); - var lifetime = host.Services.GetRequiredService(); - lifetime.StopApplication(); + .Build()) + { + var lifetime = host.Services.GetRequiredService(); + lifetime.StopApplication(); - host.Start(); - var svc = (TestHostedService)host.Services.GetRequiredService(); - Assert.True(svc.StartCalled); - host.Dispose(); - Assert.True(svc.StopCalled); + host.Start(); + var svc = (TestHostedService)host.Services.GetRequiredService(); + Assert.True(svc.StartCalled); + host.Dispose(); + Assert.True(svc.StopCalled); + } } [Fact] public void HostedServiceStartNotCalledIfWebHostNotStarted() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .ConfigureServices(services => { services.AddSingleton(); }) - .Build(); - var lifetime = host.Services.GetRequiredService(); - lifetime.StopApplication(); + .Build()) + { + var lifetime = host.Services.GetRequiredService(); + lifetime.StopApplication(); - var svc = (TestHostedService)host.Services.GetRequiredService(); - Assert.False(svc.StartCalled); - host.Dispose(); - Assert.False(svc.StopCalled); + var svc = (TestHostedService)host.Services.GetRequiredService(); + Assert.False(svc.StartCalled); + host.Dispose(); + Assert.False(svc.StopCalled); + } } [Fact] @@ -395,7 +444,7 @@ namespace Microsoft.AspNetCore.Hosting var stoppingCalls = 0; var startedCalls = 0; - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .ConfigureServices(services => { @@ -411,10 +460,10 @@ namespace Microsoft.AspNetCore.Hosting services.AddSingleton(new DelegateHostedService(started, stopping)); }) - .Build(); - var lifetime = host.Services.GetRequiredService(); - using (host) + .Build()) { + var lifetime = host.Services.GetRequiredService(); + host.Start(); host.Dispose(); @@ -429,21 +478,20 @@ namespace Microsoft.AspNetCore.Hosting bool[] events1 = null; bool[] events2 = null; - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .ConfigureServices(services => { events1 = RegisterCallbacksThatThrow(services); events2 = RegisterCallbacksThatThrow(services); }) - .Build(); - var applicationLifetime = host.Services.GetService(); - - var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted); - var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping); - - using (host) + .Build()) { + var applicationLifetime = host.Services.GetService(); + + var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted); + var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping); + host.Start(); Assert.True(events1[0]); Assert.True(events2[0]); @@ -458,13 +506,11 @@ namespace Microsoft.AspNetCore.Hosting [Fact] public void WebHostInjectsHostingEnvironment() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .UseStartup("Microsoft.AspNetCore.Hosting.Tests") .UseEnvironment("WithHostingEnvironment") - .Build(); - - using (host) + .Build()) { host.Start(); var env = host.Services.GetService(); @@ -489,8 +535,10 @@ namespace Microsoft.AspNetCore.Hosting [Fact] public void CanCreateApplicationServicesWithAddedServices() { - var host = CreateBuilder().UseServer(this).ConfigureServices(services => services.AddOptions()).Build(); - Assert.NotNull(host.Services.GetRequiredService>()); + using (var host = CreateBuilder().UseServer(this).ConfigureServices(services => services.AddOptions()).Build()) + { + Assert.NotNull(host.Services.GetRequiredService>()); + } } [Fact] @@ -498,7 +546,7 @@ namespace Microsoft.AspNetCore.Hosting { // Verify ordering var configureOrder = 0; - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .ConfigureServices(services => { @@ -511,8 +559,10 @@ namespace Microsoft.AspNetCore.Hosting () => Assert.Equal(3, configureOrder++), () => Assert.Equal(4, configureOrder++))); }) - .Build(); - Assert.Equal(6, configureOrder); + .Build()) + { + Assert.Equal(6, configureOrder); + } } private class TestFilter : IStartupFilter @@ -543,9 +593,11 @@ namespace Microsoft.AspNetCore.Hosting [Fact] public void EnvDefaultsToProductionIfNoConfig() { - var host = CreateBuilder().UseServer(this).Build(); - var env = host.Services.GetService(); - Assert.Equal(EnvironmentName.Production, env.EnvironmentName); + using (var host = CreateBuilder().UseServer(this).Build()) + { + var env = host.Services.GetService(); + Assert.Equal(EnvironmentName.Production, env.EnvironmentName); + } } [Fact] @@ -560,9 +612,11 @@ namespace Microsoft.AspNetCore.Hosting .AddInMemoryCollection(vals); var config = builder.Build(); - var host = CreateBuilder(config).UseServer(this).Build(); - var env = host.Services.GetService(); - Assert.Equal("Staging", env.EnvironmentName); + using (var host = CreateBuilder(config).UseServer(this).Build()) + { + var env = host.Services.GetService(); + Assert.Equal("Staging", env.EnvironmentName); + } } [Fact(Skip = "Missing content publish property")] @@ -577,17 +631,18 @@ namespace Microsoft.AspNetCore.Hosting .AddInMemoryCollection(vals); var config = builder.Build(); - var host = CreateBuilder(config).UseServer(this).Build(); - var env = host.Services.GetService(); - Assert.Equal(Path.GetFullPath("testroot"), env.WebRootPath); - Assert.True(env.WebRootFileProvider.GetFileInfo("TextFile.txt").Exists); + using (var host = CreateBuilder(config).UseServer(this).Build()) + { + var env = host.Services.GetService(); + Assert.Equal(Path.GetFullPath("testroot"), env.WebRootPath); + Assert.True(env.WebRootFileProvider.GetFileInfo("TextFile.txt").Exists); + } } [Fact] public void IsEnvironment_Extension_Is_Case_Insensitive() { - var host = CreateBuilder().UseServer(this).Build(); - using (host) + using (var host = CreateBuilder().UseServer(this).Build()) { host.Start(); var env = host.Services.GetRequiredService(); @@ -606,16 +661,18 @@ namespace Microsoft.AspNetCore.Hosting httpContext = innerHttpContext; return Task.FromResult(0); }); - var host = CreateHost(requestDelegate); - // Act - host.Start(); + using (var host = CreateHost(requestDelegate)) + { + // Act + host.Start(); - // Assert - Assert.NotNull(httpContext); - var featuresTraceIdentifier = httpContext.Features.Get().TraceIdentifier; - Assert.False(string.IsNullOrWhiteSpace(httpContext.TraceIdentifier)); - Assert.Same(httpContext.TraceIdentifier, featuresTraceIdentifier); + // Assert + Assert.NotNull(httpContext); + var featuresTraceIdentifier = httpContext.Features.Get().TraceIdentifier; + Assert.False(string.IsNullOrWhiteSpace(httpContext.TraceIdentifier)); + Assert.Same(httpContext.TraceIdentifier, featuresTraceIdentifier); + } } [Fact] @@ -630,24 +687,25 @@ namespace Microsoft.AspNetCore.Hosting }); var requestIdentifierFeature = new StubHttpRequestIdentifierFeature(); _featuresSupportedByThisHost[typeof(IHttpRequestIdentifierFeature)] = requestIdentifierFeature; - var host = CreateHost(requestDelegate); - // Act - host.Start(); + using (var host = CreateHost(requestDelegate)) + { + // Act + host.Start(); - // Assert - Assert.NotNull(httpContext); - Assert.Same(requestIdentifierFeature, httpContext.Features.Get()); + // Assert + Assert.NotNull(httpContext); + Assert.Same(requestIdentifierFeature, httpContext.Features.Get()); + } } [Fact] public void WebHost_InvokesConfigureMethodsOnlyOnce() { - var host = CreateBuilder() + using (var host = CreateBuilder() .UseServer(this) .UseStartup() - .Build(); - using (host) + .Build()) { host.Start(); var services = host.Services;