Microsoft.AspNetCore.Hosting.Internal
命名空间
WebHost.cs源码
using System;
using System. Collections. Generic;
using System. Diagnostics;
using System. Linq;
using System. Reflection;
using System. Runtime. ExceptionServices;
using System. Runtime. InteropServices;
using System. Threading;
using System. Threading. Tasks;
using Microsoft. AspNetCore. Builder;
using Microsoft. AspNetCore. Hosting. Builder;
using Microsoft. AspNetCore. Hosting. Server;
using Microsoft. AspNetCore. Hosting. Server. Features;
using Microsoft. AspNetCore. Hosting. Views;
using Microsoft. AspNetCore. Http;
using Microsoft. AspNetCore. Http. Features;
using Microsoft. Extensions. Configuration;
using Microsoft. Extensions. DependencyInjection;
using Microsoft. Extensions. Logging;
using Microsoft. Extensions. StackTrace. Sources;
namespace Microsoft. AspNetCore. Hosting. Internal
{
internal class WebHost : IWebHost , IAsyncDisposable
{
private static readonly string DeprecatedServerUrlsKey = "server.urls" ;
private readonly IServiceCollection _applicationServiceCollection;
private IStartup _startup;
private ApplicationLifetime _applicationLifetime;
private HostedServiceExecutor _hostedServiceExecutor;
private readonly IServiceProvider _hostingServiceProvider;
private readonly WebHostOptions _options;
private readonly IConfiguration _config;
private readonly AggregateException _hostingStartupErrors;
private IServiceProvider _applicationServices;
private ExceptionDispatchInfo _applicationServicesException;
private ILogger< WebHost> _logger;
private bool _stopped;
internal WebHostOptions Options = > _options;
private IServer Server { get ; set ; }
public WebHost (
IServiceCollection appServices,
IServiceProvider hostingServiceProvider,
WebHostOptions options,
IConfiguration config,
AggregateException hostingStartupErrors)
{
if ( appServices == null )
{
throw new ArgumentNullException ( nameof ( appServices) ) ;
}
if ( hostingServiceProvider == null )
{
throw new ArgumentNullException ( nameof ( hostingServiceProvider) ) ;
}
if ( config == null )
{
throw new ArgumentNullException ( nameof ( config) ) ;
}
_config = config;
_hostingStartupErrors = hostingStartupErrors;
_options = options;
_applicationServiceCollection = appServices;
_hostingServiceProvider = hostingServiceProvider;
_applicationServiceCollection. AddSingleton < IApplicationLifetime , ApplicationLifetime > ( ) ;
_applicationServiceCollection. AddSingleton ( sp = >
{
return sp. GetRequiredService < IApplicationLifetime > ( ) as Extensions. Hosting. IApplicationLifetime;
} ) ;
_applicationServiceCollection. AddSingleton < HostedServiceExecutor > ( ) ;
}
public IServiceProvider Services
{
get
{
return _applicationServices;
}
}
public IFeatureCollection ServerFeatures
{
get
{
EnsureServer ( ) ;
return Server? . Features;
}
}
public void Initialize ( )
{
try
{
EnsureApplicationServices ( ) ;
}
catch ( Exception ex)
{
if ( _applicationServices == null )
{
_applicationServices = _applicationServiceCollection. BuildServiceProvider ( ) ;
}
if ( ! _options. CaptureStartupErrors)
{
throw ;
}
_applicationServicesException = ExceptionDispatchInfo. Capture ( ex) ;
}
}
public void Start ( )
{
StartAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
}
public virtual async Task StartAsync ( CancellationToken cancellationToken = default )
{
HostingEventSource. Log. HostStart ( ) ;
_logger = _applicationServices. GetRequiredService< ILogger< WebHost> > ( ) ;
_logger. Starting ( ) ;
var application = BuildApplication ( ) ;
_applicationLifetime = _applicationServices. GetRequiredService < IApplicationLifetime > ( ) as ApplicationLifetime;
_hostedServiceExecutor = _applicationServices. GetRequiredService < HostedServiceExecutor > ( ) ;
var diagnosticSource = _applicationServices. GetRequiredService < DiagnosticListener > ( ) ;
var httpContextFactory = _applicationServices. GetRequiredService < IHttpContextFactory > ( ) ;
var hostingApp = new HostingApplication ( application, _logger, diagnosticSource, httpContextFactory) ;
await Server. StartAsync ( hostingApp, cancellationToken) . ConfigureAwait ( false ) ;
_applicationLifetime? . NotifyStarted ( ) ;
await _hostedServiceExecutor. StartAsync ( cancellationToken) . ConfigureAwait ( false ) ;
_logger. Started ( ) ;
if ( _logger. IsEnabled ( LogLevel. Debug) )
{
foreach ( var assembly in _options. GetFinalHostingStartupAssemblies ( ) )
{
_logger. LogDebug ( "Loaded hosting startup assembly {assemblyName}" , assembly) ;
}
}
if ( _hostingStartupErrors != null )
{
foreach ( var exception in _hostingStartupErrors. InnerExceptions)
{
_logger. HostingStartupAssemblyError ( exception) ;
}
}
}
private void EnsureApplicationServices ( )
{
if ( _applicationServices == null )
{
EnsureStartup ( ) ;
_applicationServices = _startup. ConfigureServices ( _applicationServiceCollection) ;
}
}
private void EnsureStartup ( )
{
if ( _startup != null )
{
return ;
}
_startup = _hostingServiceProvider. GetService < IStartup > ( ) ;
if ( _startup == null )
{
throw new InvalidOperationException ( $"No application configured. Please specify startup via IWebHostBuilder.UseStartup, IWebHostBuilder.Configure, injecting {nameof(IStartup)} or specifying the startup assembly via {nameof(WebHostDefaults.StartupAssemblyKey)} in the web host configuration." ) ;
}
}
private RequestDelegate BuildApplication ( )
{
try
{
_applicationServicesException? . Throw ( ) ;
EnsureServer ( ) ;
var builderFactory = _applicationServices. GetRequiredService < IApplicationBuilderFactory > ( ) ;
var builder = builderFactory. CreateBuilder ( Server. Features) ;
builder. ApplicationServices = _applicationServices;
var startupFilters = _applicationServices. GetService< IEnumerable< IStartupFilter> > ( ) ;
Action< IApplicationBuilder> configure = _startup. Configure;
foreach ( var filter in startupFilters. Reverse ( ) )
{
configure = filter. Configure ( configure) ;
}
configure ( builder) ;
return builder. Build ( ) ;
}
catch ( Exception ex)
{
if ( ! _options. SuppressStatusMessages)
{
Console. WriteLine ( "Application startup exception: " + ex. ToString ( ) ) ;
}
var logger = _applicationServices. GetRequiredService< ILogger< WebHost> > ( ) ;
logger. ApplicationError ( ex) ;
if ( ! _options. CaptureStartupErrors)
{
throw ;
}
EnsureServer ( ) ;
var hostingEnv = _applicationServices. GetRequiredService < IHostingEnvironment > ( ) ;
var showDetailedErrors = hostingEnv. IsDevelopment ( ) || _options. DetailedErrors;
var model = new ErrorPageModel
{
RuntimeDisplayName = RuntimeInformation. FrameworkDescription
} ;
var systemRuntimeAssembly = typeof ( System. ComponentModel. DefaultValueAttribute) . GetTypeInfo ( ) . Assembly;
var assemblyVersion = new AssemblyName ( systemRuntimeAssembly. FullName) . Version. ToString ( ) ;
var clrVersion = assemblyVersion;
model. RuntimeArchitecture = RuntimeInformation. ProcessArchitecture. ToString ( ) ;
var currentAssembly = typeof ( ErrorPage) . GetTypeInfo ( ) . Assembly;
model. CurrentAssemblyVesion = currentAssembly
. GetCustomAttribute < AssemblyInformationalVersionAttribute > ( )
. InformationalVersion;
model. ClrVersion = clrVersion;
model. OperatingSystemDescription = RuntimeInformation. OSDescription;
if ( showDetailedErrors)
{
var exceptionDetailProvider = new ExceptionDetailsProvider (
hostingEnv. ContentRootFileProvider,
sourceCodeLineCount: 6 ) ;
model. ErrorDetails = exceptionDetailProvider. GetDetails ( ex) ;
}
else
{
model. ErrorDetails = new ExceptionDetails [ 0 ] ;
}
var errorPage = new ErrorPage ( model) ;
return context = >
{
context. Response. StatusCode = 500 ;
context. Response. Headers[ "Cache-Control" ] = "no-cache" ;
return errorPage. ExecuteAsync ( context) ;
} ;
}
}
private void EnsureServer ( )
{
if ( Server == null )
{
Server = _applicationServices. GetRequiredService < IServer > ( ) ;
var serverAddressesFeature = Server. Features? . Get < IServerAddressesFeature > ( ) ;
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 = WebHostUtilities. ParseBool ( _config, WebHostDefaults. PreferHostingUrlsKey) ;
foreach ( var value in urls. Split ( new [ ] { ';' } , StringSplitOptions. RemoveEmptyEntries) )
{
addresses. Add ( value ) ;
}
}
}
}
}
public async Task StopAsync ( CancellationToken cancellationToken = default )
{
if ( _stopped)
{
return ;
}
_stopped = true ;
_logger? . Shutdown ( ) ;
var timeoutToken = new CancellationTokenSource ( Options. ShutdownTimeout) . Token;
if ( ! cancellationToken. CanBeCanceled)
{
cancellationToken = timeoutToken;
}
else
{
cancellationToken = CancellationTokenSource. CreateLinkedTokenSource ( cancellationToken, timeoutToken) . Token;
}
_applicationLifetime? . StopApplication ( ) ;
if ( Server != null )
{
await Server. StopAsync ( cancellationToken) . ConfigureAwait ( false ) ;
}
if ( _hostedServiceExecutor != null )
{
await _hostedServiceExecutor. StopAsync ( cancellationToken) . ConfigureAwait ( false ) ;
}
_applicationLifetime? . NotifyStopped ( ) ;
HostingEventSource. Log. HostStop ( ) ;
}
public void Dispose ( )
{
DisposeAsync ( ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
}
public async ValueTask DisposeAsync ( )
{
if ( ! _stopped)
{
try
{
await StopAsync ( ) . ConfigureAwait ( false ) ;
}
catch ( Exception ex)
{
_logger? . ServerShutdownException ( ex) ;
}
}
await DisposeServiceProviderAsync ( _applicationServices) . ConfigureAwait ( false ) ;
await DisposeServiceProviderAsync ( _hostingServiceProvider) . ConfigureAwait ( false ) ;
}
private async ValueTask DisposeServiceProviderAsync ( IServiceProvider serviceProvider)
{
switch ( serviceProvider)
{
case IAsyncDisposable asyncDisposable:
await asyncDisposable. DisposeAsync ( ) ;
break ;
case IDisposable disposable:
disposable. Dispose ( ) ;
break ;
}
}
}
}