Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit cd3f58b

Browse files
committed
#1263 Delay IServer and Startup.Configure until StartAsync
1 parent adf2f37 commit cd3f58b

File tree

3 files changed

+32
-17
lines changed

3 files changed

+32
-17
lines changed

src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics;
77
using System.Linq;
88
using System.Reflection;
9+
using System.Runtime.ExceptionServices;
910
using System.Runtime.InteropServices;
1011
using System.Threading;
1112
using System.Threading.Tasks;
@@ -38,7 +39,7 @@ internal class WebHost : IWebHost
3839
private readonly AggregateException _hostingStartupErrors;
3940

4041
private IServiceProvider _applicationServices;
41-
private RequestDelegate _application;
42+
private ExceptionDispatchInfo _applicationServicesException;
4243
private ILogger<WebHost> _logger;
4344

4445
private bool _stopped;
@@ -88,7 +89,6 @@ public IServiceProvider Services
8889
{
8990
get
9091
{
91-
EnsureApplicationServices();
9292
return _applicationServices;
9393
}
9494
}
@@ -97,15 +97,32 @@ public IFeatureCollection ServerFeatures
9797
{
9898
get
9999
{
100+
EnsureServer();
100101
return Server?.Features;
101102
}
102103
}
103104

105+
// Called immediately after the constructor so the properties can rely on it.
104106
public void Initialize()
105107
{
106-
if (_application == null)
108+
try
107109
{
108-
_application = BuildApplication();
110+
EnsureApplicationServices();
111+
}
112+
catch (Exception ex)
113+
{
114+
// EnsureApplicationServices may have failed due to a missing or throwing Startup class.
115+
if (_applicationServices == null)
116+
{
117+
_applicationServices = _applicationServiceCollection.BuildServiceProvider();
118+
}
119+
120+
if (!_options.CaptureStartupErrors)
121+
{
122+
throw;
123+
}
124+
125+
_applicationServicesException = ExceptionDispatchInfo.Capture(ex);
109126
}
110127
}
111128

@@ -120,13 +137,13 @@ public virtual async Task StartAsync(CancellationToken cancellationToken = defau
120137
_logger = _applicationServices.GetRequiredService<ILogger<WebHost>>();
121138
_logger.Starting();
122139

123-
Initialize();
140+
var application = BuildApplication();
124141

125142
_applicationLifetime = _applicationServices.GetRequiredService<IApplicationLifetime>() as ApplicationLifetime;
126143
_hostedServiceExecutor = _applicationServices.GetRequiredService<HostedServiceExecutor>();
127144
var diagnosticSource = _applicationServices.GetRequiredService<DiagnosticListener>();
128145
var httpContextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();
129-
var hostingApp = new HostingApplication(_application, _logger, diagnosticSource, httpContextFactory);
146+
var hostingApp = new HostingApplication(application, _logger, diagnosticSource, httpContextFactory);
130147
await Server.StartAsync(hostingApp, cancellationToken).ConfigureAwait(false);
131148

132149
// Fire IApplicationLifetime.Started
@@ -183,7 +200,7 @@ private RequestDelegate BuildApplication()
183200
{
184201
try
185202
{
186-
EnsureApplicationServices();
203+
_applicationServicesException?.Throw();
187204
EnsureServer();
188205

189206
var builderFactory = _applicationServices.GetRequiredService<IApplicationBuilderFactory>();
@@ -203,12 +220,6 @@ private RequestDelegate BuildApplication()
203220
}
204221
catch (Exception ex)
205222
{
206-
// EnsureApplicationServices may have failed due to a missing or throwing Startup class.
207-
if (_applicationServices == null)
208-
{
209-
_applicationServices = _applicationServiceCollection.BuildServiceProvider();
210-
}
211-
212223
if (!_options.SuppressStatusMessages)
213224
{
214225
// Write errors to standard out so they can be retrieved when not in development mode.

test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public void ConfigureDefaultServiceProvider()
182182
options.ValidateScopes = true;
183183
});
184184

185-
Assert.Throws<InvalidOperationException>(() => hostBuilder.Build());
185+
Assert.Throws<InvalidOperationException>(() => hostBuilder.Build().Start());
186186
}
187187

188188
[Fact]
@@ -208,7 +208,7 @@ public void ConfigureDefaultServiceProviderWithContext()
208208
options.ValidateScopes = true;
209209
});
210210

211-
Assert.Throws<InvalidOperationException>(() => hostBuilder.Build());
211+
Assert.Throws<InvalidOperationException>(() => hostBuilder.Build().Start());
212212
Assert.True(configurationCallbackCalled);
213213
}
214214

@@ -784,8 +784,9 @@ public void Build_RunsHostingStartupAssembliesBeforeApplication()
784784
})
785785
.UseServer(new TestServer());
786786

787-
using (builder.Build())
787+
using (var host = builder.Build())
788788
{
789+
host.Start();
789790
Assert.NotNull(startup.ServiceADescriptor);
790791
Assert.NotNull(startup.ServiceA);
791792
}
@@ -823,6 +824,7 @@ public void Build_ConfigureLoggingInHostingStartupWorks()
823824

824825
using (var host = (WebHost)builder.Build())
825826
{
827+
host.Start();
826828
var sink = host.Services.GetRequiredService<ITestSink>();
827829
Assert.Contains(sink.Writes, w => w.State.ToString() == "From startup");
828830
}
@@ -920,6 +922,7 @@ public void StartupErrorsAreLoggedIfCaptureStartupErrorsIsTrue()
920922

921923
using (var host = (WebHost)builder.Build())
922924
{
925+
host.Start();
923926
var sink = host.Services.GetRequiredService<ITestSink>();
924927
Assert.Contains(sink.Writes, w => w.Exception?.Message == "Startup exception");
925928
}
@@ -940,7 +943,7 @@ public void StartupErrorsAreLoggedIfCaptureStartupErrorsIsFalse()
940943
})
941944
.UseServer(new TestServer());
942945

943-
Assert.Throws<InvalidOperationException>(() => builder.Build());
946+
Assert.Throws<InvalidOperationException>(() => builder.Build().Start());
944947

945948
Assert.NotNull(testSink);
946949
Assert.Contains(testSink.Writes, w => w.Exception?.Message == "Startup exception");

test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,7 @@ public void ConfiguresStartupFiltersInCorrectOrder()
759759
})
760760
.Build())
761761
{
762+
host.Start();
762763
Assert.Equal(6, configureOrder);
763764
}
764765
}

0 commit comments

Comments
 (0)