SlideShare a Scribd company logo
.NET Core: Configuration
Fundamentals
David Dieruf - Pivotal
July, 2019
Let's Talk About...
Cloud-native environment and goals
Why we are here
Designing config and environment variables
Different patterns
About .NET Core configuration
Building config providers in WebHost and its hierarchy of values
The options pattern
Extending basic config with objects
External configuration servers
How they work and why you choose them
Putting the pieces together
Using Steeltoe and Spring Config to reach cloud-native goals
Environment: Local
Network
Services: DB, Cache, SMB
Environment: Stage Environment: Prod
Team Foundation Server (CI/CD): Git, Build, Release
My-App
Network
Services: DB, Cache, SMB
Network
Services: DB, Cache, SMB
My-App My-App
- One build
- Test once (for all environments)
- Parity between environments
- Automation
My-App My-App
public void ConfigureServices(IServiceCollection services) {
String connString = Environment.GetEnvironmentVariable("conn_string");
services.AddDbContext<MyContext>(options => options.UseSqlServer(connString));
}
Environment variables in the cloud
How is the value set?
Do you have to manually update the value per
instance, or script the action?
How easy is promotion?
Do you have to recompile to move between
environments? Does your build pipeline manipulate
settings?
Do you have a history of changes?
Do you know when a value was set and by who?
Atomic value in the
cloud
Per app instance
App can not run without
a value
Agnostic to its platform
or IaaS (portable)
Appsettings.json
● [Good] External to the
compiled application
● [Good] No recompilation
needed
● [Challenge] Have to change
at every instance
Internal Class Command Line
● [Good] Secure information
in compiled bits
● [Challenge] Hard coded
values in app
● [Challenge] Can not change
without recompiling
● [Good] External to the
compiled application
● [Challenge] Have to change
at every instance
● [Challenge] Lost values
because no source check-in
(Manual)
Environment Variables
Popular Configuration Design
● [Good] External to the
compiled application
● [Good] Application
compiled once and
promoted through
environment
● [Challenge] Have to change
at every host
class MyClass {
string connString = "xxxx"
}
{
"ConnectionStrings": {
"a-database": "xxxxx"
}
}
C: dotnet run my-app `
--conn "xxxx" `
--something "yyyyy"
string connString =
Environment.GetEnvironmentVari
able("my-conn")
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
.NET Core Configuration
Using Default
WebHost
Loading configuration into your app
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
- use Kestrel as the web server and configure it using the
application's configuration providers
- set the ContentRootPath to the result of GetCurrentDirectory()
- load IConfiguration from 'appsettings.json' and
'appsettings.[EnvironmentName].json'
- load IConfiguration from User Secrets when EnvironmentName
is 'Development' using the entry assembly
- load IConfiguration from environment variables
- load IConfiguration from supplied command line args
- configure the ILoggerFactory to log to the console and debug
output
- enable IIS integration
program.cs
WebHost.CreateDefaultBuilder(args)
Build your own
WebHost
Loading configuration into your app
public static IWebHost BuildWebHost(string[] args) {
var builder = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) => {
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true);
config.AddEnvironmentVariables();
config.AddCommandLine(args);
})
.UseIISIntegration()
.UseStartup<Startup>();
return builder.Build();
}
program.cs
- Options manipulate how configuration values are overwritten
- Options to [not] include other configuration providers, like
custom external config server provider
var builder = new WebHostBuilder()
Config value
hierarchy
Overwrite values based on
environment
public static IWebHost BuildWebHost(string[] args) {
var builder = new WebHostBuilder()
...
.ConfigureAppConfiguration((hostingContext, config) => {
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json");
config.AddEnvironmentVariables();
config.AddCommandLine(args);
})
...
1. Load values from appsettings.json
2. (if provided) Load values from environment
specific appsettings.{env}.json
3. (if present) Load values from environment
variables
4. (if present) Load values provided when app
was started
config.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json");
config.AddEnvironmentVariables();
config.AddCommandLine(args);
{
"my_val": "something"
}
Example Value Overwriting
1. config.AddJsonFile("appsettings.json")
{
"my_val": "another"
}
2. .AddJsonFile("appsettings.staging.json")
PS c: $env:my_val = "yet another"
3. config.AddEnvironmentVariables()
PS c: dotnet run my-app --my_val "again another"
4. config.AddCommandLine(args)
my_val == “again another”
Configuration
Providers
Supported providers for
configuration of ASP.NET core app
Provider
Provides configuration
from…
Azure Key Vault Configuration Provider (Security topics) Azure Key Vault
Azure App Configuration Provider (Azure documentation) Azure App Configuration
Command-line Configuration Provider Command-line parameters
Custom configuration provider Custom source
Environment Variables Configuration Provider Environment variables
File Configuration Provider Files (INI, JSON, XML)
Key-per-file Configuration Provider Directory files
Memory Configuration Provider In-memory collections
User secrets (Secret Manager) (Security topics) File in the user profile directory
Consuming
Values
Using
Microsoft.Extensions.Configuration
public class ValuesController : Controller{
private readonly IConfiguration _config;
public ValuesController(IConfiguration config){
_config = config;
}
[HttpGet]
public ActionResult<string> Get(){
string val = _config.GetValue<string>("my_val");
return val;
}
}
- No consideration for handler type(s)
- Simple key:value store
- Can be complex type
ValuesController.cs
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options
Options Pattern
Options Pattern Using Microsoft.Extensions.Configuration.Options
{
"section0": {
"key0": "value",
"key1": "value"
},
"section1": {
"key0": "value",
"key1": "value"
}
}
public void ConfigureServices(IServiceCollection services) {
services.AddOptions();
services.Configure<SectionZeroOptions>(Configuration.GetSection("section0"));
...
}
public class SectionZeroOptions {
public string key0 {get;set;}
public string key1 { get; set; }
}
public class MyService : IMyService {
private IOptions<SectionZeroOptions> _SectionZeroOptions;
public MyService(IOptions<SectionZeroOptions> sectionZeroOptions) {
_SectionZeroOptions = sectionZeroOptions;
}
public string DoSomething(){
string key0 = _SectionZeroOptions.Value.key0;
string key1 = _SectionZeroOptions.Value.key1;
return key0;
}
}
1. appsettings.json values
2. Matching class to json
3. Enable the Options configuration
4. Consume values
{
"section0": {
"key0": "value",
"key1": "value"
},
"section1": {
"key0": "value",
"key1": "value"
}
}
public class SectionZeroOptions {
public string key0 {get;set;}
public string key1 { get; set; }
}
public void ConfigureServices(IServiceCollection services) {
services.AddOptions();
services.Configure<SectionZeroOptions>(Configuration.GetSection("section0"));
...
}
public class MyService : IMyService {
private IOptions<SectionZeroOptions> _SectionZeroOptions;
public MyService(IOptions<SectionZeroOptions> sectionZeroOptions) {
_SectionZeroOptions = sectionZeroOptions;
}
public string DoSomething(){
string key0 = _SectionZeroOptions.Value.key0;
string key1 = _SectionZeroOptions.Value.key1;
return key0;
}
}
Business Case using options pattern
You have an api that is responsible for approving loans. There are
business rules within the app that need to be applied, to decide
approval. One of those rules compares the loan amount being asked
for, to a max loan amount the business is willing to approve. The max
amount changes throughout the year based on other events.
Place the max approval amount (integer) in an external config and give
yourself the flexibility to change values at any moment, with no
downtime.
External Configuration Server
Custom configuration provider
About Config
Server
At boot time…
➔ Platform puts values in environment variables
➔ Client looks for server
➔ Client gets config by NAME
➔ Config organised by PROFILE
At runtime...
➔ Config can be refreshed live
➔ Call /actuator/refresh
➔ Values get reloaded
➔ No need for restart!
Environment: Stage Environment: ProdEnvironment: Local
Network
Services: DB, Cache, SMB
Team Foundation Server (CI/CD): Git, Build, Release
Network
Services: DB, Cache, SMB
Network
Services: DB, Cache, SMB
Config Server: development.yml, staging.yml, production.yml
string connString = Environment.GetEnvironmentVariable("conn_string");
string configUri = Environment.GetEnvironmentVariable("config_uri");
Simplicity vs Flexibility
External configuration can be challenging in itself It offers so much
design options that things can get out of hand quickly. Use the domain
around you to decide how far to go.
Config First Approach
Don’t hold anything in your appsettings.json, only a pointer to the
config server. Everything is filled from there.
Steeltoe and Spring Config
Putting the pieces together
2. Set the application Name (in appsettings.json)...
Setup Configuration Client: .NET / Steeltoe / Spring Config
4. Include the custom config provider...
1: Add the dependencies...
(Steeltoe for Pivotal Spring Cloud Config Client)
3. Add your external configuration (in Git)...
"spring": {
"application": { "name": "loan-application-service" },
"cloud": {
"config": {
"uri": "http://10.0.7.254:8888",
"validate_certificates": false,
"fail_fast": true
...
<PackageReference
Include="Steeltoe.Extensions.Configuration.ConfigServerCore" ... />
public void ConfigureServices(IServiceCollection services){
services.AddOptions();
services.Configure<Services.SomeValuesOptions>
(Configuration.GetSection("SomeValues"));
services.AddMvc();
...
}
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>{
ILoggerFactory fac = GetLoggerFactory(hostingContext.HostingEnvironment);
var env = hostingContext.HostingEnvironment;
config.AddConfigServer(env, fac);
})
...
public class SomeValuesOptions {
public string scheme { get; set; }
public string address { get; set; }
}
program.cs
startup.cs
config options pattern
Logging:
IncludeScopes: false
Debug:
LogLevel:
Default: Information
SomeValues:
scheme: https
address: www.pivotal.io
5. Retrieve values and map to class...
<PackageReference
Include="Steeltoe.Extensions.Configuration.ConfigServerCore" ... />
"spring": {
"application": { "name": "loan-application-service" },
"cloud": {
"config": {
"uri": "http://127.0.0.1:8888",
"validate_certificates": false,
"fail_fast": true
...
Logging:
IncludeScopes: false
Debug:
LogLevel:
Default: Information
SomeValues:
scheme: https
address: www.pivotal.io
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>{
ILoggerFactory fac = GetLoggerFactory(hostingContext.HostingEnvironment);
var env = hostingContext.HostingEnvironment;
config.AddConfigServer(env, fac);
})
...
public void ConfigureServices(IServiceCollection services){
services.AddOptions();
services.Configure<Services.SomeValuesOptions>
(Configuration.GetSection("SomeValues"));
services.AddMvc();
...
}
public class SomeValuesOptions {
public string scheme { get; set; }
public string address { get; set; }
}
"name": "loan-application-service"
config.AddConfigServer(env, fac);
"uri": "http://127.0.0.1:8888"
© Copyright 2019 Pivotal Software, Inc. All rights Reserved.
Learn More.
Become a cloud-native .NET rock star
https://springoneplatform.io/2019/training
Pivotal Platform Acceleration Lab for Developers (.NET)
Experience best practices building cloud-native applications in
a hands-on setting with Pivotal educators and consultants. The
program is focused on enabling customers and partners
through “doing it” rather than “talking about it”.
https://pivotal.io/platform-acceleration-lab
© Copyright 2019 Pivotal Software, Inc. All rights Reserved.
Questions?
Thank you
Refreshing
Values
- Optionally provide an environment specific
json config
Startup.cs
public static IWebHost BuildWebHost(string[] args) {
var builder = new WebHostBuilder()
...
.ConfigureAppConfiguration((hostingContext, config) => {
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json",
reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
config.AddCommandLine(args);
})
...
Optional
providers
- Optionally provide an environment specific
json config
Startup.cs
public static IWebHost BuildWebHost(string[] args) {
var builder = new WebHostBuilder()
...
.ConfigureAppConfiguration((hostingContext, config) => {
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true);
config.AddEnvironmentVariables();
config.AddCommandLine(args);
})
...

More Related Content

PDF
High-Performance JDBC Voxxed Bucharest 2016
PDF
High Performance Hibernate JavaZone 2016
PDF
High-Performance Hibernate - JDK.io 2018
PDF
Hybrid Cloud PHPUK2012
PPTX
Hazelcast and MongoDB at Cloud CMS
PDF
Hazelcast
PDF
Writing RESTful web services using Node.js
PDF
JPA and Hibernate Performance Tips
High-Performance JDBC Voxxed Bucharest 2016
High Performance Hibernate JavaZone 2016
High-Performance Hibernate - JDK.io 2018
Hybrid Cloud PHPUK2012
Hazelcast and MongoDB at Cloud CMS
Hazelcast
Writing RESTful web services using Node.js
JPA and Hibernate Performance Tips

What's hot (19)

PDF
Developing For The Windows Azure Platform
PPTX
CloudStack Meetup London - Primary Storage Presentation by SolidFire
PDF
BeJUG Meetup - What's coming in the OSGi R7 Specification
PPTX
Play + scala + reactive mongo
PDF
Couchbase Performance Benchmarking
PPTX
Kåre Rude Andersen - Be a hero – optimize scom and present your services
PDF
Practicing Continuous Deployment
PPTX
Securing MongoDB to Serve an AWS-Based, Multi-Tenant, Security-Fanatic SaaS A...
PDF
High-Performance Hibernate Devoxx France 2016
PPTX
Azure Table Storage: The Good, the Bad, the Ugly (15 min. lightning talk)
PPTX
CUBRID Inside - Architecture, Source & Management Components
PPTX
BASTA 2013: Custom OData Provider
PPT
Multi-tenancy with Rails
PDF
Language enhancements in cold fusion 11
PPTX
Windows Azure HDInsight Service
PPTX
Growing in the Wild. The story by CUBRID Database Developers.
PDF
Keystone deep dive 1
PPTX
Azure Data Storage
PDF
Cassandra 3.0 Data Modeling
Developing For The Windows Azure Platform
CloudStack Meetup London - Primary Storage Presentation by SolidFire
BeJUG Meetup - What's coming in the OSGi R7 Specification
Play + scala + reactive mongo
Couchbase Performance Benchmarking
Kåre Rude Andersen - Be a hero – optimize scom and present your services
Practicing Continuous Deployment
Securing MongoDB to Serve an AWS-Based, Multi-Tenant, Security-Fanatic SaaS A...
High-Performance Hibernate Devoxx France 2016
Azure Table Storage: The Good, the Bad, the Ugly (15 min. lightning talk)
CUBRID Inside - Architecture, Source & Management Components
BASTA 2013: Custom OData Provider
Multi-tenancy with Rails
Language enhancements in cold fusion 11
Windows Azure HDInsight Service
Growing in the Wild. The story by CUBRID Database Developers.
Keystone deep dive 1
Azure Data Storage
Cassandra 3.0 Data Modeling
Ad

Similar to Learn Cloud-Native .NET: Core Configuration Fundamentals with Steeltoe (20)

PPTX
Spring cloud config
PDF
quickguide-einnovator-8-spring-cloud
PDF
.NET Core, ASP.NET Core Course, Session 8
PPTX
Deploying windows containers with kubernetes
PPTX
Dive into DevOps | March, Building with Terraform, Volodymyr Tsap
PPTX
Go (con)figure - Making sense of .NET configuration
PPT
Spring and Cloud Foundry; a Marriage Made in Heaven
PDF
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
PDF
How to build a Citrix infrastructure on AWS
PDF
Easy integration of Bluemix services with your applications
PDF
Priming Your Teams For Microservice Deployment to the Cloud
PDF
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
PDF
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
PPTX
Decomposing the Monolith using modern-day .NET and a touch of microservices
PDF
"How to create an infrastructure in .NET", Leonid Chetverikov
PPT
2310 b 15
PPT
2310 b 15
PDF
Case Study _Cloud Native Transformation Deploying Integration workloads to AK...
PDF
C fowler azure-dojo
PPTX
MS Cloud Day - Deploying and monitoring windows azure applications
Spring cloud config
quickguide-einnovator-8-spring-cloud
.NET Core, ASP.NET Core Course, Session 8
Deploying windows containers with kubernetes
Dive into DevOps | March, Building with Terraform, Volodymyr Tsap
Go (con)figure - Making sense of .NET configuration
Spring and Cloud Foundry; a Marriage Made in Heaven
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
How to build a Citrix infrastructure on AWS
Easy integration of Bluemix services with your applications
Priming Your Teams For Microservice Deployment to the Cloud
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
Decomposing the Monolith using modern-day .NET and a touch of microservices
"How to create an infrastructure in .NET", Leonid Chetverikov
2310 b 15
2310 b 15
Case Study _Cloud Native Transformation Deploying Integration workloads to AK...
C fowler azure-dojo
MS Cloud Day - Deploying and monitoring windows azure applications
Ad

More from VMware Tanzu (20)

PDF
Spring into AI presented by Dan Vega 5/14
PDF
What AI Means For Your Product Strategy And What To Do About It
PDF
Make the Right Thing the Obvious Thing at Cardinal Health 2023
PPTX
Enhancing DevEx and Simplifying Operations at Scale
PDF
Spring Update | July 2023
PPTX
Platforms, Platform Engineering, & Platform as a Product
PPTX
Building Cloud Ready Apps
PDF
Spring Boot 3 And Beyond
PDF
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
PDF
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
PDF
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
PPTX
tanzu_developer_connect.pptx
PDF
Tanzu Virtual Developer Connect Workshop - French
PDF
Tanzu Developer Connect Workshop - English
PDF
Virtual Developer Connect Workshop - English
PDF
Tanzu Developer Connect - French
PDF
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
PDF
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
PDF
SpringOne Tour: The Influential Software Engineer
PDF
SpringOne Tour: Domain-Driven Design: Theory vs Practice
Spring into AI presented by Dan Vega 5/14
What AI Means For Your Product Strategy And What To Do About It
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Enhancing DevEx and Simplifying Operations at Scale
Spring Update | July 2023
Platforms, Platform Engineering, & Platform as a Product
Building Cloud Ready Apps
Spring Boot 3 And Beyond
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
tanzu_developer_connect.pptx
Tanzu Virtual Developer Connect Workshop - French
Tanzu Developer Connect Workshop - English
Virtual Developer Connect Workshop - English
Tanzu Developer Connect - French
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: Domain-Driven Design: Theory vs Practice

Recently uploaded (20)

PPTX
Spectroscopy.pptx food analysis technology
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
Big Data Technologies - Introduction.pptx
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Approach and Philosophy of On baking technology
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Electronic commerce courselecture one. Pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
Machine Learning_overview_presentation.pptx
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
A Presentation on Artificial Intelligence
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
cuic standard and advanced reporting.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Spectroscopy.pptx food analysis technology
sap open course for s4hana steps from ECC to s4
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
MYSQL Presentation for SQL database connectivity
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Big Data Technologies - Introduction.pptx
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Approach and Philosophy of On baking technology
Encapsulation_ Review paper, used for researhc scholars
Electronic commerce courselecture one. Pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Machine Learning_overview_presentation.pptx
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Mobile App Security Testing_ A Comprehensive Guide.pdf
A Presentation on Artificial Intelligence
Review of recent advances in non-invasive hemoglobin estimation
cuic standard and advanced reporting.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
gpt5_lecture_notes_comprehensive_20250812015547.pdf

Learn Cloud-Native .NET: Core Configuration Fundamentals with Steeltoe

  • 1. .NET Core: Configuration Fundamentals David Dieruf - Pivotal July, 2019
  • 2. Let's Talk About... Cloud-native environment and goals Why we are here Designing config and environment variables Different patterns About .NET Core configuration Building config providers in WebHost and its hierarchy of values The options pattern Extending basic config with objects External configuration servers How they work and why you choose them Putting the pieces together Using Steeltoe and Spring Config to reach cloud-native goals
  • 3. Environment: Local Network Services: DB, Cache, SMB Environment: Stage Environment: Prod Team Foundation Server (CI/CD): Git, Build, Release My-App Network Services: DB, Cache, SMB Network Services: DB, Cache, SMB My-App My-App - One build - Test once (for all environments) - Parity between environments - Automation My-App My-App public void ConfigureServices(IServiceCollection services) { String connString = Environment.GetEnvironmentVariable("conn_string"); services.AddDbContext<MyContext>(options => options.UseSqlServer(connString)); }
  • 4. Environment variables in the cloud How is the value set? Do you have to manually update the value per instance, or script the action? How easy is promotion? Do you have to recompile to move between environments? Does your build pipeline manipulate settings? Do you have a history of changes? Do you know when a value was set and by who? Atomic value in the cloud Per app instance App can not run without a value Agnostic to its platform or IaaS (portable)
  • 5. Appsettings.json ● [Good] External to the compiled application ● [Good] No recompilation needed ● [Challenge] Have to change at every instance Internal Class Command Line ● [Good] Secure information in compiled bits ● [Challenge] Hard coded values in app ● [Challenge] Can not change without recompiling ● [Good] External to the compiled application ● [Challenge] Have to change at every instance ● [Challenge] Lost values because no source check-in (Manual) Environment Variables Popular Configuration Design ● [Good] External to the compiled application ● [Good] Application compiled once and promoted through environment ● [Challenge] Have to change at every host class MyClass { string connString = "xxxx" } { "ConnectionStrings": { "a-database": "xxxxx" } } C: dotnet run my-app ` --conn "xxxx" ` --something "yyyyy" string connString = Environment.GetEnvironmentVari able("my-conn")
  • 7. Using Default WebHost Loading configuration into your app public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); - use Kestrel as the web server and configure it using the application's configuration providers - set the ContentRootPath to the result of GetCurrentDirectory() - load IConfiguration from 'appsettings.json' and 'appsettings.[EnvironmentName].json' - load IConfiguration from User Secrets when EnvironmentName is 'Development' using the entry assembly - load IConfiguration from environment variables - load IConfiguration from supplied command line args - configure the ILoggerFactory to log to the console and debug output - enable IIS integration program.cs WebHost.CreateDefaultBuilder(args)
  • 8. Build your own WebHost Loading configuration into your app public static IWebHost BuildWebHost(string[] args) { var builder = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); config.AddEnvironmentVariables(); config.AddCommandLine(args); }) .UseIISIntegration() .UseStartup<Startup>(); return builder.Build(); } program.cs - Options manipulate how configuration values are overwritten - Options to [not] include other configuration providers, like custom external config server provider var builder = new WebHostBuilder()
  • 9. Config value hierarchy Overwrite values based on environment public static IWebHost BuildWebHost(string[] args) { var builder = new WebHostBuilder() ... .ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json"); config.AddEnvironmentVariables(); config.AddCommandLine(args); }) ... 1. Load values from appsettings.json 2. (if provided) Load values from environment specific appsettings.{env}.json 3. (if present) Load values from environment variables 4. (if present) Load values provided when app was started config.AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json"); config.AddEnvironmentVariables(); config.AddCommandLine(args);
  • 10. { "my_val": "something" } Example Value Overwriting 1. config.AddJsonFile("appsettings.json") { "my_val": "another" } 2. .AddJsonFile("appsettings.staging.json") PS c: $env:my_val = "yet another" 3. config.AddEnvironmentVariables() PS c: dotnet run my-app --my_val "again another" 4. config.AddCommandLine(args) my_val == “again another”
  • 11. Configuration Providers Supported providers for configuration of ASP.NET core app Provider Provides configuration from… Azure Key Vault Configuration Provider (Security topics) Azure Key Vault Azure App Configuration Provider (Azure documentation) Azure App Configuration Command-line Configuration Provider Command-line parameters Custom configuration provider Custom source Environment Variables Configuration Provider Environment variables File Configuration Provider Files (INI, JSON, XML) Key-per-file Configuration Provider Directory files Memory Configuration Provider In-memory collections User secrets (Secret Manager) (Security topics) File in the user profile directory
  • 12. Consuming Values Using Microsoft.Extensions.Configuration public class ValuesController : Controller{ private readonly IConfiguration _config; public ValuesController(IConfiguration config){ _config = config; } [HttpGet] public ActionResult<string> Get(){ string val = _config.GetValue<string>("my_val"); return val; } } - No consideration for handler type(s) - Simple key:value store - Can be complex type ValuesController.cs
  • 14. Options Pattern Using Microsoft.Extensions.Configuration.Options { "section0": { "key0": "value", "key1": "value" }, "section1": { "key0": "value", "key1": "value" } } public void ConfigureServices(IServiceCollection services) { services.AddOptions(); services.Configure<SectionZeroOptions>(Configuration.GetSection("section0")); ... } public class SectionZeroOptions { public string key0 {get;set;} public string key1 { get; set; } } public class MyService : IMyService { private IOptions<SectionZeroOptions> _SectionZeroOptions; public MyService(IOptions<SectionZeroOptions> sectionZeroOptions) { _SectionZeroOptions = sectionZeroOptions; } public string DoSomething(){ string key0 = _SectionZeroOptions.Value.key0; string key1 = _SectionZeroOptions.Value.key1; return key0; } } 1. appsettings.json values 2. Matching class to json 3. Enable the Options configuration 4. Consume values { "section0": { "key0": "value", "key1": "value" }, "section1": { "key0": "value", "key1": "value" } } public class SectionZeroOptions { public string key0 {get;set;} public string key1 { get; set; } } public void ConfigureServices(IServiceCollection services) { services.AddOptions(); services.Configure<SectionZeroOptions>(Configuration.GetSection("section0")); ... } public class MyService : IMyService { private IOptions<SectionZeroOptions> _SectionZeroOptions; public MyService(IOptions<SectionZeroOptions> sectionZeroOptions) { _SectionZeroOptions = sectionZeroOptions; } public string DoSomething(){ string key0 = _SectionZeroOptions.Value.key0; string key1 = _SectionZeroOptions.Value.key1; return key0; } }
  • 15. Business Case using options pattern You have an api that is responsible for approving loans. There are business rules within the app that need to be applied, to decide approval. One of those rules compares the loan amount being asked for, to a max loan amount the business is willing to approve. The max amount changes throughout the year based on other events. Place the max approval amount (integer) in an external config and give yourself the flexibility to change values at any moment, with no downtime.
  • 16. External Configuration Server Custom configuration provider
  • 17. About Config Server At boot time… ➔ Platform puts values in environment variables ➔ Client looks for server ➔ Client gets config by NAME ➔ Config organised by PROFILE At runtime... ➔ Config can be refreshed live ➔ Call /actuator/refresh ➔ Values get reloaded ➔ No need for restart!
  • 18. Environment: Stage Environment: ProdEnvironment: Local Network Services: DB, Cache, SMB Team Foundation Server (CI/CD): Git, Build, Release Network Services: DB, Cache, SMB Network Services: DB, Cache, SMB Config Server: development.yml, staging.yml, production.yml string connString = Environment.GetEnvironmentVariable("conn_string"); string configUri = Environment.GetEnvironmentVariable("config_uri");
  • 19. Simplicity vs Flexibility External configuration can be challenging in itself It offers so much design options that things can get out of hand quickly. Use the domain around you to decide how far to go. Config First Approach Don’t hold anything in your appsettings.json, only a pointer to the config server. Everything is filled from there.
  • 20. Steeltoe and Spring Config Putting the pieces together
  • 21. 2. Set the application Name (in appsettings.json)... Setup Configuration Client: .NET / Steeltoe / Spring Config 4. Include the custom config provider... 1: Add the dependencies... (Steeltoe for Pivotal Spring Cloud Config Client) 3. Add your external configuration (in Git)... "spring": { "application": { "name": "loan-application-service" }, "cloud": { "config": { "uri": "http://10.0.7.254:8888", "validate_certificates": false, "fail_fast": true ... <PackageReference Include="Steeltoe.Extensions.Configuration.ConfigServerCore" ... /> public void ConfigureServices(IServiceCollection services){ services.AddOptions(); services.Configure<Services.SomeValuesOptions> (Configuration.GetSection("SomeValues")); services.AddMvc(); ... } WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) =>{ ILoggerFactory fac = GetLoggerFactory(hostingContext.HostingEnvironment); var env = hostingContext.HostingEnvironment; config.AddConfigServer(env, fac); }) ... public class SomeValuesOptions { public string scheme { get; set; } public string address { get; set; } } program.cs startup.cs config options pattern Logging: IncludeScopes: false Debug: LogLevel: Default: Information SomeValues: scheme: https address: www.pivotal.io 5. Retrieve values and map to class... <PackageReference Include="Steeltoe.Extensions.Configuration.ConfigServerCore" ... /> "spring": { "application": { "name": "loan-application-service" }, "cloud": { "config": { "uri": "http://127.0.0.1:8888", "validate_certificates": false, "fail_fast": true ... Logging: IncludeScopes: false Debug: LogLevel: Default: Information SomeValues: scheme: https address: www.pivotal.io WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) =>{ ILoggerFactory fac = GetLoggerFactory(hostingContext.HostingEnvironment); var env = hostingContext.HostingEnvironment; config.AddConfigServer(env, fac); }) ... public void ConfigureServices(IServiceCollection services){ services.AddOptions(); services.Configure<Services.SomeValuesOptions> (Configuration.GetSection("SomeValues")); services.AddMvc(); ... } public class SomeValuesOptions { public string scheme { get; set; } public string address { get; set; } } "name": "loan-application-service" config.AddConfigServer(env, fac); "uri": "http://127.0.0.1:8888"
  • 22. © Copyright 2019 Pivotal Software, Inc. All rights Reserved. Learn More. Become a cloud-native .NET rock star https://springoneplatform.io/2019/training Pivotal Platform Acceleration Lab for Developers (.NET) Experience best practices building cloud-native applications in a hands-on setting with Pivotal educators and consultants. The program is focused on enabling customers and partners through “doing it” rather than “talking about it”. https://pivotal.io/platform-acceleration-lab
  • 23. © Copyright 2019 Pivotal Software, Inc. All rights Reserved. Questions? Thank you
  • 24. Refreshing Values - Optionally provide an environment specific json config Startup.cs public static IWebHost BuildWebHost(string[] args) { var builder = new WebHostBuilder() ... .ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); config.AddEnvironmentVariables(); config.AddCommandLine(args); }) ...
  • 25. Optional providers - Optionally provide an environment specific json config Startup.cs public static IWebHost BuildWebHost(string[] args) { var builder = new WebHostBuilder() ... .ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); config.AddEnvironmentVariables(); config.AddCommandLine(args); }) ...