Server addresses configuration enhancements

Add PreferHostingUrls to IServerAdressesFeature

Add extension to IWebHostBuilder to set this flag
This commit is contained in:
John Luo 2017-03-26 01:07:39 -07:00
parent f15c99c980
commit 4cdc970055
11 changed files with 301 additions and 192 deletions

View File

@ -145,6 +145,18 @@ namespace Microsoft.AspNetCore.Hosting
return hostBuilder.UseSetting(WebHostDefaults.ServerUrlsKey, string.Join(ServerUrlsSeparator, urls)); return hostBuilder.UseSetting(WebHostDefaults.ServerUrlsKey, string.Join(ServerUrlsSeparator, urls));
} }
/// <summary>
/// Indicate whether the host should listen on the URLs configured on the <see cref="IWebHostBuilder"/>
/// instead of those configured on the <see cref="IServer"/>.
/// </summary>
/// <param name="hostBuilder">The <see cref="IWebHostBuilder"/> to configure.</param>
/// <param name="preferHostingUrls"><c>true</c> to prefer URLs configured on the <see cref="IWebHostBuilder"/>; otherwise <c>false</c>.</param>
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
public static IWebHostBuilder PreferHostingUrls(this IWebHostBuilder hostBuilder, bool preferHostingUrls)
{
return hostBuilder.UseSetting(WebHostDefaults.PreferHostingUrls, preferHostingUrls ? "true" : "false");
}
/// <summary> /// <summary>
/// Start the web host and listen on the specified urls. /// Start the web host and listen on the specified urls.
/// </summary> /// </summary>

View File

@ -15,5 +15,6 @@ namespace Microsoft.AspNetCore.Hosting
public static readonly string CaptureStartupErrorsKey = "captureStartupErrors"; public static readonly string CaptureStartupErrorsKey = "captureStartupErrors";
public static readonly string ServerUrlsKey = "urls"; public static readonly string ServerUrlsKey = "urls";
public static readonly string ContentRootKey = "contentRoot"; public static readonly string ContentRootKey = "contentRoot";
public static readonly string PreferHostingUrls = "preferHostingUrls";
} }
} }

View File

@ -8,5 +8,7 @@ namespace Microsoft.AspNetCore.Hosting.Server.Features
public interface IServerAddressesFeature public interface IServerAddressesFeature
{ {
ICollection<string> Addresses { get; } ICollection<string> Addresses { get; }
bool PreferHostingUrls { get; set; }
} }
} }

View File

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

View File

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

View File

@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
{ {
hostingEnvironment.WebRootFileProvider = new NullFileProvider(); hostingEnvironment.WebRootFileProvider = new NullFileProvider();
} }
hostingEnvironment.EnvironmentName = hostingEnvironment.EnvironmentName =
options.Environment ?? options.Environment ??
hostingEnvironment.EnvironmentName; hostingEnvironment.EnvironmentName;

View File

@ -249,12 +249,15 @@ namespace Microsoft.AspNetCore.Hosting.Internal
{ {
Server = _applicationServices.GetRequiredService<IServer>(); Server = _applicationServices.GetRequiredService<IServer>();
var addresses = Server.Features?.Get<IServerAddressesFeature>()?.Addresses; var serverAddressesFeature = Server.Features?.Get<IServerAddressesFeature>();
var addresses = serverAddressesFeature?.Addresses;
if (addresses != null && !addresses.IsReadOnly && addresses.Count == 0) if (addresses != null && !addresses.IsReadOnly && addresses.Count == 0)
{ {
var urls = _config[WebHostDefaults.ServerUrlsKey] ?? _config[DeprecatedServerUrlsKey]; var urls = _config[WebHostDefaults.ServerUrlsKey] ?? _config[DeprecatedServerUrlsKey];
if (!string.IsNullOrEmpty(urls)) if (!string.IsNullOrEmpty(urls))
{ {
serverAddressesFeature.PreferHostingUrls = _options.PreferHostingUrls;
foreach (var value in urls.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) foreach (var value in urls.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{ {
addresses.Add(value); addresses.Add(value);

View File

@ -9,9 +9,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
{ {
public class WebHostOptions public class WebHostOptions
{ {
public WebHostOptions() public WebHostOptions() { }
{
}
public WebHostOptions(IConfiguration configuration) public WebHostOptions(IConfiguration configuration)
{ {
@ -28,6 +26,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
WebRoot = configuration[WebHostDefaults.WebRootKey]; WebRoot = configuration[WebHostDefaults.WebRootKey];
ContentRootPath = configuration[WebHostDefaults.ContentRootKey]; ContentRootPath = configuration[WebHostDefaults.ContentRootKey];
HostingStartupAssemblies = configuration[WebHostDefaults.HostingStartupAssembliesKey]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0]; HostingStartupAssemblies = configuration[WebHostDefaults.HostingStartupAssembliesKey]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0];
PreferHostingUrls = ParseBool(configuration, WebHostDefaults.PreferHostingUrls);
} }
public string ApplicationName { get; set; } public string ApplicationName { get; set; }
@ -39,13 +38,15 @@ namespace Microsoft.AspNetCore.Hosting.Internal
public bool CaptureStartupErrors { get; set; } public bool CaptureStartupErrors { get; set; }
public string Environment { get; set; } public string Environment { get; set; }
public string StartupAssembly { get; set; } public string StartupAssembly { get; set; }
public string WebRoot { get; set; } public string WebRoot { get; set; }
public string ContentRootPath { get; set; } public string ContentRootPath { get; set; }
public bool PreferHostingUrls { get; set; }
private static bool ParseBool(IConfiguration configuration, string key) private static bool ParseBool(IConfiguration configuration, string key)
{ {
return string.Equals("true", configuration[key], StringComparison.OrdinalIgnoreCase) return string.Equals("true", configuration[key], StringComparison.OrdinalIgnoreCase)

View File

@ -8,5 +8,7 @@ namespace Microsoft.AspNetCore.Hosting.Server.Features
public class ServerAddressesFeature : IServerAddressesFeature public class ServerAddressesFeature : IServerAddressesFeature
{ {
public ICollection<string> Addresses { get; } = new List<string>(); public ICollection<string> Addresses { get; } = new List<string>();
public bool PreferHostingUrls { get; set; }
} }
} }

View File

@ -20,7 +20,8 @@ namespace Microsoft.AspNetCore.Hosting.Tests
{ "startupAssembly", "MyProjectReference" }, { "startupAssembly", "MyProjectReference" },
{ "environment", "Development"}, { "environment", "Development"},
{ "detailederrors", "true"}, { "detailederrors", "true"},
{ "captureStartupErrors", "true" } { "captureStartupErrors", "true" },
{ "preferHostingUrls", "true" }
}; };
var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build()); var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build());
@ -31,6 +32,7 @@ namespace Microsoft.AspNetCore.Hosting.Tests
Assert.Equal("Development", config.Environment); Assert.Equal("Development", config.Environment);
Assert.True(config.CaptureStartupErrors); Assert.True(config.CaptureStartupErrors);
Assert.True(config.DetailedErrors); Assert.True(config.DetailedErrors);
Assert.True(config.PreferHostingUrls);
} }
[Fact] [Fact]

View File

@ -67,15 +67,19 @@ namespace Microsoft.AspNetCore.Hosting
} }
[Fact] [Fact]
public void NoDefaultAddressesIfNotConfigured() public void NoDefaultAddressesAndDoNotPreferHostingUrlsIfNotConfigured()
{ {
var host = CreateBuilder().UseServer(this).Build(); using (var host = CreateBuilder().UseServer(this).Build())
host.Start(); {
Assert.Equal(false, host.ServerFeatures.Get<IServerAddressesFeature>().Addresses.Any()); host.Start();
var serverAddressesFeature = host.ServerFeatures.Get<IServerAddressesFeature>();
Assert.False(serverAddressesFeature.Addresses.Any());
Assert.False(serverAddressesFeature.PreferHostingUrls);
}
} }
[Fact] [Fact]
public void UsesLegacyConfigurationForAddresses() public void UsesLegacyConfigurationForAddressesAndDoNotPreferHostingUrlsIfNotConfigured()
{ {
var data = new Dictionary<string, string> var data = new Dictionary<string, string>
{ {
@ -84,13 +88,17 @@ namespace Microsoft.AspNetCore.Hosting
var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build(); var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build();
var host = CreateBuilder(config).UseServer(this).Build(); using (var host = CreateBuilder(config).UseServer(this).Build())
host.Start(); {
Assert.Equal("http://localhost:5002", host.ServerFeatures.Get<IServerAddressesFeature>().Addresses.First()); host.Start();
var serverAddressFeature = host.ServerFeatures.Get<IServerAddressesFeature>();
Assert.Equal("http://localhost:5002", serverAddressFeature.Addresses.First());
Assert.False(serverAddressFeature.PreferHostingUrls);
}
} }
[Fact] [Fact]
public void UsesConfigurationForAddresses() public void UsesConfigurationForAddressesAndDoNotPreferHostingUrlsIfNotConfigured()
{ {
var data = new Dictionary<string, string> var data = new Dictionary<string, string>
{ {
@ -99,13 +107,17 @@ namespace Microsoft.AspNetCore.Hosting
var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build(); var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build();
var host = CreateBuilder(config).UseServer(this).Build(); using (var host = CreateBuilder(config).UseServer(this).Build())
host.Start(); {
Assert.Equal("http://localhost:5003", host.ServerFeatures.Get<IServerAddressesFeature>().Addresses.First()); host.Start();
var serverAddressFeature = host.ServerFeatures.Get<IServerAddressesFeature>();
Assert.Equal("http://localhost:5003", serverAddressFeature.Addresses.First());
Assert.False(serverAddressFeature.PreferHostingUrls);
}
} }
[Fact] [Fact]
public void UsesNewConfigurationOverLegacyConfigForAddresses() public void UsesNewConfigurationOverLegacyConfigForAddressesAndDoNotPreferHostingUrlsIfNotConfigured()
{ {
var data = new Dictionary<string, string> var data = new Dictionary<string, string>
{ {
@ -115,121 +127,157 @@ namespace Microsoft.AspNetCore.Hosting
var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build(); var config = new ConfigurationBuilder().AddInMemoryCollection(data).Build();
var host = CreateBuilder(config).UseServer(this).Build(); using (var host = CreateBuilder(config).UseServer(this).Build())
host.Start(); {
Assert.Equal("http://localhost:5009", host.ServerFeatures.Get<IServerAddressesFeature>().Addresses.First()); host.Start();
var serverAddressFeature = host.ServerFeatures.Get<IServerAddressesFeature>();
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<IServerAddressesFeature>();
Assert.Empty(serverAddressesFeature.Addresses);
Assert.False(serverAddressesFeature.PreferHostingUrls);
}
}
[Fact]
public void PreferHostingUrlsWhenAddressIsConfigured()
{
var data = new Dictionary<string, string>
{
{ "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<IServerAddressesFeature>().PreferHostingUrls);
}
} }
[Fact] [Fact]
public void WebHostCanBeStarted() public void WebHostCanBeStarted()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.UseStartup("Microsoft.AspNetCore.Hosting.Tests") .UseStartup("Microsoft.AspNetCore.Hosting.Tests")
.Start(); .Start())
{
Assert.NotNull(host);
Assert.Equal(1, _startInstances.Count);
Assert.Equal(0, _startInstances[0].DisposeCalls);
Assert.NotNull(host); host.Dispose();
Assert.Equal(1, _startInstances.Count);
Assert.Equal(0, _startInstances[0].DisposeCalls);
host.Dispose(); Assert.Equal(0, _startInstances[0].DisposeCalls);
}
Assert.Equal(0, _startInstances[0].DisposeCalls);
} }
[Fact] [Fact]
public void WebHostShutsDownWhenTokenTriggers() public void WebHostShutsDownWhenTokenTriggers()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.UseStartup("Microsoft.AspNetCore.Hosting.Tests") .UseStartup("Microsoft.AspNetCore.Hosting.Tests")
.Build(); .Build())
{
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>(); 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 Assert.Equal(1, _startInstances.Count);
lifetime.ApplicationStarted.WaitHandle.WaitOne(); Assert.Equal(0, _startInstances[0].DisposeCalls);
Assert.Equal(1, _startInstances.Count); cts.Cancel();
Assert.Equal(0, _startInstances[0].DisposeCalls);
cts.Cancel(); // Wait on the host to shutdown
lifetime.ApplicationStopped.WaitHandle.WaitOne();
// Wait on the host to shutdown Assert.Equal(0, _startInstances[0].DisposeCalls);
lifetime.ApplicationStopped.WaitHandle.WaitOne(); }
Assert.Equal(0, _startInstances[0].DisposeCalls);
} }
[Fact] [Fact]
public void WebHostApplicationLifetimeEventsOrderedCorrectlyDuringShutdown() public void WebHostApplicationLifetimeEventsOrderedCorrectlyDuringShutdown()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.UseStartup("Microsoft.AspNetCore.Hosting.Tests") .UseStartup("Microsoft.AspNetCore.Hosting.Tests")
.Build(); .Build())
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
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(() =>
{ {
applicationStartedEvent.Set(); var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
}); 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(() => lifetime.ApplicationStarted.Register(() =>
{ {
// Check whether the applicationStartedEvent has been set applicationStartedEvent.Set();
applicationStartedCompletedBeforeApplicationStopping = applicationStartedEvent.IsSet; });
// Simulate work. lifetime.ApplicationStopping.Register(() =>
Thread.Sleep(1000); {
// Check whether the applicationStartedEvent has been set
applicationStartedCompletedBeforeApplicationStopping = applicationStartedEvent.IsSet;
applicationStoppingEvent.Set(); // Simulate work.
}); Thread.Sleep(1000);
lifetime.ApplicationStopped.Register(() => applicationStoppingEvent.Set();
{ });
// Check whether the applicationStoppingEvent has been set
applicationStoppingCompletedBeforeApplicationStopped = applicationStoppingEvent.IsSet;
applicationStoppedEvent.Set();
});
var runHostAndVerifyApplicationStopped = Task.Run(() => lifetime.ApplicationStopped.Register(() =>
{ {
host.Run(); // Check whether the applicationStoppingEvent has been set
// Check whether the applicationStoppingEvent has been set applicationStoppingCompletedBeforeApplicationStopped = applicationStoppingEvent.IsSet;
applicationStoppedCompletedBeforeRunCompleted = applicationStoppedEvent.IsSet; applicationStoppedEvent.Set();
}); });
// Wait until application has started to shut down the host var runHostAndVerifyApplicationStopped = Task.Run(() =>
Assert.True(applicationStartedEvent.Wait(5000)); {
host.Run();
// Check whether the applicationStoppingEvent has been set
applicationStoppedCompletedBeforeRunCompleted = applicationStoppedEvent.IsSet;
});
// Trigger host shutdown on a separate thread // Wait until application has started to shut down the host
Task.Run(() => lifetime.StopApplication()); Assert.True(applicationStartedEvent.Wait(5000));
// Wait for all events and host.Run() to complete // Trigger host shutdown on a separate thread
Assert.True(runHostAndVerifyApplicationStopped.Wait(5000)); Task.Run(() => lifetime.StopApplication());
// Verify Ordering // Wait for all events and host.Run() to complete
Assert.True(applicationStartedCompletedBeforeApplicationStopping); Assert.True(runHostAndVerifyApplicationStopped.Wait(5000));
Assert.True(applicationStoppingCompletedBeforeApplicationStopped);
Assert.True(applicationStoppedCompletedBeforeRunCompleted); // Verify Ordering
Assert.True(applicationStartedCompletedBeforeApplicationStopping);
Assert.True(applicationStoppingCompletedBeforeApplicationStopped);
Assert.True(applicationStoppedCompletedBeforeRunCompleted);
}
} }
[Fact] [Fact]
public void WebHostDisposesServiceProvider() public void WebHostDisposesServiceProvider()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.ConfigureServices(s => .ConfigureServices(s =>
{ {
@ -237,33 +285,34 @@ namespace Microsoft.AspNetCore.Hosting
s.AddSingleton<IFakeSingletonService, FakeService>(); s.AddSingleton<IFakeSingletonService, FakeService>();
}) })
.UseStartup("Microsoft.AspNetCore.Hosting.Tests") .UseStartup("Microsoft.AspNetCore.Hosting.Tests")
.Build(); .Build())
{
host.Start();
host.Start(); var singleton = (FakeService)host.Services.GetService<IFakeSingletonService>();
var transient = (FakeService)host.Services.GetService<IFakeService>();
var singleton = (FakeService)host.Services.GetService<IFakeSingletonService>(); Assert.False(singleton.Disposed);
var transient = (FakeService)host.Services.GetService<IFakeService>(); Assert.False(transient.Disposed);
Assert.False(singleton.Disposed); host.Dispose();
Assert.False(transient.Disposed);
host.Dispose(); Assert.True(singleton.Disposed);
Assert.True(transient.Disposed);
Assert.True(singleton.Disposed); }
Assert.True(transient.Disposed);
} }
[Fact] [Fact]
public void WebHostNotifiesApplicationStarted() public void WebHostNotifiesApplicationStarted()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.Build(); .Build())
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
Assert.False(applicationLifetime.ApplicationStarted.IsCancellationRequested);
using (host)
{ {
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
Assert.False(applicationLifetime.ApplicationStarted.IsCancellationRequested);
host.Start(); host.Start();
Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested); Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested);
} }
@ -272,17 +321,16 @@ namespace Microsoft.AspNetCore.Hosting
[Fact] [Fact]
public void WebHostNotifiesAllIApplicationLifetimeCallbacksEvenIfTheyThrow() public void WebHostNotifiesAllIApplicationLifetimeCallbacksEvenIfTheyThrow()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.Build(); .Build())
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted);
var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping);
var stopped = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopped);
using (host)
{ {
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted);
var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping);
var stopped = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopped);
host.Start(); host.Start();
Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested); Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested);
Assert.True(started.All(s => s)); Assert.True(started.All(s => s));
@ -298,16 +346,14 @@ namespace Microsoft.AspNetCore.Hosting
bool[] events1 = null; bool[] events1 = null;
bool[] events2 = null; bool[] events2 = null;
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.ConfigureServices(services => .ConfigureServices(services =>
{ {
events1 = RegisterCallbacksThatThrow(services); events1 = RegisterCallbacksThatThrow(services);
events2 = RegisterCallbacksThatThrow(services); events2 = RegisterCallbacksThatThrow(services);
}) })
.Build(); .Build())
using (host)
{ {
host.Start(); host.Start();
Assert.True(events1[0]); Assert.True(events1[0]);
@ -323,7 +369,7 @@ namespace Microsoft.AspNetCore.Hosting
{ {
var stoppingCalls = 0; var stoppingCalls = 0;
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.ConfigureServices(services => .ConfigureServices(services =>
{ {
@ -338,12 +384,11 @@ namespace Microsoft.AspNetCore.Hosting
services.AddSingleton<IHostedService>(new DelegateHostedService(started, stopping)); services.AddSingleton<IHostedService>(new DelegateHostedService(started, stopping));
}) })
.Build(); .Build())
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
lifetime.StopApplication();
using (host)
{ {
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
lifetime.StopApplication();
host.Start(); host.Start();
Assert.Equal(0, stoppingCalls); Assert.Equal(0, stoppingCalls);
@ -353,40 +398,44 @@ namespace Microsoft.AspNetCore.Hosting
[Fact] [Fact]
public void HostedServiceCanInjectApplicationLifetime() public void HostedServiceCanInjectApplicationLifetime()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.ConfigureServices(services => .ConfigureServices(services =>
{ {
services.AddSingleton<IHostedService, TestHostedService>(); services.AddSingleton<IHostedService, TestHostedService>();
}) })
.Build(); .Build())
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>(); {
lifetime.StopApplication(); var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
lifetime.StopApplication();
host.Start(); host.Start();
var svc = (TestHostedService)host.Services.GetRequiredService<IHostedService>(); var svc = (TestHostedService)host.Services.GetRequiredService<IHostedService>();
Assert.True(svc.StartCalled); Assert.True(svc.StartCalled);
host.Dispose(); host.Dispose();
Assert.True(svc.StopCalled); Assert.True(svc.StopCalled);
}
} }
[Fact] [Fact]
public void HostedServiceStartNotCalledIfWebHostNotStarted() public void HostedServiceStartNotCalledIfWebHostNotStarted()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.ConfigureServices(services => .ConfigureServices(services =>
{ {
services.AddSingleton<IHostedService, TestHostedService>(); services.AddSingleton<IHostedService, TestHostedService>();
}) })
.Build(); .Build())
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>(); {
lifetime.StopApplication(); var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
lifetime.StopApplication();
var svc = (TestHostedService)host.Services.GetRequiredService<IHostedService>(); var svc = (TestHostedService)host.Services.GetRequiredService<IHostedService>();
Assert.False(svc.StartCalled); Assert.False(svc.StartCalled);
host.Dispose(); host.Dispose();
Assert.False(svc.StopCalled); Assert.False(svc.StopCalled);
}
} }
[Fact] [Fact]
@ -395,7 +444,7 @@ namespace Microsoft.AspNetCore.Hosting
var stoppingCalls = 0; var stoppingCalls = 0;
var startedCalls = 0; var startedCalls = 0;
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.ConfigureServices(services => .ConfigureServices(services =>
{ {
@ -411,10 +460,10 @@ namespace Microsoft.AspNetCore.Hosting
services.AddSingleton<IHostedService>(new DelegateHostedService(started, stopping)); services.AddSingleton<IHostedService>(new DelegateHostedService(started, stopping));
}) })
.Build(); .Build())
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
using (host)
{ {
var lifetime = host.Services.GetRequiredService<IApplicationLifetime>();
host.Start(); host.Start();
host.Dispose(); host.Dispose();
@ -429,21 +478,20 @@ namespace Microsoft.AspNetCore.Hosting
bool[] events1 = null; bool[] events1 = null;
bool[] events2 = null; bool[] events2 = null;
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.ConfigureServices(services => .ConfigureServices(services =>
{ {
events1 = RegisterCallbacksThatThrow(services); events1 = RegisterCallbacksThatThrow(services);
events2 = RegisterCallbacksThatThrow(services); events2 = RegisterCallbacksThatThrow(services);
}) })
.Build(); .Build())
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted);
var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping);
using (host)
{ {
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted);
var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping);
host.Start(); host.Start();
Assert.True(events1[0]); Assert.True(events1[0]);
Assert.True(events2[0]); Assert.True(events2[0]);
@ -458,13 +506,11 @@ namespace Microsoft.AspNetCore.Hosting
[Fact] [Fact]
public void WebHostInjectsHostingEnvironment() public void WebHostInjectsHostingEnvironment()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.UseStartup("Microsoft.AspNetCore.Hosting.Tests") .UseStartup("Microsoft.AspNetCore.Hosting.Tests")
.UseEnvironment("WithHostingEnvironment") .UseEnvironment("WithHostingEnvironment")
.Build(); .Build())
using (host)
{ {
host.Start(); host.Start();
var env = host.Services.GetService<IHostingEnvironment>(); var env = host.Services.GetService<IHostingEnvironment>();
@ -489,8 +535,10 @@ namespace Microsoft.AspNetCore.Hosting
[Fact] [Fact]
public void CanCreateApplicationServicesWithAddedServices() public void CanCreateApplicationServicesWithAddedServices()
{ {
var host = CreateBuilder().UseServer(this).ConfigureServices(services => services.AddOptions()).Build(); using (var host = CreateBuilder().UseServer(this).ConfigureServices(services => services.AddOptions()).Build())
Assert.NotNull(host.Services.GetRequiredService<IOptions<object>>()); {
Assert.NotNull(host.Services.GetRequiredService<IOptions<object>>());
}
} }
[Fact] [Fact]
@ -498,7 +546,7 @@ namespace Microsoft.AspNetCore.Hosting
{ {
// Verify ordering // Verify ordering
var configureOrder = 0; var configureOrder = 0;
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.ConfigureServices(services => .ConfigureServices(services =>
{ {
@ -511,8 +559,10 @@ namespace Microsoft.AspNetCore.Hosting
() => Assert.Equal(3, configureOrder++), () => Assert.Equal(3, configureOrder++),
() => Assert.Equal(4, configureOrder++))); () => Assert.Equal(4, configureOrder++)));
}) })
.Build(); .Build())
Assert.Equal(6, configureOrder); {
Assert.Equal(6, configureOrder);
}
} }
private class TestFilter : IStartupFilter private class TestFilter : IStartupFilter
@ -543,9 +593,11 @@ namespace Microsoft.AspNetCore.Hosting
[Fact] [Fact]
public void EnvDefaultsToProductionIfNoConfig() public void EnvDefaultsToProductionIfNoConfig()
{ {
var host = CreateBuilder().UseServer(this).Build(); using (var host = CreateBuilder().UseServer(this).Build())
var env = host.Services.GetService<IHostingEnvironment>(); {
Assert.Equal(EnvironmentName.Production, env.EnvironmentName); var env = host.Services.GetService<IHostingEnvironment>();
Assert.Equal(EnvironmentName.Production, env.EnvironmentName);
}
} }
[Fact] [Fact]
@ -560,9 +612,11 @@ namespace Microsoft.AspNetCore.Hosting
.AddInMemoryCollection(vals); .AddInMemoryCollection(vals);
var config = builder.Build(); var config = builder.Build();
var host = CreateBuilder(config).UseServer(this).Build(); using (var host = CreateBuilder(config).UseServer(this).Build())
var env = host.Services.GetService<IHostingEnvironment>(); {
Assert.Equal("Staging", env.EnvironmentName); var env = host.Services.GetService<IHostingEnvironment>();
Assert.Equal("Staging", env.EnvironmentName);
}
} }
[Fact(Skip = "Missing content publish property")] [Fact(Skip = "Missing content publish property")]
@ -577,17 +631,18 @@ namespace Microsoft.AspNetCore.Hosting
.AddInMemoryCollection(vals); .AddInMemoryCollection(vals);
var config = builder.Build(); var config = builder.Build();
var host = CreateBuilder(config).UseServer(this).Build(); using (var host = CreateBuilder(config).UseServer(this).Build())
var env = host.Services.GetService<IHostingEnvironment>(); {
Assert.Equal(Path.GetFullPath("testroot"), env.WebRootPath); var env = host.Services.GetService<IHostingEnvironment>();
Assert.True(env.WebRootFileProvider.GetFileInfo("TextFile.txt").Exists); Assert.Equal(Path.GetFullPath("testroot"), env.WebRootPath);
Assert.True(env.WebRootFileProvider.GetFileInfo("TextFile.txt").Exists);
}
} }
[Fact] [Fact]
public void IsEnvironment_Extension_Is_Case_Insensitive() public void IsEnvironment_Extension_Is_Case_Insensitive()
{ {
var host = CreateBuilder().UseServer(this).Build(); using (var host = CreateBuilder().UseServer(this).Build())
using (host)
{ {
host.Start(); host.Start();
var env = host.Services.GetRequiredService<IHostingEnvironment>(); var env = host.Services.GetRequiredService<IHostingEnvironment>();
@ -606,16 +661,18 @@ namespace Microsoft.AspNetCore.Hosting
httpContext = innerHttpContext; httpContext = innerHttpContext;
return Task.FromResult(0); return Task.FromResult(0);
}); });
var host = CreateHost(requestDelegate);
// Act using (var host = CreateHost(requestDelegate))
host.Start(); {
// Act
host.Start();
// Assert // Assert
Assert.NotNull(httpContext); Assert.NotNull(httpContext);
var featuresTraceIdentifier = httpContext.Features.Get<IHttpRequestIdentifierFeature>().TraceIdentifier; var featuresTraceIdentifier = httpContext.Features.Get<IHttpRequestIdentifierFeature>().TraceIdentifier;
Assert.False(string.IsNullOrWhiteSpace(httpContext.TraceIdentifier)); Assert.False(string.IsNullOrWhiteSpace(httpContext.TraceIdentifier));
Assert.Same(httpContext.TraceIdentifier, featuresTraceIdentifier); Assert.Same(httpContext.TraceIdentifier, featuresTraceIdentifier);
}
} }
[Fact] [Fact]
@ -630,24 +687,25 @@ namespace Microsoft.AspNetCore.Hosting
}); });
var requestIdentifierFeature = new StubHttpRequestIdentifierFeature(); var requestIdentifierFeature = new StubHttpRequestIdentifierFeature();
_featuresSupportedByThisHost[typeof(IHttpRequestIdentifierFeature)] = requestIdentifierFeature; _featuresSupportedByThisHost[typeof(IHttpRequestIdentifierFeature)] = requestIdentifierFeature;
var host = CreateHost(requestDelegate);
// Act using (var host = CreateHost(requestDelegate))
host.Start(); {
// Act
host.Start();
// Assert // Assert
Assert.NotNull(httpContext); Assert.NotNull(httpContext);
Assert.Same(requestIdentifierFeature, httpContext.Features.Get<IHttpRequestIdentifierFeature>()); Assert.Same(requestIdentifierFeature, httpContext.Features.Get<IHttpRequestIdentifierFeature>());
}
} }
[Fact] [Fact]
public void WebHost_InvokesConfigureMethodsOnlyOnce() public void WebHost_InvokesConfigureMethodsOnlyOnce()
{ {
var host = CreateBuilder() using (var host = CreateBuilder()
.UseServer(this) .UseServer(this)
.UseStartup<CountStartup>() .UseStartup<CountStartup>()
.Build(); .Build())
using (host)
{ {
host.Start(); host.Start();
var services = host.Services; var services = host.Services;