More hosting API changes

- Added IWebApplicationBuilder and moved it to Hosting.Abstractions as a
target for others to extend the web application builder.
- Made methods extension methods where possible
- Added UseUrls
This commit is contained in:
David Fowler 2016-01-06 18:08:57 -08:00
parent 46e3e25ec7
commit e72924796e
19 changed files with 373 additions and 242 deletions

View File

@ -35,8 +35,9 @@ namespace SampleStartups
.UseStartup<StartupBlockingOnStart>()
.Build();
using (application.Start())
using (application)
{
application.Start();
Console.ReadLine();
}
}

View File

@ -32,12 +32,9 @@ namespace SampleStartups
var application = new WebApplicationBuilder()
.UseConfiguration(config)
.UseStartup<StartupConfigureAddresses>()
.UseUrls("http://localhost:5000", "http://localhost:5001")
.Build();
var addresses = application.GetAddresses();
addresses.Add("http://localhost:5000");
addresses.Add("http://localhost:5001");
application.Run();
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http;
@ -10,8 +11,8 @@ namespace SampleStartups
{
public class StartupExternallyControlled
{
private readonly IWebApplication _host;
private IDisposable _application;
private IWebApplication _application;
private readonly List<string> _urls = new List<string>();
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
@ -30,15 +31,13 @@ namespace SampleStartups
public StartupExternallyControlled()
{
_host = new WebApplicationBuilder().UseStartup<StartupExternallyControlled>().Build();
// Clear all configured addresses
_host.GetAddresses().Clear();
}
public void Start()
{
_application = _host.Start();
_application = new WebApplicationBuilder()
.UseStartup<StartupExternallyControlled>()
.Start(_urls.ToArray());
}
public void Stop()
@ -48,9 +47,7 @@ namespace SampleStartups
public void AddUrl(string url)
{
var addresses = _host.GetAddresses();
addresses.Add(url);
_urls.Add(url);
}
}
}

View File

@ -14,14 +14,11 @@ namespace SampleStartups
public static void Main(string[] args)
{
var application = new WebApplicationBuilder()
.UseServerFactory("Microsoft.AspNet.Server.Kestrel") // Set the server manually
.UseServer("Microsoft.AspNet.Server.Kestrel") // Set the server manually
.UseApplicationBasePath(Directory.GetCurrentDirectory()) // Override the application base with the current directory
.UseUrls("http://*:1000", "https://*:902")
.UseEnvironment("Development")
.UseWebRoot("public")
.ConfigureLogging(loggerFactory =>
{
loggerFactory.AddProvider(new MyHostLoggerProvider());
})
.ConfigureServices(services =>
{
// Configure services that the application can see

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Hosting
/// <summary>
/// Represents a configured web application
/// </summary>
public interface IWebApplication
public interface IWebApplication : IDisposable
{
/// <summary>
/// The <see cref="IFeatureCollection"/> exposed by the configured server.
@ -25,6 +25,6 @@ namespace Microsoft.AspNet.Hosting
/// Starts listening on the configured addresses.
/// </summary>
/// <returns></returns>
IDisposable Start();
void Start();
}
}

View File

@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting.Server;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNet.Hosting
{
public interface IWebApplicationBuilder
{
IWebApplication Build();
IWebApplicationBuilder UseConfiguration(IConfiguration configuration);
IWebApplicationBuilder UseServer(IServerFactory factory);
IWebApplicationBuilder UseStartup(Type startupType);
IWebApplicationBuilder ConfigureServices(Action<IServiceCollection> configureServices);
IWebApplicationBuilder Configure(Action<IApplicationBuilder> configureApplication);
IWebApplicationBuilder UseSetting(string key, string value);
}
}

View File

@ -12,7 +12,9 @@
"dependencies": {
"Microsoft.AspNet.Http.Abstractions": "1.0.0-*",
"Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*",
"Microsoft.Extensions.Configuration.Abstractions": "1.0.0-*"
"Microsoft.AspNet.Hosting.Server.Abstractions": "1.0.0-*",
"Microsoft.Extensions.Configuration.Abstractions": "1.0.0-*",
"Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-*"
},
"frameworks": {
"net451": {},

View File

@ -13,7 +13,6 @@ namespace Microsoft.AspNet.Hosting.WindowsServices
public class WebApplicationService : ServiceBase
{
private IWebApplication _application;
private IDisposable _applicationShutdown;
private bool _stopRequestedByWindows;
/// <summary>
@ -41,7 +40,7 @@ namespace Microsoft.AspNet.Hosting.WindowsServices
}
});
_applicationShutdown = _application.Start();
_application.Start();
OnStarted();
}
@ -50,7 +49,7 @@ namespace Microsoft.AspNet.Hosting.WindowsServices
{
_stopRequestedByWindows = true;
OnStopping();
_applicationShutdown?.Dispose();
_application?.Dispose();
OnStopped();
}

View File

@ -0,0 +1,39 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.Configuration;
namespace Microsoft.AspNet.Hosting.Internal
{
// TODO: Remove this once https://github.com/aspnet/Configuration/pull/349 gets merged
internal class IncludedConfigurationProvider : ConfigurationProvider
{
public IncludedConfigurationProvider(IConfiguration source)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
int pathStart = 0;
var section = source as IConfigurationSection;
if (section != null)
{
pathStart = section.Path.Length + 1;
}
foreach (var child in source.GetChildren())
{
AddSection(child, pathStart);
}
}
private void AddSection(IConfigurationSection section, int pathStart)
{
Data.Add(section.Path.Substring(pathStart), section.Value);
foreach (var child in section.GetChildren())
{
AddSection(child, pathStart);
}
}
}
}

View File

@ -32,6 +32,7 @@ namespace Microsoft.AspNet.Hosting.Internal
private IServiceProvider _applicationServices;
private RequestDelegate _application;
private ILogger<WebApplication> _logger;
// Only one of these should be set
internal string StartupAssemblyName { get; set; }
@ -41,7 +42,7 @@ namespace Microsoft.AspNet.Hosting.Internal
// Only one of these should be set
internal IServerFactory ServerFactory { get; set; }
internal string ServerFactoryLocation { get; set; }
internal IServer Server { get; set; }
private IServer Server { get; set; }
public WebApplication(
IServiceCollection appServices,
@ -97,29 +98,20 @@ namespace Microsoft.AspNet.Hosting.Internal
}
}
public virtual IDisposable Start()
public virtual void Start()
{
Initialize();
var logger = _applicationServices.GetRequiredService<ILogger<WebApplication>>();
_logger = _applicationServices.GetRequiredService<ILogger<WebApplication>>();
var diagnosticSource = _applicationServices.GetRequiredService<DiagnosticSource>();
var httpContextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();
logger.Starting();
_logger.Starting();
Server.Start(new HostingApplication(_application, logger, diagnosticSource, httpContextFactory));
Server.Start(new HostingApplication(_application, _logger, diagnosticSource, httpContextFactory));
_applicationLifetime.NotifyStarted();
logger.Started();
return new Disposable(() =>
{
logger.Shutdown();
_applicationLifetime.StopApplication();
Server.Dispose();
_applicationLifetime.NotifyStopped();
(_applicationServices as IDisposable)?.Dispose();
});
_logger.Started();
}
private void EnsureApplicationServices()
@ -248,6 +240,15 @@ namespace Microsoft.AspNet.Hosting.Internal
}
}
public void Dispose()
{
_logger?.Shutdown();
_applicationLifetime.StopApplication();
Server?.Dispose();
_applicationLifetime.NotifyStopped();
(_applicationServices as IDisposable)?.Dispose();
}
private class Disposable : IDisposable
{
private Action _dispose;

View File

@ -27,6 +27,7 @@ namespace Microsoft.AspNet.Hosting.Internal
Environment = configuration[WebApplicationConfiguration.EnvironmentKey] ?? configuration[OldEnvironmentKey];
ServerFactoryLocation = configuration[WebApplicationConfiguration.ServerKey];
WebRoot = configuration[WebApplicationConfiguration.WebRootKey];
ApplicationBasePath = configuration[WebApplicationConfiguration.ApplicationBaseKey];
}
public string Application { get; set; }
@ -41,6 +42,8 @@ namespace Microsoft.AspNet.Hosting.Internal
public string WebRoot { get; set; }
public string ApplicationBasePath { get; set; }
private static bool ParseBool(IConfiguration configuration, string key)
{
return string.Equals("true", configuration[key], StringComparison.OrdinalIgnoreCase)

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Versioning;
using Microsoft.AspNet.Builder;
@ -16,10 +17,11 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNet.Hosting
{
public class WebApplicationBuilder
public class WebApplicationBuilder : IWebApplicationBuilder
{
private readonly IHostingEnvironment _hostingEnvironment;
private readonly ILoggerFactory _loggerFactory;
@ -28,19 +30,15 @@ namespace Microsoft.AspNet.Hosting
private WebApplicationOptions _options;
private Action<IServiceCollection> _configureServices;
private string _environmentName;
private string _webRoot;
private string _applicationBasePath;
// Only one of these should be set
private StartupMethods _startup;
private Type _startupType;
private string _startupAssemblyName;
// Only one of these should be set
private string _serverFactoryLocation;
private IServerFactory _serverFactory;
private IServer _server;
private Dictionary<string, string> _settings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public WebApplicationBuilder()
{
@ -48,62 +46,19 @@ namespace Microsoft.AspNet.Hosting
_loggerFactory = new LoggerFactory();
}
public WebApplicationBuilder UseConfiguration(IConfiguration configuration)
public IWebApplicationBuilder UseSetting(string key, string value)
{
_settings[key] = value;
return this;
}
public IWebApplicationBuilder UseConfiguration(IConfiguration configuration)
{
_config = configuration;
return this;
}
public WebApplicationBuilder UseApplicationBasePath(string applicationBasePath)
{
_applicationBasePath = applicationBasePath;
return this;
}
public WebApplicationBuilder UseEnvironment(string environment)
{
if (environment == null)
{
throw new ArgumentNullException(nameof(environment));
}
_environmentName = environment;
return this;
}
public WebApplicationBuilder UseWebRoot(string webRoot)
{
if (webRoot == null)
{
throw new ArgumentNullException(nameof(webRoot));
}
_webRoot = webRoot;
return this;
}
public WebApplicationBuilder UseServer(IServer server)
{
if (server == null)
{
throw new ArgumentNullException(nameof(server));
}
_server = server;
return this;
}
public WebApplicationBuilder UseServerFactory(string assemblyName)
{
if (assemblyName == null)
{
throw new ArgumentNullException(nameof(assemblyName));
}
_serverFactoryLocation = assemblyName;
return this;
}
public WebApplicationBuilder UseServerFactory(IServerFactory factory)
public IWebApplicationBuilder UseServer(IServerFactory factory)
{
if (factory == null)
{
@ -114,18 +69,7 @@ namespace Microsoft.AspNet.Hosting
return this;
}
public WebApplicationBuilder UseStartup(string startupAssemblyName)
{
if (startupAssemblyName == null)
{
throw new ArgumentNullException(nameof(startupAssemblyName));
}
_startupAssemblyName = startupAssemblyName;
return this;
}
public WebApplicationBuilder UseStartup(Type startupType)
public IWebApplicationBuilder UseStartup(Type startupType)
{
if (startupType == null)
{
@ -136,18 +80,13 @@ namespace Microsoft.AspNet.Hosting
return this;
}
public WebApplicationBuilder UseStartup<TStartup>() where TStartup : class
{
return UseStartup(typeof(TStartup));
}
public WebApplicationBuilder ConfigureServices(Action<IServiceCollection> configureServices)
public IWebApplicationBuilder ConfigureServices(Action<IServiceCollection> configureServices)
{
_configureServices = configureServices;
return this;
}
public WebApplicationBuilder Configure(Action<IApplicationBuilder> configureApp)
public IWebApplicationBuilder Configure(Action<IApplicationBuilder> configureApp)
{
if (configureApp == null)
{
@ -158,7 +97,7 @@ namespace Microsoft.AspNet.Hosting
return this;
}
public WebApplicationBuilder ConfigureLogging(Action<ILoggerFactory> configureLogging)
public IWebApplicationBuilder ConfigureLogging(Action<ILoggerFactory> configureLogging)
{
configureLogging(_loggerFactory);
return this;
@ -173,29 +112,19 @@ namespace Microsoft.AspNet.Hosting
var appEnvironment = hostingContainer.GetRequiredService<IApplicationEnvironment>();
var startupLoader = hostingContainer.GetRequiredService<IStartupLoader>();
_config = _config ?? WebApplicationConfiguration.GetDefault();
_options = new WebApplicationOptions(_config);
// Initialize the hosting environment
_options.WebRoot = _webRoot ?? _options.WebRoot;
_hostingEnvironment.Initialize(appEnvironment.ApplicationBasePath, _options, _config);
if (!string.IsNullOrEmpty(_environmentName))
{
_hostingEnvironment.EnvironmentName = _environmentName;
}
var application = new WebApplication(hostingServices, startupLoader, _options, _config);
// Only one of these should be set, but they are used in priority
application.Server = _server;
application.ServerFactory = _serverFactory;
application.ServerFactoryLocation = _options.ServerFactoryLocation ?? _serverFactoryLocation;
application.ServerFactoryLocation = _options.ServerFactoryLocation;
// Only one of these should be set, but they are used in priority
application.Startup = _startup;
application.StartupType = _startupType;
application.StartupAssemblyName = _startupAssemblyName ?? _options.Application;
application.StartupAssemblyName = _options.Application;
application.Initialize();
@ -204,6 +133,17 @@ namespace Microsoft.AspNet.Hosting
private IServiceCollection BuildHostingServices()
{
// Apply the configuration settings
var configuration = _config ?? WebApplicationConfiguration.GetDefault();
var mergedConfiguration = new ConfigurationBuilder()
.Add(new IncludedConfigurationProvider(configuration))
.AddInMemoryCollection(_settings)
.Build();
_config = mergedConfiguration;
_options = new WebApplicationOptions(_config);
var services = new ServiceCollection();
services.AddSingleton(_hostingEnvironment);
services.AddSingleton(_loggerFactory);
@ -230,9 +170,9 @@ namespace Microsoft.AspNet.Hosting
if (defaultPlatformServices.Application != null)
{
var appEnv = defaultPlatformServices.Application;
if (!string.IsNullOrEmpty(_applicationBasePath))
if (!string.IsNullOrEmpty(_options.ApplicationBasePath))
{
appEnv = new WrappedApplicationEnvironment(_applicationBasePath, appEnv);
appEnv = new WrappedApplicationEnvironment(_options.ApplicationBasePath, appEnv);
}
services.TryAddSingleton(appEnv);

View File

@ -0,0 +1,148 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Hosting.Server;
using Microsoft.AspNet.Server.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNet.Hosting
{
public static class WebApplicationBuilderExtensions
{
private static readonly string ServerUrlsSeparator = ";";
public static IWebApplicationBuilder UseStartup<TStartup>(this IWebApplicationBuilder applicationBuilder) where TStartup : class
{
return applicationBuilder.UseStartup(typeof(TStartup));
}
public static IWebApplicationBuilder UseServer(this IWebApplicationBuilder applicationBuilder, string assemblyName)
{
if (assemblyName == null)
{
throw new ArgumentNullException(nameof(assemblyName));
}
return applicationBuilder.UseSetting(WebApplicationConfiguration.ServerKey, assemblyName);
}
public static IWebApplicationBuilder UseServer(this IWebApplicationBuilder applicationBuilder, IServer server)
{
if (server == null)
{
throw new ArgumentNullException(nameof(server));
}
return applicationBuilder.UseServer(new ServerFactory(server));
}
public static IWebApplicationBuilder UseApplicationBasePath(this IWebApplicationBuilder applicationBuilder, string applicationBasePath)
{
if (applicationBasePath == null)
{
throw new ArgumentNullException(nameof(applicationBasePath));
}
return applicationBuilder.UseSetting(WebApplicationConfiguration.ApplicationBaseKey, applicationBasePath);
}
public static IWebApplicationBuilder UseEnvironment(this IWebApplicationBuilder applicationBuilder, string environment)
{
if (environment == null)
{
throw new ArgumentNullException(nameof(environment));
}
return applicationBuilder.UseSetting(WebApplicationConfiguration.EnvironmentKey, environment);
}
public static IWebApplicationBuilder UseWebRoot(this IWebApplicationBuilder applicationBuilder, string webRoot)
{
if (webRoot == null)
{
throw new ArgumentNullException(nameof(webRoot));
}
return applicationBuilder.UseSetting(WebApplicationConfiguration.WebRootKey, webRoot);
}
public static IWebApplicationBuilder UseUrls(this IWebApplicationBuilder applicationBuilder, params string[] urls)
{
if (urls == null)
{
throw new ArgumentNullException(nameof(urls));
}
return applicationBuilder.UseSetting(WebApplicationConfiguration.ServerUrlsKey, string.Join(ServerUrlsSeparator, urls));
}
public static IWebApplicationBuilder UseStartup(this IWebApplicationBuilder applicationBuilder, string startupAssemblyName)
{
if (startupAssemblyName == null)
{
throw new ArgumentNullException(nameof(startupAssemblyName));
}
return applicationBuilder.UseSetting(WebApplicationConfiguration.ApplicationKey, startupAssemblyName);
}
public static IWebApplication Start(this IWebApplicationBuilder applicationBuilder, params string[] urls)
{
var application = applicationBuilder.UseUrls(urls).Build();
application.Start();
return application;
}
/// <summary>
/// Runs a web application and block the calling thread until host shutdown.
/// </summary>
/// <param name="application"></param>
public static void Run(this IWebApplication application)
{
using (application)
{
application.Start();
var hostingEnvironment = application.Services.GetService<IHostingEnvironment>();
var applicationLifetime = application.Services.GetService<IApplicationLifetime>();
Console.WriteLine("Hosting environment: " + hostingEnvironment.EnvironmentName);
var serverAddresses = application.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
if (serverAddresses != null)
{
foreach (var address in serverAddresses)
{
Console.WriteLine("Now listening on: " + address);
}
}
Console.WriteLine("Application started. Press Ctrl+C to shut down.");
Console.CancelKeyPress += (sender, eventArgs) =>
{
applicationLifetime.StopApplication();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
applicationLifetime.ApplicationStopping.WaitHandle.WaitOne();
}
}
private class ServerFactory : IServerFactory
{
private readonly IServer _server;
public ServerFactory(IServer server)
{
_server = server;
}
public IServer CreateServer(IConfiguration configuration) => _server;
}
}
}

View File

@ -4,12 +4,14 @@ namespace Microsoft.AspNet.Hosting
{
public class WebApplicationConfiguration
{
public static readonly string ApplicationKey = "app";
public static readonly string ApplicationKey = "application";
public static readonly string DetailedErrorsKey = "detailedErrors";
public static readonly string EnvironmentKey = "environment";
public static readonly string ServerKey = "server";
public static readonly string WebRootKey = "webroot";
public static readonly string CaptureStartupErrorsKey = "captureStartupErrors";
public static readonly string ServerUrlsKey = "server.urls";
public static readonly string ApplicationBaseKey = "applicationBase";
public static readonly string HostingJsonFile = "hosting.json";
public static readonly string EnvironmentVariablesPrefix = "ASPNET_";

View File

@ -1,60 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Server.Features;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNet.Hosting
{
public static class WebApplicationExtensions
{
/// <summary>
/// Retruns the server addresses the web application is going to listen on.
/// </summary>
/// <param name="application"></param>
/// <returns>An <see cref="ICollection{string}"> which the addresses the server will listen to</returns>
public static ICollection<string> GetAddresses(this IWebApplication application)
{
return application.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
}
/// <summary>
/// Runs a web application and block the calling thread until host shutdown.
/// </summary>
/// <param name="application"></param>
public static void Run(this IWebApplication application)
{
using (application.Start())
{
var hostingEnvironment = application.Services.GetService<IHostingEnvironment>();
var applicationLifetime = application.Services.GetService<IApplicationLifetime>();
Console.WriteLine("Hosting environment: " + hostingEnvironment.EnvironmentName);
var serverAddresses = application.GetAddresses();
if (serverAddresses != null)
{
foreach (var address in serverAddresses)
{
Console.WriteLine("Now listening on: " + address);
}
}
Console.WriteLine("Application started. Press Ctrl+C to shut down.");
Console.CancelKeyPress += (sender, eventArgs) =>
{
applicationLifetime.StopApplication();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
applicationLifetime.ApplicationStopping.WaitHandle.WaitOne();
}
}
}
}

View File

@ -16,14 +16,15 @@ namespace Microsoft.AspNet.TestHost
{
private const string DefaultEnvironmentName = "Development";
private const string ServerName = nameof(TestServer);
private IDisposable _appInstance;
private IWebApplication _appInstance;
private bool _disposed = false;
private IHttpApplication<Context> _application;
public TestServer(WebApplicationBuilder builder)
public TestServer(IWebApplicationBuilder builder)
{
var application = builder.UseServer(this).Build();
_appInstance = application.Start();
application.Start();
_appInstance = application;
}
public Uri BaseAddress { get; set; } = new Uri("http://localhost/");
@ -59,8 +60,11 @@ namespace Microsoft.AspNet.TestHost
public void Dispose()
{
_disposed = true;
_appInstance.Dispose();
if (!_disposed)
{
_disposed = true;
_appInstance.Dispose();
}
}
void IServer.Start<TContext>(IHttpApplication<TContext> application)

View File

@ -36,8 +36,9 @@ namespace Microsoft.AspNet.Hosting
var builder = CreateWebApplicationBuilder();
var server = new TestServer();
var application = builder.UseServer(server).UseStartup("MissingStartupAssembly").Build();
using (application.Start())
using (application)
{
application.Start();
await AssertResponseContains(server.RequestDelegate, "MissingStartupAssembly");
}
}
@ -48,8 +49,9 @@ namespace Microsoft.AspNet.Hosting
var builder = CreateWebApplicationBuilder();
var server = new TestServer();
var application = builder.UseServer(server).UseStartup<StartupStaticCtorThrows>().Build();
using (application.Start())
using (application)
{
application.Start();
await AssertResponseContains(server.RequestDelegate, "Exception from static constructor");
}
}
@ -60,8 +62,9 @@ namespace Microsoft.AspNet.Hosting
var builder = CreateWebApplicationBuilder();
var server = new TestServer();
var application = builder.UseServer(server).UseStartup<StartupCtorThrows>().Build();
using (application.Start())
using (application)
{
application.Start();
await AssertResponseContains(server.RequestDelegate, "Exception from constructor");
}
}
@ -72,8 +75,9 @@ namespace Microsoft.AspNet.Hosting
var builder = CreateWebApplicationBuilder();
var server = new TestServer();
var application = builder.UseServer(server).UseStartup<StartupThrowTypeLoadException>().Build();
using (application.Start())
using (application)
{
application.Start();
await AssertResponseContains(server.RequestDelegate, "Message from the LoaderException</span>");
}
}
@ -84,8 +88,9 @@ namespace Microsoft.AspNet.Hosting
var builder = CreateWebApplicationBuilder();
var server = new TestServer();
var application = builder.UseServer(server).UseStartup<StartupCtorThrows>().Build();
using (application.Start())
using (application)
{
application.Start();
var service = application.Services.GetServices<IApplicationLifetime>();
Assert.NotNull(service);
await AssertResponseContains(server.RequestDelegate, "Exception from constructor");
@ -98,8 +103,9 @@ namespace Microsoft.AspNet.Hosting
var builder = CreateWebApplicationBuilder();
var server = new TestServer();
var application = builder.UseServer(server).UseStartup<StartupConfigureServicesThrows>().Build();
using (application.Start())
using (application)
{
application.Start();
await AssertResponseContains(server.RequestDelegate, "Exception from ConfigureServices");
}
}
@ -110,8 +116,9 @@ namespace Microsoft.AspNet.Hosting
var builder = CreateWebApplicationBuilder();
var server = new TestServer();
var application = builder.UseServer(server).UseStartup<StartupConfigureServicesThrows>().Build();
using (application.Start())
using (application)
{
application.Start();
await AssertResponseContains(server.RequestDelegate, "Exception from Configure");
}
}
@ -138,6 +145,28 @@ namespace Microsoft.AspNet.Hosting
Assert.Equal(expected, application.Services.GetService<IHostingEnvironment>().EnvironmentName);
}
[Fact]
public void BuildAndDispose()
{
var vals = new Dictionary<string, string>
{
{ "ENV", "Dev" },
};
var builder = new ConfigurationBuilder()
.AddInMemoryCollection(vals);
var config = builder.Build();
var expected = "MY_TEST_ENVIRONMENT";
var application = new WebApplicationBuilder()
.UseConfiguration(config)
.UseEnvironment(expected)
.UseServer(new TestServer())
.UseStartup("Microsoft.AspNet.Hosting.Tests")
.Build();
application.Dispose();
}
[Fact]
public void UseBasePathConfiguresBasePath()
{
@ -159,7 +188,7 @@ namespace Microsoft.AspNet.Hosting
Assert.Equal("/foo/bar", application.Services.GetService<IApplicationEnvironment>().ApplicationBasePath);
}
private WebApplicationBuilder CreateWebApplicationBuilder()
private IWebApplicationBuilder CreateWebApplicationBuilder()
{
var vals = new Dictionary<string, string>
{

View File

@ -15,11 +15,11 @@ namespace Microsoft.AspNet.Hosting.Tests
{
var parameters = new Dictionary<string, string>()
{
{"webroot", "wwwroot"},
{"server", "Microsoft.AspNet.Server.Kestrel"},
{"app", "MyProjectReference"},
{"environment", "Development"},
{"detailederrors", "true"},
{ "webroot", "wwwroot"},
{ "server", "Microsoft.AspNet.Server.Kestrel"},
{ "application", "MyProjectReference"},
{ "environment", "Development"},
{ "detailederrors", "true"},
{ "captureStartupErrors", "true" }
};

View File

@ -119,7 +119,7 @@ namespace Microsoft.AspNet.Hosting
.AddInMemoryCollection(vals);
var config = builder.Build();
var application = CreateBuilder(config).Build();
var app = application.Start();
application.Start();
Assert.NotNull(application.Services.GetService<IHostingEnvironment>());
Assert.Equal("http://localhost:abc123", application.ServerFeatures.Get<IServerAddressesFeature>().Addresses.First());
}
@ -136,9 +136,9 @@ namespace Microsoft.AspNet.Hosting
.AddInMemoryCollection(vals);
var config = builder.Build();
var application = CreateBuilder(config).Build();
var app = application.Start();
application.Start();
Assert.NotNull(application.Services.GetService<IHostingEnvironment>());
Assert.Equal("http://localhost:5000", application.GetAddresses().First());
Assert.Equal("http://localhost:5000", application.ServerFeatures.Get<IServerAddressesFeature>().Addresses.First());
}
[Fact]
@ -153,7 +153,7 @@ namespace Microsoft.AspNet.Hosting
.AddInMemoryCollection(vals);
var config = builder.Build();
var application = CreateBuilder(config).Build();
var app = application.Start();
application.Start();
var hostingEnvironment = application.Services.GetService<IHostingEnvironment>();
Assert.NotNull(hostingEnvironment.Configuration);
Assert.Equal("Microsoft.AspNet.Hosting.Tests", hostingEnvironment.Configuration["Server"]);
@ -163,9 +163,8 @@ namespace Microsoft.AspNet.Hosting
public void WebApplicationCanBeStarted()
{
var app = CreateBuilder()
.UseServer(this)
.UseServer((IServerFactory)this)
.UseStartup("Microsoft.AspNet.Hosting.Tests")
.Build()
.Start();
Assert.NotNull(app);
@ -181,7 +180,7 @@ namespace Microsoft.AspNet.Hosting
public void WebApplicationDisposesServiceProvider()
{
var application = CreateBuilder()
.UseServer(this)
.UseServer((IServerFactory)this)
.ConfigureServices(s =>
{
s.AddTransient<IFakeService, FakeService>();
@ -190,7 +189,7 @@ namespace Microsoft.AspNet.Hosting
.UseStartup("Microsoft.AspNet.Hosting.Tests")
.Build();
var app = application.Start();
application.Start();
var singleton = (FakeService)application.Services.GetService<IFakeSingletonService>();
var transient = (FakeService)application.Services.GetService<IFakeService>();
@ -198,7 +197,7 @@ namespace Microsoft.AspNet.Hosting
Assert.False(singleton.Disposed);
Assert.False(transient.Disposed);
app.Dispose();
application.Dispose();
Assert.True(singleton.Disposed);
Assert.True(transient.Disposed);
@ -208,13 +207,14 @@ namespace Microsoft.AspNet.Hosting
public void WebApplicationNotifiesApplicationStarted()
{
var application = CreateBuilder()
.UseServer(this)
.UseServer((IServerFactory)this)
.Build();
var applicationLifetime = application.Services.GetService<IApplicationLifetime>();
Assert.False(applicationLifetime.ApplicationStarted.IsCancellationRequested);
using (application.Start())
using (application)
{
application.Start();
Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested);
}
}
@ -223,13 +223,14 @@ namespace Microsoft.AspNet.Hosting
public void WebApplicationInjectsHostingEnvironment()
{
var application = CreateBuilder()
.UseServer(this)
.UseServer((IServerFactory)this)
.UseStartup("Microsoft.AspNet.Hosting.Tests")
.UseEnvironment("WithHostingEnvironment")
.Build();
using (application.Start())
using (application)
{
application.Start();
var env = application.Services.GetService<IHostingEnvironment>();
Assert.Equal("Changed", env.EnvironmentName);
}
@ -243,7 +244,7 @@ namespace Microsoft.AspNet.Hosting
{
services.AddTransient<IStartupLoader, TestLoader>();
})
.UseServer(this)
.UseServer((IServerFactory)this)
.UseStartup("Microsoft.AspNet.Hosting.Tests");
Assert.Throws<NotImplementedException>(() => builder.Build());
@ -252,14 +253,14 @@ namespace Microsoft.AspNet.Hosting
[Fact]
public void CanCreateApplicationServicesWithAddedServices()
{
var application = CreateBuilder().UseServer(this).ConfigureServices(services => services.AddOptions()).Build();
var application = CreateBuilder().UseServer((IServerFactory)this).ConfigureServices(services => services.AddOptions()).Build();
Assert.NotNull(application.Services.GetRequiredService<IOptions<object>>());
}
[Fact]
public void EnvDefaultsToProductionIfNoConfig()
{
var application = CreateBuilder().UseServer(this).Build();
var application = CreateBuilder().UseServer((IServerFactory)this).Build();
var env = application.Services.GetService<IHostingEnvironment>();
Assert.Equal(EnvironmentName.Production, env.EnvironmentName);
}
@ -278,7 +279,7 @@ namespace Microsoft.AspNet.Hosting
.AddInMemoryCollection(vals);
var config = builder.Build();
var application = CreateBuilder(config).UseServer(this).Build();
var application = CreateBuilder(config).UseServer((IServerFactory)this).Build();
var env = application.Services.GetService<IHostingEnvironment>();
Assert.Equal("Staging", env.EnvironmentName);
}
@ -295,7 +296,7 @@ namespace Microsoft.AspNet.Hosting
.AddInMemoryCollection(vals);
var config = builder.Build();
var application = CreateBuilder(config).UseServer(this).Build();
var application = CreateBuilder(config).UseServer((IServerFactory)this).Build();
var env = application.Services.GetService<IHostingEnvironment>();
Assert.Equal("Staging", env.EnvironmentName);
}
@ -312,7 +313,7 @@ namespace Microsoft.AspNet.Hosting
.AddInMemoryCollection(vals);
var config = builder.Build();
var application = CreateBuilder(config).UseServer(this).Build();
var application = CreateBuilder(config).UseServer((IServerFactory)this).Build();
var env = application.Services.GetService<IHostingEnvironment>();
Assert.Equal(Path.GetFullPath("testroot"), env.WebRootPath);
Assert.True(env.WebRootFileProvider.GetFileInfo("TextFile.txt").Exists);
@ -321,9 +322,10 @@ namespace Microsoft.AspNet.Hosting
[Fact]
public void IsEnvironment_Extension_Is_Case_Insensitive()
{
var application = CreateBuilder().UseServer(this).Build();
using (application.Start())
var application = CreateBuilder().UseServer((IServerFactory)this).Build();
using (application)
{
application.Start();
var env = application.Services.GetRequiredService<IHostingEnvironment>();
Assert.True(env.IsEnvironment(EnvironmentName.Production));
Assert.True(env.IsEnvironment("producTion"));
@ -364,7 +366,7 @@ namespace Microsoft.AspNet.Hosting
var application = CreateApplication(requestDelegate);
// Act
var disposable = application.Start();
application.Start();
// Assert
Assert.NotNull(httpContext);
@ -388,7 +390,7 @@ namespace Microsoft.AspNet.Hosting
var application = CreateApplication(requestDelegate);
// Act
var disposable = application.Start();
application.Start();
// Assert
Assert.NotNull(httpContext);
@ -399,11 +401,12 @@ namespace Microsoft.AspNet.Hosting
public void WebApplication_InvokesConfigureMethodsOnlyOnce()
{
var application = CreateBuilder()
.UseServer(this)
.UseServer((IServerFactory)this)
.UseStartup<CountStartup>()
.Build();
using (application.Start())
using (application)
{
application.Start();
var services = application.Services;
var services2 = application.Services;
Assert.Equal(1, CountStartup.ConfigureCount);
@ -431,7 +434,7 @@ namespace Microsoft.AspNet.Hosting
public void WebApplication_ThrowsForBadConfigureServiceSignature()
{
var builder = CreateBuilder()
.UseServer(this)
.UseServer((IServerFactory)this)
.UseStartup<BadConfigureServicesStartup>();
var ex = Assert.Throws<InvalidOperationException>(() => builder.Build());
@ -447,7 +450,7 @@ namespace Microsoft.AspNet.Hosting
private IWebApplication CreateApplication(RequestDelegate requestDelegate)
{
var builder = CreateBuilder()
.UseServer(this)
.UseServer((IServerFactory)this)
.Configure(
appBuilder =>
{
@ -459,10 +462,11 @@ namespace Microsoft.AspNet.Hosting
private void RunMapPath(string virtualPath, string expectedSuffix)
{
var application = CreateBuilder().UseServer(this).Build();
var application = CreateBuilder().UseServer((IServerFactory)this).Build();
using (application.Start())
using (application)
{
application.Start();
var env = application.Services.GetRequiredService<IHostingEnvironment>();
// MapPath requires webroot to be set, we don't care
// about file provider so just set it here
@ -473,7 +477,7 @@ namespace Microsoft.AspNet.Hosting
}
}
private WebApplicationBuilder CreateBuilder(IConfiguration config = null)
private IWebApplicationBuilder CreateBuilder(IConfiguration config = null)
{
return new WebApplicationBuilder().UseConfiguration(config ?? new ConfigurationBuilder().Build()).UseStartup("Microsoft.AspNet.Hosting.Tests");
}