Fancy thing that ASP.NET Core supports is environment based application configuring on code level. We can write special methods to application start-up class and use default ones as fallbacks. This blog post shows how to write environment based configuring methods on ASP.NET Core.
Default configuring methods of start-up class
When we create new ASP.NET Core application then Startup class looks like this.
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework 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, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
ConfigureServices() method adds services to container and Configure() method configures request pipeline.
Configuring multiple environments
It’s possible we need to configure application based on environment where application is running. We may want to use some specific services and features in development mode and some others in release mode. One option is to use default configuring methods and #ifdef checks but these make our code look ugly.
ASP.NET Core allows us to define special versions of configuring methods:
- Configure<ENVIRONMENT>Services()
- Configure<ENVIORNMENT>()
where <ENVIRONMENT> is the name of environment where application runs. By example, with debug build we can use Development as environment name. It gives us the following two methods:
- ConfigureDevelopmentServices()
- ConfigureDevelopment()
Same way we can use Staging and Production as environment names. We can try out these methods with some lines of additional code.
public void ConfigureDevelopmentServices(IServiceCollection services)
{
Debug.WriteLine("ConfigureDevelopmentServices");
ConfigureServices(services);
}
public void ConfigureDevelopment(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
Debug.WriteLine("ConfigureDevelopment");
Configure(app, env, loggerFactory);
}
We can run application and check output in debug window or we can just use breakpoints to see application stopping on these when we run it.
Adding custom environments
It’s possible we need support for additional environments. Behind the curtains ASP.NET Core uses ASPNETCORE_ENVIRONMENT environment variable to find out what is the current environment. We can set value to this variable on Debug settings page of project properties.
And methods for environment called “Custom” are here:
public void ConfigureCustomServices(IServiceCollection services)
{
Debug.WriteLine("ConfigureCustomServices");
ConfigureServices(services);
}
public void ConfigureCustom(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
Debug.WriteLine("ConfigureCustom");
Configure(app, env, loggerFactory);
}
This way we can add methods for as many environments as we want.
Wrapping up
We can write configuration methods based on environment name and use default ones as fallbacks for other environments. This way we can avoid ugly code with many environment name checks. Environment name is held in ASPNETCORE_ENVIRONMENT variable and the value can be set on project properties page. Using environment based configuration methods we can keep code cleaner.