← Back to list

Using appsettings.json in Modern .NET WPF Applications

Modern WPF config with appsettings.json, Dependency Injection, environments, and live reload

Ed Curtin · 2026-02-26 03:18 · 2 claps · 2.6 min read
#settings #wpf #ioc #dependency-injection
Open on Medium ↗

Using appsettings.json in Modern .NET WPF Applications

Modern WPF applications built on .NET (Core/5/6/7/8+) can fully leverage the same configuration infrastructure used in ASP.NET Core. By using the Generic Host, you gain access to:

  • appsettings.json
  • Environment-specific configuration
  • Dependency Injection
  • Logging (e.g., Serilog)
  • Configuration reload on change

This article explains how appsettings.json works in modern WPF applications and how to configure it properly using Host.CreateDefaultBuilder().

Why Use the Generic Host in WPF?

Traditionally, WPF relied on App.config. However, with modern .NET, we can use:

  • Microsoft.Extensions.Hosting
  • Microsoft.Extensions.Configuration
  • Microsoft.Extensions.DependencyInjection

This provides a consistent configuration model across:

  • WPF
  • ASP.NET Core
  • Worker Services
  • Console apps

The result is a cleaner, more maintainable architecture.

Setting Up the Host in WPF

A modern WPF App.xaml.cs typically initializes the host like this:

var appSettingsJson = "appsettings.json";
var appSettingsEnvironmentJson = "appsettings.{0}.json";

_host = Host.CreateDefaultBuilder()
    .UseSerilog()
    .ConfigureAppConfiguration((context, config) =>
    {
        config.SetBasePath(Directory.GetCurrentDirectory());
        config.AddJsonFile(appSettingsJson, optional: false, reloadOnChange: true);
        config.AddJsonFile(
            string.Format(appSettingsEnvironmentJson, context.HostingEnvironment.EnvironmentName),
            optional: true,
            reloadOnChange: true);
        config.AddEnvironmentVariables();
    })
    .ConfigureServices(ConfigureServices)
    .Build();
services.Configure<AppSettings>(
   context.Configuration.GetSection(nameof(AppSettings)));

Let’s break this down.

What Host.CreateDefaultBuilder() Provides

Host.CreateDefaultBuilder() automatically adds:

  • appsettings.json
  • appsettings.{Environment}.json
  • Environment variables
  • Command-line arguments
  • Logging configuration

It also sets the environment from:

DOTNET_ENVIRONMENT

or

ASPNETCORE_ENVIRONMENT

Even in WPF applications.

The Role of appsettings.json

appsettings.json is your main configuration file.

Example:

{
  "AppSettings": {
    "Application": {
      "Name": "My WPF App",
      "Version": "1.0.0"
    },
    "ConnectionStrings": {
      "DefaultConnection": "Server=.;Database=AppDb;Trusted_Connection=True;"
    },
    "Serilog": {
      "MinimumLevel": "Information",
      "WriteTo": [
        {
          "Name": "File",
          "Args": {
            "path": "logs/log.txt",
            "rollingInterval": "Day"
          }
        }
      ]
    }
  }
}

Environment-Specific Configuration

Your code supports environment-based configuration:

config.AddJsonFile(
    string.Format(appSettingsEnvironmentJson, context.HostingEnvironment.EnvironmentName),
    optional: true,
    reloadOnChange: true);

This enables files like:

  • appsettings.Development.json
  • appsettings.Staging.json
  • appsettings.Production.json

Example:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=DEVSERVER;Database=DevDb;"
  }
}

The environment-specific file overrides values from appsettings.json.

Configuration Reload on Change

Notice:

reloadOnChange: true

This enables live reload when the JSON file changes.

You can combine this with:

IOptionsMonitor<T>

to react to changes dynamically in your WPF UI without restarting the application.

Strongly Typed Configuration (Best Practice)

Instead of reading configuration manually, use strongly typed settings.

1️⃣ Create a Settings Class

public class AppSettings
{
    public string Name { get; set; }
    public string Version { get; set; }
}

2️⃣ Register It

Inside ConfigureServices:

services.Configure<AppSettings>(
    configuration.GetSection(nameof(AppSettings)));

3️⃣ Inject It

public class MainViewModel
{
    private readonly AppSettings _settings;

    public MainViewModel(IOptions<AppSettings> options)
    {
        _settings = options.Value;
    }
}

This keeps your application clean and maintainable.

Using Serilog with appsettings.json

When using:

.UseSerilog()

Serilog can read configuration directly from appsettings.json.

Example:

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

This keeps logging configuration centralized and environment-aware.

Folder Structure Recommendation

/MyWpfApp
 ├── App.xaml
 ├── App.xaml.cs
 ├── appsettings.json
 ├── appsettings.Development.json
 ├── ViewModels/
 ├── Services/

Make sure:

  • appsettings.json → Copy to Output Directory = Copy if newer

Configuration Sources Order (Important)

Configuration is applied in order, and later sources override earlier ones:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Environment variables
  4. Command-line arguments

Environment variables always win.

When to Use SetBasePath

config.SetBasePath(Directory.GetCurrentDirectory());

This ensures the configuration system looks in the correct directory when running:

  • From Visual Studio
  • From published folder
  • From Windows Service mode

In many cases, CreateDefaultBuilder() already handles this, but explicitly setting it ensures predictable behavior in desktop apps.

Accessing Configuration Anywhere

You can inject:

IConfiguration

or better:

IOptions<T>
IOptionsMonitor<T>

Avoid directly calling:

configuration["SomeKey"]

except in infrastructure code.

Common Pitfalls

  • Forgetting to copy appsettings.json to output
  • Hardcoding environment names
  • Not using strongly typed options
  • Not enabling reload when required
  • Mixing configuration logic inside ViewModels

Benefits of Using appsettings.json in WPF

  • Centralized configuration
  • Environment support
  • Clean separation of concerns
  • Logging integration
  • Dependency Injection compatibility
  • Live reload support
  • Enterprise-ready architecture

Final Thoughts

Modern WPF applications built on the Generic Host bring desktop development closer to ASP.NET Core architecture standards. By leveraging appsettings.json, environment-specific configuration, and dependency injection, you create scalable, maintainable, and testable desktop applications.

If you’re building enterprise-grade WPF applications on .NET 6 or later, this pattern should be your default architecture.


메타데이터
post_id
463dccb864db
slug
using-appsettings-json-in-modern-net-wpf-applications-463dccb864db
url
https://medium.com/@EdwardCurtin/using-appsettings-json-in-modern-net-wpf-applications-463dccb864db
canonical_url
https://medium.com/@EdwardCurtin/using-appsettings-json-in-modern-net-wpf-applications-463dccb864db
author_url
https://medium.com/@EdwardCurtin
status
ok
fetched_at
2026-06-14 11:28:49