Hosting 295 B

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. commit cd3f58bed7234ed5035a995c8688dccd6706b584
  2. Author: Chris Ross (ASP.NET) <[email protected]>
  3. Date: Fri Nov 10 16:18:51 2017 -0800
  4. #1263 Delay IServer and Startup.Configure until StartAsync
  5. diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs b/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs
  6. index 203cea8137b..3764427f63e 100644
  7. --- a/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs
  8. +++ b/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs
  9. @@ -6,6 +6,7 @@ using System.Collections.Generic;
  10. using System.Diagnostics;
  11. using System.Linq;
  12. using System.Reflection;
  13. +using System.Runtime.ExceptionServices;
  14. using System.Runtime.InteropServices;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. @@ -38,7 +39,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
  18. private readonly AggregateException _hostingStartupErrors;
  19. private IServiceProvider _applicationServices;
  20. - private RequestDelegate _application;
  21. + private ExceptionDispatchInfo _applicationServicesException;
  22. private ILogger<WebHost> _logger;
  23. private bool _stopped;
  24. @@ -88,7 +89,6 @@ namespace Microsoft.AspNetCore.Hosting.Internal
  25. {
  26. get
  27. {
  28. - EnsureApplicationServices();
  29. return _applicationServices;
  30. }
  31. }
  32. @@ -97,15 +97,32 @@ namespace Microsoft.AspNetCore.Hosting.Internal
  33. {
  34. get
  35. {
  36. + EnsureServer();
  37. return Server?.Features;
  38. }
  39. }
  40. + // Called immediately after the constructor so the properties can rely on it.
  41. public void Initialize()
  42. {
  43. - if (_application == null)
  44. + try
  45. {
  46. - _application = BuildApplication();
  47. + EnsureApplicationServices();
  48. + }
  49. + catch (Exception ex)
  50. + {
  51. + // EnsureApplicationServices may have failed due to a missing or throwing Startup class.
  52. + if (_applicationServices == null)
  53. + {
  54. + _applicationServices = _applicationServiceCollection.BuildServiceProvider();
  55. + }
  56. +
  57. + if (!_options.CaptureStartupErrors)
  58. + {
  59. + throw;
  60. + }
  61. +
  62. + _applicationServicesException = ExceptionDispatchInfo.Capture(ex);
  63. }
  64. }
  65. @@ -120,13 +137,13 @@ namespace Microsoft.AspNetCore.Hosting.Internal
  66. _logger = _applicationServices.GetRequiredService<ILogger<WebHost>>();
  67. _logger.Starting();
  68. - Initialize();
  69. + var application = BuildApplication();
  70. _applicationLifetime = _applicationServices.GetRequiredService<IApplicationLifetime>() as ApplicationLifetime;
  71. _hostedServiceExecutor = _applicationServices.GetRequiredService<HostedServiceExecutor>();
  72. var diagnosticSource = _applicationServices.GetRequiredService<DiagnosticListener>();
  73. var httpContextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();
  74. - var hostingApp = new HostingApplication(_application, _logger, diagnosticSource, httpContextFactory);
  75. + var hostingApp = new HostingApplication(application, _logger, diagnosticSource, httpContextFactory);
  76. await Server.StartAsync(hostingApp, cancellationToken).ConfigureAwait(false);
  77. // Fire IApplicationLifetime.Started
  78. @@ -183,7 +200,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
  79. {
  80. try
  81. {
  82. - EnsureApplicationServices();
  83. + _applicationServicesException?.Throw();
  84. EnsureServer();
  85. var builderFactory = _applicationServices.GetRequiredService<IApplicationBuilderFactory>();
  86. @@ -203,12 +220,6 @@ namespace Microsoft.AspNetCore.Hosting.Internal
  87. }
  88. catch (Exception ex)
  89. {
  90. - // EnsureApplicationServices may have failed due to a missing or throwing Startup class.
  91. - if (_applicationServices == null)
  92. - {
  93. - _applicationServices = _applicationServiceCollection.BuildServiceProvider();
  94. - }
  95. -
  96. if (!_options.SuppressStatusMessages)
  97. {
  98. // Write errors to standard out so they can be retrieved when not in development mode.
  99. diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs
  100. index a7c358141fb..a5765a52b22 100644
  101. --- a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs
  102. +++ b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs
  103. @@ -182,7 +182,7 @@ namespace Microsoft.AspNetCore.Hosting
  104. options.ValidateScopes = true;
  105. });
  106. - Assert.Throws<InvalidOperationException>(() => hostBuilder.Build());
  107. + Assert.Throws<InvalidOperationException>(() => hostBuilder.Build().Start());
  108. }
  109. [Fact]
  110. @@ -208,7 +208,7 @@ namespace Microsoft.AspNetCore.Hosting
  111. options.ValidateScopes = true;
  112. });
  113. - Assert.Throws<InvalidOperationException>(() => hostBuilder.Build());
  114. + Assert.Throws<InvalidOperationException>(() => hostBuilder.Build().Start());
  115. Assert.True(configurationCallbackCalled);
  116. }
  117. @@ -784,8 +784,9 @@ namespace Microsoft.AspNetCore.Hosting
  118. })
  119. .UseServer(new TestServer());
  120. - using (builder.Build())
  121. + using (var host = builder.Build())
  122. {
  123. + host.Start();
  124. Assert.NotNull(startup.ServiceADescriptor);
  125. Assert.NotNull(startup.ServiceA);
  126. }
  127. @@ -823,6 +824,7 @@ namespace Microsoft.AspNetCore.Hosting
  128. using (var host = (WebHost)builder.Build())
  129. {
  130. + host.Start();
  131. var sink = host.Services.GetRequiredService<ITestSink>();
  132. Assert.Contains(sink.Writes, w => w.State.ToString() == "From startup");
  133. }
  134. @@ -920,6 +922,7 @@ namespace Microsoft.AspNetCore.Hosting
  135. using (var host = (WebHost)builder.Build())
  136. {
  137. + host.Start();
  138. var sink = host.Services.GetRequiredService<ITestSink>();
  139. Assert.Contains(sink.Writes, w => w.Exception?.Message == "Startup exception");
  140. }
  141. @@ -940,7 +943,7 @@ namespace Microsoft.AspNetCore.Hosting
  142. })
  143. .UseServer(new TestServer());
  144. - Assert.Throws<InvalidOperationException>(() => builder.Build());
  145. + Assert.Throws<InvalidOperationException>(() => builder.Build().Start());
  146. Assert.NotNull(testSink);
  147. Assert.Contains(testSink.Writes, w => w.Exception?.Message == "Startup exception");
  148. diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs
  149. index 70d12561d3d..81b6dcffbe5 100644
  150. --- a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs
  151. +++ b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs
  152. @@ -759,6 +759,7 @@ namespace Microsoft.AspNetCore.Hosting
  153. })
  154. .Build())
  155. {
  156. + host.Start();
  157. Assert.Equal(6, configureOrder);
  158. }
  159. }