-
Notifications
You must be signed in to change notification settings - Fork 5
Description
The new recommend way to start an asp net core 2.0 app is as follows
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();If we take a look at CreateDefaultBuilder then we get
public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
var builder = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
if (env.IsDevelopment())
{
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
}
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.UseIISIntegration()
.UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
});
return builder;
}and Startup is now expected to look like this
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}Which causes problems for the TestEnvironment. Because the app is being setup outside Startup. Startup just adds a little flavor to the configuration it no longer creates/controls it.
Inside TestEnvironment we find CreateTestServer
protected virtual TestServer CreateTestServer()
{
return new TestServer
(
new WebHostBuilder()
.ConfigureStartup(new TStartupConfigurationService(), this.contentRootPath)
.UseStartup<TStartup>()
);
}The problem with this is that the new WebHostBuilder() should reflect the configuration inside Main.BuildWebHost().
I tried solving this by deriving from TestEnvironment
public class MyTestEnviornment<TStartup, TStartupConfigurationService> : TestEnvironment<TStartup, TStartupConfigurationService>
{
public MyTestEnviornment(string targetProjectRelativePath = null) : base(targetProjectRelativePath)
{
}
protected override TestServer CreateTestServer()
{
return new TestServer
(
new WebHostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
env.EnvironmentName = "Test";
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
if (env.IsDevelopment())
{
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
}
config.AddEnvironmentVariables();
})
.ConfigureStartup(new TStartupConfigurationService(), this.contentRootPath)
.UseStartup<TStartup>()
);
}
}But that has a bunch of problems. this.contentRootPath is private and therefore inaccessible to MyTestEnviornment. Also note I have to do env.EnvironmentName = "Test"; because the below haven't been called yet.
// defined in IStartupConfigurationService
public void ConfigureEnvironment(IHostingEnvironment env)
{
env.EnvironmentName = "Test";
}I haven't figured out a good way of solving this. We need a way to control what gets added to WebHostBuilder. So a wrapper comes to mind, but then the nice "add-in" feeling disappears :(