Skip to content

Commit

Permalink
React to API review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
halter73 committed Apr 19, 2021
1 parent 1184f79 commit b430995
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 108 deletions.
12 changes: 4 additions & 8 deletions src/DefaultBuilder/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ Microsoft.AspNetCore.Builder.WebApplication.DisposeAsync() -> System.Threading.T
Microsoft.AspNetCore.Builder.WebApplication.Environment.get -> Microsoft.AspNetCore.Hosting.IWebHostEnvironment!
Microsoft.AspNetCore.Builder.WebApplication.Lifetime.get -> Microsoft.Extensions.Hosting.IHostApplicationLifetime!
Microsoft.AspNetCore.Builder.WebApplication.Logger.get -> Microsoft.Extensions.Logging.ILogger!
Microsoft.AspNetCore.Builder.WebApplication.Run() -> void
Microsoft.AspNetCore.Builder.WebApplication.RunAsync() -> System.Threading.Tasks.Task!
Microsoft.AspNetCore.Builder.WebApplication.RunAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task!
Microsoft.AspNetCore.Builder.WebApplication.RunAsync(params string![]! urls) -> System.Threading.Tasks.Task!
Microsoft.AspNetCore.Builder.WebApplication.Run(string? url = null) -> void
Microsoft.AspNetCore.Builder.WebApplication.RunAsync(string? url = null) -> System.Threading.Tasks.Task!
Microsoft.AspNetCore.Builder.WebApplication.Services.get -> System.IServiceProvider!
Microsoft.AspNetCore.Builder.WebApplication.StartAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
Microsoft.AspNetCore.Builder.WebApplication.StopAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
Expand All @@ -41,7 +39,5 @@ Microsoft.AspNetCore.Builder.WebApplicationBuilder.Host.get -> Microsoft.AspNetC
Microsoft.AspNetCore.Builder.WebApplicationBuilder.Logging.get -> Microsoft.Extensions.Logging.ILoggingBuilder!
Microsoft.AspNetCore.Builder.WebApplicationBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
Microsoft.AspNetCore.Builder.WebApplicationBuilder.WebHost.get -> Microsoft.AspNetCore.Builder.ConfigureWebHostBuilder!
static Microsoft.AspNetCore.Builder.WebApplication.Create() -> Microsoft.AspNetCore.Builder.WebApplication!
static Microsoft.AspNetCore.Builder.WebApplication.Create(string![]! args) -> Microsoft.AspNetCore.Builder.WebApplication!
static Microsoft.AspNetCore.Builder.WebApplication.CreateBuilder() -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
static Microsoft.AspNetCore.Builder.WebApplication.CreateBuilder(string![]! args) -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
static Microsoft.AspNetCore.Builder.WebApplication.Create(string![]? args = null) -> Microsoft.AspNetCore.Builder.WebApplication!
static Microsoft.AspNetCore.Builder.WebApplication.CreateBuilder(string![]? args = null) -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
119 changes: 51 additions & 68 deletions src/DefaultBuilder/src/WebApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,53 +95,66 @@ internal IEndpointRouteBuilder RouteBuilder
IServiceProvider IEndpointRouteBuilder.ServiceProvider => Services;

/// <summary>
/// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with pre-configured defaults.
/// </summary>
/// <returns>The <see cref="WebApplicationBuilder"/></returns>
public static WebApplicationBuilder CreateBuilder() =>
// The assumption here is that this API is called by the application directly
// this might give a better approximation of the default application name
new WebApplicationBuilder(Assembly.GetCallingAssembly());

/// <summary>
/// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with pre-configured defaults.
/// Initializes a new instance of the <see cref="WebApplication"/> class with preconfigured defaults.
/// </summary>
/// <param name="args">Command line arguments</param>
/// <returns>The <see cref="WebApplicationBuilder"/></returns>
public static WebApplicationBuilder CreateBuilder(string[] args) =>
new WebApplicationBuilder(Assembly.GetCallingAssembly(), args);

/// <summary>
/// Initializes a new instance of the <see cref="WebApplication"/> class with pre-configured defaults.
/// </summary>
/// <param name="args">Command line arguments</param>
/// <returns>The <see cref="WebApplication"/></returns>
public static WebApplication Create(string[] args) =>
/// <returns>The <see cref="WebApplication"/>.</returns>
public static WebApplication Create(string[]? args = null) =>
new WebApplicationBuilder(Assembly.GetCallingAssembly(), args).Build();

/// <summary>
/// Initializes a new instance of the <see cref="WebApplication"/> class with pre-configured defaults.
/// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class with preconfigured defaults.
/// </summary>
/// <returns>The <see cref="WebApplication"/></returns>
public static WebApplication Create()
=> new WebApplicationBuilder(Assembly.GetCallingAssembly()).Build();
/// <param name="args">Command line arguments</param>
/// <returns>The <see cref="WebApplicationBuilder"/>.</returns>
public static WebApplicationBuilder CreateBuilder(string[]? args = null) =>
new WebApplicationBuilder(Assembly.GetCallingAssembly(), args);

/// <summary>
/// Start the application.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <returns>
/// A <see cref="Task"/> that represents the startup of the <see cref="WebApplication"/>.
/// Successful completion indicates the server is ready to accept new requests.
/// </returns>
public Task StartAsync(CancellationToken cancellationToken = default) =>
_host.StartAsync(cancellationToken);

/// <summary>
/// Shuts down the application.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <returns>
/// A <see cref="Task"/> that represents the shutdown of the <see cref="WebApplication"/>.
/// Successful completion indicates that all the server connections have been closed.
/// </returns>
public Task StopAsync(CancellationToken cancellationToken = default) =>
_host.StopAsync(cancellationToken);

/// <summary>
/// Runs an application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <param name="url">The URL to listen to if the server hasn't been configured directly.</param>
/// <returns>
/// A <see cref="Task"/> that represents the entire runtime of the <see cref="WebApplication"/> from startup to shutdown.
/// </returns>
public Task RunAsync(string? url = null)
{
Listen(url);
return HostingAbstractionsHostExtensions.RunAsync(this);
}

/// <summary>
/// Runs an application and block the calling thread until host shutdown.
/// </summary>
/// <param name="url">The URL to listen to if the server hasn't been configured directly.</param>
public void Run(string? url = null)
{
Listen(url);
HostingAbstractionsHostExtensions.Run(this);
}

/// <summary>
/// Disposes the application.
/// </summary>
Expand All @@ -166,55 +179,25 @@ IApplicationBuilder IApplicationBuilder.Use(Func<RequestDelegate, RequestDelegat

IApplicationBuilder IEndpointRouteBuilder.CreateApplicationBuilder() => ApplicationBuilder.New();

/// <summary>
/// Runs an application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <returns>A <see cref="Task"/>that represents the asynchronous operation.</returns>
// REVIEW: We cannot use a default param for the CT because of the params urls overload. Are we okay with this?
public Task RunAsync() => RunAsync(CancellationToken.None);

/// <summary>
/// Runs an application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <param name="cancellationToken">The token to trigger shutdown.</param>
/// <returns>A <see cref="Task"/>that represents the asynchronous operation.</returns>
public Task RunAsync(CancellationToken cancellationToken) =>
HostingAbstractionsHostExtensions.RunAsync(this, cancellationToken);

/// <summary>
/// Runs an application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <param name="urls">A set of urls to listen to if the server hasn't been configured directly.</param>
/// <returns>A <see cref="Task"/>that represents the asynchronous operation.</returns>
public Task RunAsync(params string[] urls)
private void Listen(string? url)
{
Listen(urls);
return HostingAbstractionsHostExtensions.RunAsync(this);
}

/// <summary>
/// Runs an application and block the calling thread until host shutdown.
/// </summary>
public void Run() =>
HostingAbstractionsHostExtensions.Run(this);
if (url is null)
{
return;
}

/// <summary>
/// Sets the URLs the web server will listen on.
/// </summary>
/// <param name="urls">A set of urls to listen to if the server hasn't been configured directly.</param>
private void Listen(params string[] urls)
{
var addresses = ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
if (addresses is null || addresses.IsReadOnly)
if (addresses is null)
{
throw new NotSupportedException("Changing the URL isn't supported.");
throw new NotSupportedException($"Changing the URL is not supported because no valid {nameof(IServerAddressesFeature)} was found.");
}

addresses.Clear();
foreach (var u in urls)
if (addresses.IsReadOnly)
{
addresses.Add(u);
throw new NotSupportedException($"Changing the URL is not supported because {nameof(IServerAddressesFeature.Addresses)} {nameof(ICollection<string>.IsReadOnly)}.");
}

addresses.Clear();
addresses.Add(url);
}
}
}
61 changes: 29 additions & 32 deletions src/DefaultBuilder/src/WebApplicationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,11 @@ public sealed class WebApplicationBuilder

internal WebApplicationBuilder(Assembly? callingAssembly, string[]? args = null)
{
Services = new ServiceCollection();

// HACK: MVC and Identity do this horrible thing to get the hosting environment as an instance
// from the service collection before it is built. That needs to be fixed...
Environment = _environment = new WebHostEnvironment(callingAssembly);
Services.AddSingleton(Environment);

Configuration = new Configuration();

// Run methods to configure both generic and web host defaults early to populate config from appsettings.json
// environment variables (both DOTNET_ and ASPNETCORE_ prefixed) and other possible default sources to prepopulate
// the correct defaults.
Expand All @@ -57,12 +53,12 @@ internal WebApplicationBuilder(Assembly? callingAssembly, string[]? args = null)
/// <summary>
/// A collection of services for the application to compose. This is useful for adding user provided or framework provided services.
/// </summary>
public IServiceCollection Services { get; }
public IServiceCollection Services { get; } = new ServiceCollection();

/// <summary>
/// A collection of configuration providers for the application to compose. This is useful for adding new configuration sources and providers.
/// </summary>
public Configuration Configuration { get; }
public Configuration Configuration { get; } = new();

/// <summary>
/// A collection of logging providers for the applicaiton to compose. This is useful for adding new logging providers.
Expand Down Expand Up @@ -92,32 +88,6 @@ public WebApplication Build()
return _builtApplication;
}

private void ConfigureWebHost(IWebHostBuilder genericWebHostBuilder)
{
genericWebHostBuilder.Configure(ConfigureApplication);

_hostBuilder.ConfigureServices((context, services) =>
{
foreach (var s in Services)
{
services.Add(s);
}
});

_hostBuilder.ConfigureAppConfiguration((hostContext, builder) =>
{
foreach (var s in Configuration.Sources)
{
builder.Sources.Add(s);
}
});

_deferredHostBuilder.ExecuteActions(_hostBuilder);
_deferredWebHostBuilder.ExecuteActions(genericWebHostBuilder);

_environment.ApplyEnvironmentSettings(genericWebHostBuilder);
}

private void ConfigureApplication(WebHostBuilderContext context, IApplicationBuilder app)
{
Debug.Assert(_builtApplication is not null);
Expand Down Expand Up @@ -180,6 +150,33 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui
{
app.Properties[item.Key] = item.Value;
}

}

private void ConfigureWebHost(IWebHostBuilder genericWebHostBuilder)
{
genericWebHostBuilder.Configure(ConfigureApplication);

_hostBuilder.ConfigureServices((context, services) =>
{
foreach (var s in Services)
{
services.Add(s);
}
});

_hostBuilder.ConfigureAppConfiguration((hostContext, builder) =>
{
foreach (var s in Configuration.Sources)
{
builder.Sources.Add(s);
}
});

_deferredHostBuilder.ExecuteActions(_hostBuilder);
_deferredWebHostBuilder.ExecuteActions(genericWebHostBuilder);

_environment.ApplyEnvironmentSettings(genericWebHostBuilder);
}

private class LoggingBuilder : ILoggingBuilder
Expand Down

0 comments on commit b430995

Please sign in to comment.