CalSync โ€” Automate Outlook Calendar Colors

Auto-color-code events for your team using rules. Faster visibility, less admin. 10-user minimum ยท 12-month term.

CalSync Colors is a service by CPI Consulting

In this blog post How to Use .NET appsettings.json for Cleaner Configuration we will explore how appsettings.json helps you manage configuration in modern .NET apps, without sprinkling values throughout your codebase. You will learn what it is, why it exists, and how to use it confidently in real-world projects.

At a high level, appsettings.json is the default place to store configuration values your application needs at runtime. Think connection strings, API endpoints, feature flags, logging levels, and service settings. The big win is separation of concerns: your code stays focused on behaviour, while configuration stays flexible and changeable across environments.

Under the hood, this is powered by the .NET configuration system and the generic host. .NET builds a configuration pipeline from one or more providers (JSON files, environment variables, command-line args, secret stores, and more). These providers are layered, so later sources can override earlier ones. That layering is what makes appsettings.json a good base configuration, while environment-specific or secret values can override it safely.

What is appsettings.json in .NET

appsettings.json is a JSON file typically located at the root of your project. By convention, it contains key-value pairs and nested sections. .NET loads it on startup and exposes values via IConfiguration. You can read config directly, or bind sections to typed options classes for safer, cleaner code.

Common uses include:

  • Application settings like AppName or DefaultLanguage
  • Service endpoints like BaseUrl or TimeoutSeconds
  • Logging configuration via the built-in logging providers
  • Connection strings (often overridden in production)
  • Feature toggles for controlled rollout

How the .NET configuration system works

The core technology is the Microsoft.Extensions.Configuration stack. In practical terms, it gives you:

  • Providers that load configuration from various sources (JSON, env vars, Azure Key Vault, etc.)
  • Binding that maps configuration sections to strongly typed classes
  • Reload support so changes can be detected (mostly useful in development or certain hosting scenarios)

In most modern .NET templates (ASP.NET Core and worker services), the host is created for you and configuration is wired up automatically. The default order is roughly:

  • appsettings.json
  • appsettings.{Environment}.json (for example, Development, Staging, Production)
  • User secrets (development only, when enabled)
  • Environment variables
  • Command-line arguments

The key takeaway is last one wins. If the same key exists in multiple sources, the value from the later source overrides earlier ones.

A solid starting appsettings.json

Here is a realistic example with a few common sections:

Notice the structure. Group related settings into sections so they stay readable and are easy to bind.

Environment-specific configuration with appsettings.Development.json

Most teams want different settings in development versus production. That is where environment-specific JSON files help.

Create an appsettings.Development.json like this:

Only include what changes. You do not need to duplicate every setting. The configuration system merges sections and applies overrides.

How .NET knows the environment

ASP.NET Core uses ASPNETCORE_ENVIRONMENT (and the generic host uses DOTNET_ENVIRONMENT) to decide which environment file to load. Typical values are Development, Staging, and Production.

Reading configuration with IConfiguration

For quick access, you can read values directly from IConfiguration. This is common in small apps or in glue code where binding might feel heavy.

The colon syntax (Section:SubSection:Key) is how nested JSON is addressed.

Preferred approach with strongly typed options

For most production code, binding configuration to a typed class makes your app safer and easier to maintain. You get autocomplete, compile-time checks, and one place to document the meaning of each setting.

Step 1 Create an options class

Step 2 Register it in Program.cs

If you want validation with attributes, add [Required] and other annotations to the properties, then keep ValidateDataAnnotations().

Step 3 Consume via IOptions or IOptionsMonitor

Use IOptionsMonitor<T> if you want to react to configuration changes at runtime (useful in some hosted scenarios). Most line-of-business apps are fine with IOptions<T>.

Connection strings and the ConnectionStrings section

.NET treats the ConnectionStrings section as a first-class convention. You can access it like any other value, or use helpers:

In production, prefer overriding connection strings using environment variables or a secret store, rather than committing real credentials into JSON files.

Overriding settings with environment variables

Environment variables are a common way to configure containers, CI/CD pipelines, and cloud services. .NET maps nested keys using double underscores.

For example, to override:

  • ExternalApis:Payments:BaseUrl

Set an environment variable named:

  • ExternalApis__Payments__BaseUrl

This plays nicely with Kubernetes, Azure App Service configuration, and most deployment tooling.

Secrets and what not to put in appsettings.json

A simple rule: if leaking a value would hurt you, do not store it in appsettings.json in source control. That includes:

  • Production database passwords
  • API keys and shared secrets
  • Client secrets for OAuth apps

Better options include:

  • User Secrets for local development
  • Environment variables for deployments
  • Managed secret stores like Azure Key Vault or AWS Secrets Manager

The nice part is you do not have to change your code much. You keep reading the same configuration keys, but the values come from a safer provider later in the pipeline.

Practical steps to structure appsettings.json well

  • Group by domain. Use sections like ExternalApis, Storage, Auth, FeatureFlags.
  • Keep names consistent. Pick a naming style and stick with it.
  • Prefer typed options for anything more than a couple of keys.
  • Use defaults carefully. Defaults are great for developer experience, but dangerous for security-sensitive settings.
  • Document intent. A short comment is not allowed in strict JSON, so consider documenting settings in code (options class) or in a README.

Common pitfalls and how to avoid them

Accidentally relying on the wrong environment

If ASPNETCORE_ENVIRONMENT is not what you think it is, the wrong file loads and values can surprise you. Make environment explicit in your deployment pipeline and verify it in logs at startup.

Storing secrets in JSON

This is the most frequent mistake. If you need local convenience, use user secrets. If you need production safety, use environment variables or a secret manager.

Using IConfiguration everywhere

It works, but it spreads configuration knowledge throughout your code. Typed options centralise it, make it testable, and reduce runtime errors.

Overly flat configuration

A long list of top-level keys gets messy quickly. Nest settings into sections that match how your system is organised.

A simple checklist for your next .NET project

  • Create a clean base appsettings.json with sensible defaults and no secrets.
  • Add appsettings.Development.json for local overrides.
  • Use environment variables or a secret store for production secrets.
  • Bind important sections to typed options classes.
  • Add validation so the app fails fast when configuration is missing or invalid.

Wrap up

appsettings.json is more than a convenient file in your project. It is the front door to the .NET configuration pipeline, designed to keep your code clean, your deployments flexible, and your environment differences manageable. With a solid structure, typed options, and safe overrides for secrets, you get configuration that supports growth rather than slowing it down.


Discover more from CPI Consulting -Specialist Azure Consultancy

Subscribe to get the latest posts sent to your email.