C#設定の基本を完全解説|appsettings・configファイル・環境変数の使い分けまで

はじめに

C#でアプリケーションを作るとき、意外と重要になるのが「設定」をどう管理するかです。たとえば、データベース接続文字列、外部APIのURL、ログレベル、機能のオン・オフ、タイムアウト値、メール送信設定などは、アプリケーションの動作を左右する大切な情報です。

これらをコードの中に直接書いてしまうと、環境ごとの切り替えが難しくなり、セキュリティ上のリスクも高まります。開発環境ではローカルDB、本番環境ではクラウドDBを使いたい場合や、APIキーを安全に管理したい場合には、C#設定の考え方を正しく理解しておく必要があります。

C#の設定管理には、主に appsettings.jsonApp.config / Web.config、環境変数、そして IConfiguration や Optionsパターンといった仕組みがあります。特に .NET Core/.NET 5以降では、IConfiguration を中心としたモダンな設定管理が一般的です。一方で、.NET Frameworkのアプリでは今でも App.configWeb.config が使われる場面があります。

この記事では、C#設定の基本から、appsettings、configファイル、環境変数の使い分け、セキュリティを意識した管理方法、よくあるエラーの解決方法まで、実践的に解説します。

1. C#の「設定」とは?まず押さえる基本

1-1. C#における設定の役割

C#における設定とは、アプリケーションの動作を外部から変更できるようにするための値です。コードそのものではなく、設定ファイルや環境変数などに値を分離することで、アプリケーションを再ビルドせずに動作を変えられます。

たとえば、次のような値は設定として管理されることが多いです。

C#
var apiUrl = "https://api.example.com";
var timeoutSeconds = 30;
var logLevel = "Information";

このような値をコードに直接書くのではなく、appsettings.json や環境変数から読み込むようにすると、開発環境、本番環境、テスト環境で柔軟に切り替えられます。

C#設定の目的は、単に値を外部化することではありません。環境差分を吸収し、セキュリティを高め、運用しやすいアプリケーションを作ることが本質です。

1-2. 設定値をコードに直接書くべきではない理由

設定値をコードに直接書くことを「ハードコーディング」と呼びます。小さなサンプルアプリでは問題になりにくいですが、実務では避けるべきです。

理由の1つは、環境ごとの切り替えが難しくなることです。開発環境では localhost のDB、本番環境では本番DBを使う場合、接続先をコードに書いていると、環境ごとにコードを変更しなければなりません。

もう1つは、セキュリティリスクです。パスワード、APIキー、アクセストークンなどをコードに書くと、Gitなどのリポジトリに誤って含めてしまう可能性があります。Microsoftのドキュメントでも、パスワードなどの機密情報をコードやプレーンテキストの設定ファイルに保存しないことが推奨されています。

さらに、変更のたびにビルドやデプロイが必要になる点も問題です。ログレベルや一時的な機能フラグの変更だけでアプリケーションを再リリースするのは、運用上の負担になります。

1-3. 設定で管理する代表的な項目

C#設定でよく管理される項目には、次のようなものがあります。

項目
データベース接続文字列SQL Server、PostgreSQL、MySQLなどの接続情報
外部APIのURL決済API、認証API、社内APIのエンドポイント
APIキー・トークン外部サービスを利用するための認証情報
ログレベルDebug、Information、Warning、Errorなど
タイムアウト値HTTP通信やDB接続の待機時間
機能フラグ特定機能の有効・無効
メール設定SMTPサーバー、ポート、送信元アドレス
ファイルパスアップロード先、ログ出力先、テンプレート配置先

ただし、すべての設定を同じ場所で管理すればよいわけではありません。公開しても問題ない値、環境ごとに変わる値、秘密にすべき値を分けて考えることが重要です。

1-4. C#設定でよく使われる3つの管理方法

C#設定でよく使われる管理方法は、大きく分けると次の3つです。

1つ目は appsettings.json です。主に .NET Core、.NET 5以降、ASP.NET Core、モダンなコンソールアプリなどで使われます。JSON形式で読みやすく、階層構造の設定を表現しやすいのが特徴です。

2つ目は App.configWeb.config です。主に .NET Framework時代のデスクトップアプリ、Windowsサービス、ASP.NETアプリなどで使われます。XML形式で、appSettingsconnectionStrings セクションを使って設定を管理します。

3つ目は環境変数です。OS、Docker、クラウド、CI/CD環境などから設定を注入できます。特に本番環境の接続文字列やAPIキーなど、環境ごとに変わる値や機密情報の管理に向いています。環境変数は、指定済みの設定ソースより後から読み込まれる場合、既存の設定値を上書きできます。

2. C#設定の全体像|appsettings・configファイル・環境変数の違い

2-1. appsettings.jsonとは

appsettings.json は、.NET Core/.NET 5以降のアプリケーションで広く使われるJSON形式の設定ファイルです。ASP.NET Coreプロジェクトを作成すると、標準で appsettings.json が含まれることが多く、ログ設定や接続文字列などを管理できます。

例として、次のように設定を書きます。

JSON
{
"AppName": "SampleApp",
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=SampleDb;Trusted_Connection=True;"
}
}

JSON形式なので、人間が読みやすく、階層構造も自然に表現できます。IConfiguration と組み合わせることで、C#コードから簡単に値を取得できます。

2-2. App.config・Web.configとは

App.configWeb.config は、主に .NET Frameworkで使われるXML形式の設定ファイルです。

App.config は、コンソールアプリ、Windows Forms、WPF、Windowsサービスなどのアプリケーションで使われます。ビルド後には、実行ファイル名に合わせて アプリ名.exe.config のようなファイルとして出力されます。

Web.config は、従来のASP.NET Web FormsやASP.NET MVCなど、.NET FrameworkベースのWebアプリで使われます。アプリケーション設定だけでなく、IISや認証、ルーティング、HTTPハンドラーなどの設定にも使われます。

.NET Frameworkの App.config では、appSettings セクションに単純なキーと値を定義し、ConfigurationManager.AppSettings で読み取ることができます。Microsoftのドキュメントでも、この方法は .NET Framework固有のものとして説明されています。

2-3. 環境変数とは

環境変数は、OSや実行環境に設定するキーと値のペアです。C#アプリケーションからは、Environment.GetEnvironmentVariableIConfiguration を通じて読み込めます。

たとえば、次のような値を環境変数として設定できます。

ConnectionStrings__DefaultConnection=Server=prod-db;Database=AppDb;User Id=app;Password=secret;
ExternalApi__BaseUrl=https://api.example.com

.NETの構成システムでは、階層構造を表すために : を使うことがあります。ただし、OSやシェルによっては : が扱いにくいため、環境変数では __、つまりダブルアンダースコアを使うのが一般的です。

環境変数の大きな利点は、アプリケーションのコードや設定ファイルを変更せずに、実行環境側から値を注入できることです。Docker、Kubernetes、Azure App Service、GitHub Actionsなどの環境でもよく使われます。

2-4. それぞれの使い分け早見表

管理方法主な形式向いている用途機密情報主な利用場面
appsettings.jsonJSON通常設定、ログ設定、API URL、既定値原則として書かない.NET Core/.NET 5以降
appsettings.{Environment}.jsonJSON環境ごとの差分設定原則として書かないDevelopment、Staging、Production
App.configXML.NET Frameworkデスクトップアプリの設定原則として書かないWindows Forms、WPF、コンソール
Web.configXML.NET Framework Webアプリ、IIS関連設定原則として書かないASP.NET Web Forms、ASP.NET MVC
環境変数OS依存本番環境の上書き、接続先、秘密情報内容に注意して利用Docker、クラウド、CI/CD
User SecretsJSON風のローカル秘密ストア開発時の秘密情報開発用途に向くASP.NET Core、.NET開発
Key Vaultなど外部サービス本番の秘密情報管理向いているクラウド本番環境

迷った場合は、まず appsettings.json に公開可能な既定値を書き、環境差分は appsettings.{Environment}.json、本番の秘密情報は環境変数や外部シークレット管理に逃がす、という考え方が基本です。

2-5. .NET Frameworkと.NET Core/.NET 5以降での違い

.NET Frameworkでは、設定管理の中心は App.config / Web.configConfigurationManager です。XML形式の設定ファイルを読み込み、ConfigurationManager.AppSettingsConfigurationManager.ConnectionStrings を使って値を取得します。

一方、.NET Core/.NET 5以降では、IConfiguration を中心に、JSONファイル、環境変数、コマンドライン引数、User Secrets、Azure Key Vaultなど、複数の設定ソースを組み合わせる設計が一般的です。ASP.NET CoreではDIから IConfiguration を受け取ることができます。

つまり、古い.NET Frameworkアプリでは App.config / Web.config、新しい .NETアプリでは appsettings.jsonIConfiguration が基本、と理解するとよいでしょう。

3. appsettings.jsonの基本

3-1. appsettings.jsonを使う場面

appsettings.json は、.NET Core/.NET 5以降のC#設定で最もよく使われる方法です。ASP.NET Core Webアプリ、Web API、Worker Service、コンソールアプリなどで利用できます。

特に次のような設定に向いています。

  • アプリケーション名

  • ログレベル

  • 外部APIのベースURL

  • タイムアウト値

  • 機能フラグ

  • 開発用の接続文字列

  • 公開しても問題ない既定値

一方で、パスワードや本番APIキーなどの秘密情報をそのまま書くべきではありません。appsettings.json はプロジェクトに含まれ、Gitで管理されることが多いためです。

3-2. appsettings.jsonの基本構造

appsettings.json はJSON形式で記述します。キーと値のペアだけでなく、オブジェクトを使った階層構造も表現できます。

JSON
{
"Application": {
"Name": "MyCSharpApp",
"Version": "1.0.0"
},
"ExternalApi": {
"BaseUrl": "https://api.example.com",
"TimeoutSeconds": 30
},
"FeatureFlags": {
"EnableNewCheckout": false
}
}

このように、関連する設定をまとめて階層化すると、設定の意味が分かりやすくなります。

C#側では、Application:NameExternalApi:BaseUrlFeatureFlags:EnableNewCheckout のように、コロン区切りで階層を指定して取得できます。

3-3. appsettings.jsonに設定値を書く方法

たとえば、外部APIの設定を書く場合は次のようにします。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com",
"ApiVersion": "v1",
"TimeoutSeconds": 30
}
}

ログ設定を書く場合は、ASP.NET Coreのテンプレートでよく見られるように、次のような構造になります。

JSON
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

接続文字列は、慣例的に ConnectionStrings セクションに書きます。

JSON
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;"
}
}

ただし、本番用のユーザー名やパスワードを含む接続文字列は、appsettings.json に直接書かず、環境変数やシークレット管理サービスで上書きする設計にしましょう。

3-4. C#からappsettings.jsonを読み込む方法

ASP.NET Coreでは、通常 WebApplication.CreateBuilder(args) によって既定の構成が読み込まれます。そのため、Program.cs で次のように取得できます。

C#
var builder = WebApplication.CreateBuilder(args);

var appName = builder.Configuration["Application:Name"];
var baseUrl = builder.Configuration["ExternalApi:BaseUrl"];

Console.WriteLine(appName);
Console.WriteLine(baseUrl);

コントローラーやサービスで使う場合は、DIで IConfiguration を受け取ります。

C#
public class SampleService
{
private readonly IConfiguration _configuration;

public SampleService(IConfiguration configuration)
{
_configuration = configuration;
}

public string GetApiBaseUrl()
{
return _configuration["ExternalApi:BaseUrl"] ?? "";
}
}

コンソールアプリで明示的に読み込む場合は、ConfigurationBuilder を使います。

C#
using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();

var appName = configuration["Application:Name"];

Console.WriteLine(appName);

この場合、Microsoft.Extensions.ConfigurationMicrosoft.Extensions.Configuration.Json などのパッケージが必要になることがあります。

3-5. 階層構造の設定値を取得する方法

階層構造の設定は、コロン区切りで取得できます。

JSON
{
"Mail": {
"Smtp": {
"Host": "smtp.example.com",
"Port": 587
}
}
}

C#では次のように取得します。

C#
var host = configuration["Mail:Smtp:Host"];
var port = configuration.GetValue<int>("Mail:Smtp:Port");

文字列として取得するだけならインデクサーで十分ですが、数値やboolに変換したい場合は GetValue<T> を使うと便利です。

C#
var timeout = configuration.GetValue<int>("ExternalApi:TimeoutSeconds");
var enabled = configuration.GetValue<bool>("FeatureFlags:EnableNewCheckout");

設定値が存在しない場合は、既定値を指定することもできます。

C#
var timeout = configuration.GetValue<int>("ExternalApi:TimeoutSeconds", 10);

3-6. 接続文字列をappsettings.jsonで管理する方法

接続文字列は、ConnectionStrings セクションにまとめるのが一般的です。

JSON
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;"
}
}

取得するときは、GetConnectionString を使います。

C#
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

Entity Framework Coreを使う場合は、次のように DbContext の登録時に利用できます。

C#
builder.Services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection"));
});

接続文字列は環境によって変わりやすく、パスワードを含むこともあります。そのため、開発用のローカル接続文字列は appsettings.Development.json に置き、本番用は環境変数やクラウド側の設定で上書きするのが安全です。EF Coreのドキュメントでも、接続文字列は環境移行時に変わる可能性があり、機密情報を含み得るものとして説明されています。

4. appsettings.{Environment}.jsonで環境ごとに設定を切り替える

4-1. Development・Staging・Productionとは

ASP.NET Coreでは、実行環境を表す名前として DevelopmentStagingProduction がよく使われます。Microsoftのドキュメントでも、ローカル開発では Development、本番前検証では Staging、本番環境では Production といった環境の使い分けが説明されています。

それぞれの役割は次の通りです。

環境役割
Development開発者のローカル環境。詳細エラーやデバッグ向け設定を使う
Staging本番に近い検証環境。リリース前確認に使う
Production実ユーザーが利用する本番環境。安全性、性能、信頼性を重視する

同じアプリケーションでも、環境によってDB接続先、ログレベル、外部APIのURLなどを変える必要があります。そのために使うのが appsettings.{Environment}.json です。

4-2. appsettings.Development.jsonの役割

appsettings.Development.json は、Development 環境でのみ読み込まれる設定ファイルです。

たとえば、基本設定を appsettings.json に書きます。

JSON
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"ExternalApi": {
"BaseUrl": "https://api.example.com"
}
}

開発環境だけログを詳しくしたい場合は、appsettings.Development.json に上書き設定を書きます。

JSON
{
"Logging": {
"LogLevel": {
"Default": "Debug"
}
},
"ExternalApi": {
"BaseUrl": "https://dev-api.example.com"
}
}

このように、共通設定は appsettings.json、環境ごとの差分は appsettings.Development.json などに分けると管理しやすくなります。

4-3. 本番環境と開発環境で設定を分ける方法

環境ごとに設定を分ける基本形は、次のようなファイル構成です。

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

appsettings.json には全環境共通の既定値を書きます。

JSON
{
"ExternalApi": {
"TimeoutSeconds": 30
}
}

appsettings.Development.json には開発環境用の差分を書きます。

JSON
{
"ExternalApi": {
"BaseUrl": "https://dev-api.example.com"
}
}

appsettings.Production.json には本番環境用の差分を書きます。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com"
}
}

ただし、本番のパスワードやAPIキーを appsettings.Production.json に書いてGit管理するのは避けるべきです。秘密情報は環境変数、クラウドのアプリケーション設定、Azure Key Vaultなどで管理しましょう。

4-4. ASPNETCORE_ENVIRONMENTの設定方法

ASP.NET Coreでは、環境名を決めるために ASPNETCORE_ENVIRONMENTDOTNET_ENVIRONMENT が使われます。環境変数が設定されていない場合、既定では Production として扱われます。

Windows PowerShellでは次のように設定できます。

PowerShell
$env:ASPNETCORE_ENVIRONMENT="Development"
dotnet run

Windowsのコマンドプロンプトでは次のように設定します。

cmd
set ASPNETCORE_ENVIRONMENT=Development
dotnet run

LinuxやmacOSでは次のように設定できます。

Bash
export ASPNETCORE_ENVIRONMENT=Development
dotnet run

launchSettings.json でローカル実行時の環境変数を設定することもあります。

JSON
{
"profiles": {
"MyApp": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

4-5. 環境別設定でよくあるミス

環境別設定でよくあるミスは、まず環境名のスペル違いです。

appsettings.Develop.json

このようにファイル名を間違えると、Development 環境では読み込まれません。正しくは次のようにします。

appsettings.Development.json

次に、ASPNETCORE_ENVIRONMENT が設定されていないケースです。設定されていなければ本番環境として動作するため、appsettings.Development.json が読み込まれないことがあります。

また、ファイルのコピー設定も確認が必要です。コンソールアプリなどで appsettings.json を使う場合、ビルド出力先にコピーされていないと実行時に読み込めません。Visual Studioのプロパティで「出力ディレクトリにコピー」を設定するか、.csproj に次のような設定を追加します。

XML
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

5. App.config・Web.configの基本

5-1. App.configとは

App.config は、.NET Frameworkのデスクトップアプリやコンソールアプリで使われるXML形式の設定ファイルです。Windows Forms、WPF、Windowsサービス、.NET Frameworkコンソールアプリなどでよく使われます。

基本形は次の通りです。

XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="AppName" value="SampleApp" />
<add key="LogLevel" value="Information" />
</appSettings>
</configuration>

ビルドすると、App.config は実行ファイルに対応した .exe.config ファイルとして出力されます。

SampleApp.exe
SampleApp.exe.config

.NET Frameworkアプリでは、この .config ファイルが実行時に読み込まれます。

5-2. Web.configとは

Web.config は、.NET FrameworkベースのWebアプリで使われる設定ファイルです。ASP.NET Web Forms、ASP.NET MVC、古いASP.NET Web APIなどでよく見られます。

Web.config では、アプリケーション設定だけでなく、IIS連携、認証、認可、URLルーティング、HTTPモジュール、セッション、エラーページなど、Webアプリ全体に関わる設定を管理できます。

例は次の通りです。

XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="ExternalApiUrl" value="https://api.example.com" />
</appSettings>

<connectionStrings>
<add name="DefaultConnection"
connectionString="Server=localhost;Database=SampleDb;Trusted_Connection=True;"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>

ASP.NET Coreでは、アプリケーション設定は基本的に appsettings.jsonIConfiguration で管理します。ただし、IISにホストする場合など、一部のホスティング設定で Web.config が生成・利用されることがあります。

5-3. appSettingsセクションの使い方

appSettings セクションは、単純なキーと値を管理するための場所です。

XML
<configuration>
<appSettings>
<add key="AppName" value="LegacyApp" />
<add key="MaxRetryCount" value="3" />
<add key="EnableFeatureX" value="true" />
</appSettings>
</configuration>

C#から取得するには、ConfigurationManager.AppSettings を使います。

C#
using System.Configuration;

var appName = ConfigurationManager.AppSettings["AppName"];
var maxRetryCount = int.Parse(ConfigurationManager.AppSettings["MaxRetryCount"] ?? "0");
var enableFeatureX = bool.Parse(ConfigurationManager.AppSettings["EnableFeatureX"] ?? "false");

appSettings は簡単ですが、値は基本的に文字列として扱われます。数値やboolとして使う場合は、C#側で変換が必要です。

5-4. connectionStringsセクションの使い方

データベース接続文字列は、connectionStrings セクションに書きます。

XML
<configuration>
<connectionStrings>
<add name="DefaultConnection"
connectionString="Server=localhost;Database=SampleDb;Trusted_Connection=True;"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>

C#から取得するには、ConfigurationManager.ConnectionStrings を使います。

C#
using System.Configuration;

var connectionString = ConfigurationManager
.ConnectionStrings["DefaultConnection"]
.ConnectionString;

connectionStrings は、Entity Framework 6やADO.NETを使う.NET Frameworkアプリでよく使われます。

5-5. ConfigurationManagerで設定を読み込む方法

ConfigurationManager は、.NET Frameworkで設定ファイルを読み込むための代表的なクラスです。

C#
using System;
using System.Configuration;

class Program
{
static void Main()
{
var appName = ConfigurationManager.AppSettings["AppName"];
var connectionString = ConfigurationManager
.ConnectionStrings["DefaultConnection"]
.ConnectionString;

Console.WriteLine(appName);
Console.WriteLine(connectionString);
}
}

.NET Core/.NET 5以降でも互換目的で System.Configuration.ConfigurationManager パッケージを使えるケースはありますが、新規開発では IConfiguration を使う方が自然です。

5-6. configファイルを使うべきケース

App.configWeb.config を使うべきケースは、主に次のような場合です。

  • .NET Frameworkの既存アプリを保守している

  • Windows FormsやWPFの古いアプリで既にApp.configを使っている

  • ASP.NET Web FormsやASP.NET MVCのアプリを運用している

  • 既存ライブラリがConfigurationManager前提で動作している

  • IISやASP.NET Framework固有の設定を管理する必要がある

一方、新規に .NET 8、.NET 9、.NET 10などのモダンな .NETアプリを作る場合は、appsettings.jsonIConfiguration、Optionsパターンを使う設計を選ぶのが一般的です。

6. 環境変数でC#の設定を管理する方法

6-1. 環境変数を使うメリット

環境変数を使う最大のメリットは、アプリケーションの外側から設定を変更できることです。コードや設定ファイルを変更せずに、実行環境ごとに値を差し替えられます。

特に本番環境では、次のような理由で環境変数がよく使われます。

  • Gitに秘密情報を含めずに済む

  • Dockerやクラウド環境と相性がよい

  • デプロイ先ごとに設定を変えやすい

  • CI/CDで値を注入しやすい

  • appsettings.json の既定値を上書きできる

Microsoftのドキュメントでも、環境変数はコードやローカル設定ファイルに秘密情報を保存しないために使われ、既に指定された設定値を上書きできると説明されています。

6-2. 環境変数に向いている設定値

環境変数に向いている設定値は、環境ごとに変わる値や、設定ファイルに書きたくない値です。

代表例は次の通りです。

設定値環境変数に向いている理由
本番DB接続文字列環境ごとに異なり、秘密情報を含みやすい
APIキーGitに含めるべきではない
外部APIのURL開発・検証・本番で変わる
ログレベル運用時に変更したい場合がある
認証プロバイダー設定環境ごとに異なることが多い
ストレージ接続情報クラウド環境ごとに異なる

ただし、環境変数も万能ではありません。環境変数は一般にプレーンテキストとして扱われることが多く、マシンやプロセスが侵害された場合には第三者から読み取られる可能性があります。Microsoftのドキュメントでも、この点に注意が示されています。

6-3. C#から環境変数を取得する方法

最もシンプルな方法は、Environment.GetEnvironmentVariable を使うことです。

C#
var apiKey = Environment.GetEnvironmentVariable("EXTERNAL_API_KEY");

if (string.IsNullOrEmpty(apiKey))
{
throw new InvalidOperationException("EXTERNAL_API_KEY is not set.");
}

IConfiguration に環境変数プロバイダーを追加している場合は、他の設定と同じように取得できます。

C#
var apiKey = configuration["ExternalApi:ApiKey"];

環境変数で階層構造を表す場合は、ダブルアンダースコアを使います。

ExternalApi__ApiKey=xxxxxxxx
ExternalApi__BaseUrl=https://api.example.com

C#側では、通常の階層キーとして取得できます。

C#
var apiKey = configuration["ExternalApi:ApiKey"];
var baseUrl = configuration["ExternalApi:BaseUrl"];

6-4. Windowsで環境変数を設定する方法

Windows PowerShellで一時的に環境変数を設定する場合は、次のようにします。

PowerShell
$env:ExternalApi__ApiKey="xxxxxxxx"
dotnet run

この方法は現在のPowerShellセッションでのみ有効です。永続的に設定したい場合は、setx を使う方法があります。

PowerShell
setx ExternalApi__ApiKey "xxxxxxxx"

ただし、setx で設定した値は新しいターミナルから有効になります。現在開いているターミナルにはすぐ反映されない点に注意してください。

WindowsのGUIから設定する場合は、「システムの詳細設定」から「環境変数」を開き、ユーザー環境変数またはシステム環境変数として追加します。

6-5. Linux・Docker・クラウド環境での環境変数設定

LinuxやmacOSでは、次のように環境変数を設定できます。

Bash
export ExternalApi__ApiKey="xxxxxxxx"
dotnet run

Dockerでは、docker run-e オプションで指定できます。

Bash
docker run -e ExternalApi__ApiKey="xxxxxxxx" myapp

docker-compose.yml では次のように書けます。

YAML
services:
app:
image: myapp
environment:
ExternalApi__BaseUrl: "https://api.example.com"
ExternalApi__ApiKey: "xxxxxxxx"

クラウド環境では、Azure App Service、AWS Elastic Beanstalk、ECS、Kubernetesなど、それぞれの設定画面やマニフェストで環境変数を指定できます。Azure App Serviceでは、アプリ設定や接続文字列を設定することで、アプリの構成値を上書きできます。

6-6. 環境変数を使うときの注意点

環境変数を使うときは、次の点に注意しましょう。

まず、変数名のルールを統一することです。C#設定では階層構造を ExternalApi:BaseUrl のように扱いますが、環境変数では ExternalApi__BaseUrl のようにダブルアンダースコアを使うと扱いやすくなります。

次に、環境変数が本当に設定されているか確認することです。設定されていない場合、null が返り、実行時エラーの原因になります。起動時に必須設定を検証する仕組みを入れると安全です。

また、環境変数に秘密情報を入れたからといって完全に安全というわけではありません。サーバーの管理権限を持つユーザーや、侵害されたプロセスから読み取られる可能性があります。本番の高機密情報は、Azure Key Vaultなどの外部シークレット管理サービスの利用も検討しましょう。

7. IConfigurationを使ったモダンな設定管理

7-1. IConfigurationとは

IConfiguration は、.NET Core/.NET 5以降の設定管理で中心となるインターフェイスです。JSONファイル、環境変数、コマンドライン引数、User Secrets、Azure Key Vaultなど、複数の設定ソースをまとめて扱えます。

ASP.NET Coreでは、IConfiguration はDIに登録されているため、コントローラーやサービスに注入して利用できます。Microsoftのドキュメントでも、DIを使って IConfiguration をサービスに注入できることが説明されています。

C#
public class WeatherService
{
private readonly IConfiguration _configuration;

public WeatherService(IConfiguration configuration)
{
_configuration = configuration;
}

public string GetEndpoint()
{
return _configuration["WeatherApi:Endpoint"] ?? "";
}
}

IConfiguration の強みは、設定値の取得元を意識せずに使えることです。値が appsettings.json から来たのか、環境変数から来たのか、コマンドライン引数から来たのかを、利用側のコードは基本的に知る必要がありません。

7-2. ConfigurationBuilderの基本

ConfigurationBuilder は、設定ソースを組み立てるためのクラスです。ASP.NET Coreでは既定で設定済みですが、コンソールアプリや独自構成では明示的に使うことがあります。

C#
using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();

var value = configuration["SampleKey"];

ここでは、JSONファイル、環境変数、コマンドライン引数を順番に追加しています。後から追加した設定ソースが、同じキーの値を上書きできる点が重要です。

7-3. JSONファイル・環境変数・コマンドライン引数を組み合わせる方法

実務では、1つの設定ソースだけでなく、複数の設定ソースを組み合わせることが多いです。

たとえば、次のような構成にします。

C#
var environment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") 
?? "Production";

var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();

この構成では、まず共通設定を読み込み、次に環境別設定を読み込み、その後に環境変数、最後にコマンドライン引数を読み込みます。

たとえば appsettings.json に次の設定があるとします。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com"
}
}

環境変数で次のように指定すると、値を上書きできます。

Bash
export ExternalApi__BaseUrl="https://staging-api.example.com"

さらにコマンドライン引数で一時的に上書きすることもできます。

Bash
dotnet run --ExternalApi:BaseUrl=https://local-api.example.com

7-4. 設定ソースの優先順位

IConfiguration では、同じキーが複数の設定ソースに存在する場合、基本的に後から追加された設定ソースの値が優先されます。

たとえば、次の順番で追加したとします。

C#
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.Production.json")
.AddEnvironmentVariables()
.AddCommandLine(args)

この場合の優先順位は、概念的には次のようになります。

優先度設定ソース
コマンドライン引数
環境変数
appsettings.Production.json
appsettings.json

つまり、appsettings.json に既定値を書き、環境別JSONで差分を上書きし、環境変数で本番固有の値を上書きし、必要に応じてコマンドライン引数で一時的に上書きする、という構成ができます。

ASP.NET Coreの既定構成では、User SecretsがJSON設定ファイルより後に登録されるため、appsettings.jsonappsettings.{Environment}.json より優先されることが説明されています。

7-5. ASP.NET CoreでDIから設定を受け取る方法

ASP.NET Coreでは、IConfiguration をコンストラクターで受け取るだけで設定を利用できます。

C#
[ApiController]
[Route("[controller]")]
public class SampleController : ControllerBase
{
private readonly IConfiguration _configuration;

public SampleController(IConfiguration configuration)
{
_configuration = configuration;
}

[HttpGet]
public IActionResult Get()
{
var appName = _configuration["Application:Name"];
return Ok(new { appName });
}
}

ただし、設定項目が増えてくると、文字列キーをあちこちに書くことになり、タイプミスや保守性の問題が出ます。

C#
_configuration["ExternalApi:BaseUrl"]
_configuration["ExternalApi:TimeoutSeconds"]
_configuration["ExternalApi:ApiKey"]

このような場合は、次に説明するOptionsパターンを使うと、型安全に設定を扱えます。

7-6. コンソールアプリでIConfigurationを使う方法

コンソールアプリでも IConfiguration を使えます。たとえば、次のように設定ファイルを読み込みます。

C#
using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();

var message = configuration["Message"];

Console.WriteLine(message);

appsettings.json は次のようにします。

JSON
{
"Message": "Hello from appsettings.json"
}

さらにDIも使いたい場合は、Microsoft.Extensions.Hosting のGeneric Hostを利用すると、ASP.NET Coreに近い形で設定、ログ、DIをまとめて扱えます。

C#
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;

var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddTransient<App>();
})
.Build();

await host.Services.GetRequiredService<App>().RunAsync();

public class App
{
private readonly IConfiguration _configuration;

public App(IConfiguration configuration)
{
_configuration = configuration;
}

public Task RunAsync()
{
Console.WriteLine(_configuration["Message"]);
return Task.CompletedTask;
}
}

8. Optionsパターンで設定を型安全に扱う

8-1. Optionsパターンとは

Optionsパターンは、関連する設定値をC#のクラスにマッピングして、型安全に扱うための仕組みです。Microsoftのドキュメントでも、Optionsパターンは関連する設定グループに対して強く型付けされたアクセスを提供する方法として説明されています。

たとえば、次のような設定があるとします。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com",
"TimeoutSeconds": 30
}
}

これを毎回次のように読むと、キー名のタイプミスが起きやすくなります。

C#
var baseUrl = configuration["ExternalApi:BaseUrl"];
var timeout = configuration.GetValue<int>("ExternalApi:TimeoutSeconds");

Optionsパターンを使うと、次のようにクラスとして扱えます。

C#
public class ExternalApiOptions
{
public string BaseUrl { get; set; } = "";
public int TimeoutSeconds { get; set; }
}

設定値をクラスにバインドすることで、補完が効き、テストしやすく、保守性も高まります。

8-2. 設定クラスを作成する方法

設定クラスは、設定セクションに対応するプロパティを持つ通常のC#クラスとして作成します。

C#
public class ExternalApiOptions
{
public const string SectionName = "ExternalApi";

public string BaseUrl { get; set; } = "";
public int TimeoutSeconds { get; set; } = 30;
public string ApiKey { get; set; } = "";
}

SectionName を定数として持たせておくと、文字列キーの重複を減らせます。

C#
builder.Services.Configure<ExternalApiOptions>(
builder.Configuration.GetSection(ExternalApiOptions.SectionName));

Optionsパターンでバインドするクラスは、基本的にpublicなsetterを持つプロパティを使います。Microsoftのドキュメントでも、Optionsクラスは非abstractでパラメーターなしコンストラクターを持ち、バインド対象はpublicな読み書き可能プロパティであることが説明されています。

8-3. appsettings.jsonをクラスにバインドする方法

appsettings.json に次のような設定を書きます。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com",
"TimeoutSeconds": 30,
"ApiKey": "development-api-key"
}
}

Program.cs でOptionsとして登録します。

C#
builder.Services.Configure<ExternalApiOptions>(
builder.Configuration.GetSection("ExternalApi"));

サービス側では、IOptions<T> を使って受け取ります。

C#
using Microsoft.Extensions.Options;

public class ExternalApiClient
{
private readonly ExternalApiOptions _options;

public ExternalApiClient(IOptions<ExternalApiOptions> options)
{
_options = options.Value;
}

public void Call()
{
Console.WriteLine(_options.BaseUrl);
Console.WriteLine(_options.TimeoutSeconds);
}
}

これにより、文字列キーをサービス内に散らばらせず、設定をクラスとして扱えます。

8-4. IOptions・IOptionsSnapshot・IOptionsMonitorの違い

Optionsパターンでは、主に IOptions<T>IOptionsSnapshot<T>IOptionsMonitor<T> の3つを使い分けます。

種類特徴向いているケース
IOptions<T>アプリ起動時の設定を基本的に使う設定が実行中に変わらない場合
IOptionsSnapshot<T>リクエスト単位で設定を再評価できるASP.NET Coreでリクエストごとに設定反映したい場合
IOptionsMonitor<T>設定変更の監視や変更通知に対応実行中の変更を反映したい場合

通常のWebアプリでは、まず IOptions<T> から始めるとよいでしょう。リクエストごとの再読み込みが必要なら IOptionsSnapshot<T>、設定変更を監視したい場合は IOptionsMonitor<T> を検討します。

IOptionsMonitor<T> の例は次の通りです。

C#
public class ExternalApiClient
{
private readonly IOptionsMonitor<ExternalApiOptions> _optionsMonitor;

public ExternalApiClient(IOptionsMonitor<ExternalApiOptions> optionsMonitor)
{
_optionsMonitor = optionsMonitor;
}

public string GetBaseUrl()
{
return _optionsMonitor.CurrentValue.BaseUrl;
}
}

8-5. Optionsパターンを使うべきケース

Optionsパターンを使うべきケースは、設定項目が複数あり、意味のあるグループとして扱える場合です。

たとえば、次のような設定はOptionsパターンに向いています。

  • 外部API設定

  • SMTP設定

  • 認証設定

  • ストレージ設定

  • バッチ処理設定

  • リトライ設定

  • 機能フラグ設定

逆に、1つだけの単純な設定値を読み取るだけなら、IConfiguration["Key"] でも十分です。

実務では、アプリケーションの規模が大きくなるほどOptionsパターンのメリットが大きくなります。文字列キーの重複が減り、設定の構造が明確になり、テストコードも書きやすくなります。

9. セキュリティを意識したC#設定管理

9-1. パスワードやAPIキーを設定ファイルに書いてはいけない理由

C#設定で最も注意すべきなのは、機密情報の扱いです。DBパスワード、APIキー、JWT署名キー、OAuthクライアントシークレットなどを appsettings.jsonApp.config に直接書くのは避けるべきです。

理由は明確です。設定ファイルはGitにコミットされやすく、レビューや共有の過程で多くの人の目に触れます。誤って公開リポジトリにpushすれば、秘密情報が漏えいする可能性があります。

Microsoftのドキュメントでも、パスワードなどの機密情報をソースコードや設定ファイルに保存せず、本番シークレットを開発・テスト環境で使わないことが推奨されています。

安全な基本方針は次の通りです。

値の種類推奨される管理方法
公開可能な既定値appsettings.json
開発用の秘密情報User Secrets
本番の環境差分環境変数、クラウド設定
高機密の本番シークレットAzure Key Vaultなど
チーム共通のサンプル値appsettings.example.json

9-2. User Secretsの使い方

User Secretsは、開発環境で秘密情報をソースコードの外に保存するための仕組みです。ASP.NET Coreの開発時に、APIキーやローカルDB接続文字列をGitに含めず管理したい場合に便利です。

まず、プロジェクトでUser Secretsを初期化します。

Bash
dotnet user-secrets init

次に、秘密情報を設定します。

Bash
dotnet user-secrets set "ExternalApi:ApiKey" "xxxxxxxx"
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=DevDb;User Id=dev;Password=secret;"

C#側では、通常の設定と同じように読み取れます。

C#
var apiKey = builder.Configuration["ExternalApi:ApiKey"];
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

User Secretsは、開発中にシークレットをソースコードから除外するための仕組みとして説明されています。ただし、本番環境用のシークレット管理として使うものではありません。

9-3. 環境変数で機密情報を管理する方法

本番環境では、環境変数を使って秘密情報を注入することがあります。

たとえば、接続文字列を環境変数で指定します。

Bash
export ConnectionStrings__DefaultConnection="Server=prod-db;Database=AppDb;User Id=app;Password=secret;"

C#側では、次のように取得できます。

C#
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

外部APIキーも同様です。

Bash
export ExternalApi__ApiKey="xxxxxxxx"
C#
var apiKey = builder.Configuration["ExternalApi:ApiKey"];

環境変数は便利ですが、保存方式やアクセス権限は実行環境に依存します。サーバーにログインできる人、コンテナ定義を閲覧できる人、CI/CDのシークレットを管理できる人など、誰が値にアクセスできるのかを必ず確認しましょう。

9-4. Azure Key Vaultなど外部シークレット管理の考え方

本番環境でより安全に秘密情報を管理したい場合は、Azure Key Vault、AWS Secrets Manager、Google Secret Manager、HashiCorp Vaultなどの外部シークレット管理サービスを使います。

Azure Key Vaultは、アプリやサービスで使う暗号キーやシークレットの保護を支援するクラウドサービスです。ASP.NET CoreではAzure Key Vault構成プロバイダーを使って、Key Vaultのシークレットをアプリ構成として読み込めます。

考え方としては、アプリケーション内に秘密情報を持たせるのではなく、実行時に安全な仕組みで取得します。Azure環境では、Managed Identityを使うことで、アプリケーションコードや設定に認証情報を保存せずKey Vaultへアクセスする構成も可能です。

外部シークレット管理を使うべき場面は次の通りです。

  • 本番のDBパスワードを安全に管理したい

  • APIキーのローテーションを行いたい

  • 監査ログを取りたい

  • アクセス権限を厳密に管理したい

  • 複数アプリで共通の秘密情報を利用したい

  • コンプライアンス要件がある

9-5. Gitに含めてよい設定・含めてはいけない設定

Gitに含めてよい設定と、含めてはいけない設定を明確に分けましょう。

Gitに含めてよいものは、公開されても問題ない既定値です。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com",
"TimeoutSeconds": 30
},
"FeatureFlags": {
"EnableNewFeature": false
}
}

Gitに含めてはいけないものは、漏えいすると問題になる値です。

JSON
{
"ExternalApi": {
"ApiKey": "real-api-key"
},
"ConnectionStrings": {
"DefaultConnection": "Server=prod;User Id=admin;Password=real-password;"
}
}

実務では、次のような構成がおすすめです。

appsettings.json                  Gitに含める
appsettings.Development.json 内容によって判断
appsettings.Production.json 原則として秘密情報は書かない
appsettings.Local.json .gitignoreに追加
appsettings.example.json サンプルとしてGitに含める

.gitignore には、ローカル専用の設定ファイルを追加しておきます。

appsettings.Local.json
*.user

10. C#設定管理の実践例

10-1. ログレベルを環境ごとに切り替える

開発環境では詳細なログを出し、本番環境では必要なログだけに絞るのはよくある設定です。

appsettings.json には本番寄りの既定値を書きます。

JSON
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"Microsoft.AspNetCore": "Warning"
}
}
}

appsettings.Development.json では詳細ログに変更します。

JSON
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Information"
}
}
}

これにより、開発時は問題調査しやすく、本番ではログ量を抑えられます。

10-2. データベース接続文字列を切り替える

開発環境ではローカルDB、本番環境では本番DBを使う例です。

appsettings.Development.json には開発用DBを書きます。

JSON
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=DevDb;Trusted_Connection=True;TrustServerCertificate=True;"
}
}

本番環境では、環境変数で接続文字列を設定します。

Bash
export ConnectionStrings__DefaultConnection="Server=prod-db;Database=ProdDb;User Id=app;Password=secret;"

C#側のコードは共通です。

C#
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

この設計にしておけば、コードを変えずに接続先だけを切り替えられます。

10-3. 外部APIのURLを環境ごとに変更する

外部APIのURLも、開発・検証・本番で変わることが多い設定です。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com",
"TimeoutSeconds": 30
}
}

開発環境では次のように上書きします。

JSON
{
"ExternalApi": {
"BaseUrl": "https://dev-api.example.com"
}
}

Optionsパターンで受け取る場合は、次のようにします。

C#
builder.Services.Configure<ExternalApiOptions>(
builder.Configuration.GetSection("ExternalApi"));
C#
public class ExternalApiOptions
{
public string BaseUrl { get; set; } = "";
public int TimeoutSeconds { get; set; }
}

HTTPクライアントに適用する例です。

C#
builder.Services.AddHttpClient<ExternalApiClient>((serviceProvider, client) =>
{
var options = serviceProvider
.GetRequiredService<IOptions<ExternalApiOptions>>()
.Value;

client.BaseAddress = new Uri(options.BaseUrl);
client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds);
});

10-4. Docker環境で設定を上書きする

Dockerでは、環境変数による設定上書きが非常によく使われます。

appsettings.json に既定値を書きます。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com"
}
}

Docker実行時に環境変数で上書きします。

Bash
docker run \
-e ExternalApi__BaseUrl="https://docker-api.example.com" \
-e ASPNETCORE_ENVIRONMENT="Production" \
myapp

docker-compose.yml の例です。

YAML
services:
web:
image: myapp
ports:
- "8080:8080"
environment:
ASPNETCORE_ENVIRONMENT: "Production"
ExternalApi__BaseUrl: "https://api.example.com"
ConnectionStrings__DefaultConnection: "Server=db;Database=AppDb;User Id=app;Password=secret;"

Dockerイメージには汎用的な設定だけを含め、環境ごとの差分はコンテナ起動時に注入するのが基本です。

10-5. コマンドライン引数で一時的に設定を変更する

一時的に設定を変えたい場合、コマンドライン引数が便利です。

Bash
dotnet run --ExternalApi:BaseUrl=https://local-api.example.com --BatchSize=100

C#側では、AddCommandLine(args) を追加しておきます。

C#
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();

値は通常の設定と同じように取得できます。

C#
var baseUrl = configuration["ExternalApi:BaseUrl"];
var batchSize = configuration.GetValue<int>("BatchSize");

バッチアプリや検証用ツールでは、コマンドライン引数で一時的に設定を変えられるようにしておくと便利です。

11. appsettings・configファイル・環境変数の使い分け

11-1. 開発環境でおすすめの設定管理

開発環境では、次の構成がおすすめです。

用途推奨
共通の既定値appsettings.json
開発環境の差分appsettings.Development.json
開発用の秘密情報User Secrets
個人専用設定appsettings.Local.jsonを.gitignore
一時変更コマンドライン引数

開発中は利便性も大切です。すべてを環境変数にすると、ローカル環境の構築が面倒になります。一方で、秘密情報をGitに含めるのは危険です。

そのため、公開可能な設定は appsettings.json、開発環境用の差分は appsettings.Development.json、個人ごとの秘密情報はUser Secretsに分けるのが扱いやすいです。

11-2. 本番環境でおすすめの設定管理

本番環境では、セキュリティと運用性を優先します。

用途推奨
公開可能な既定値appsettings.json
本番固有の非機密設定環境変数、クラウドのアプリ設定
本番の秘密情報Key Vault、Secrets Manager、環境変数
ログレベルなどの運用設定環境変数、クラウド設定
接続文字列環境変数またはシークレット管理

本番では、appsettings.Production.json に秘密情報を直接書いてデプロイするよりも、デプロイ先の設定機能や外部シークレット管理を使う方が安全です。

特にDBパスワード、APIキー、秘密鍵、トークンは、アプリケーションの成果物に含めないことを基本にしましょう。

11-3. チーム開発での設定管理

チーム開発では、設定の「サンプル」と「実値」を分けることが重要です。

おすすめの構成は次の通りです。

appsettings.json
appsettings.Development.json
appsettings.example.json
appsettings.Local.json

appsettings.example.json には、必要な設定項目の一覧とダミー値を書きます。

JSON
{
"ExternalApi": {
"BaseUrl": "https://example.com",
"ApiKey": "set-your-api-key"
},
"ConnectionStrings": {
"DefaultConnection": "set-your-connection-string"
}
}

実際の値は、各開発者がUser Secretsや appsettings.Local.json に設定します。

この方法にすると、新しいメンバーが必要な設定項目を把握しやすくなり、秘密情報をGitに含める事故も減らせます。

11-4. デスクトップアプリでの使い分け

デスクトップアプリの場合、対象フレームワークによって使い分けが変わります。

.NET FrameworkのWindows FormsやWPFであれば、App.config を使うケースが多いです。

XML
<appSettings>
<add key="Theme" value="Light" />
<add key="WindowWidth" value="1024" />
</appSettings>

.NET 6以降のWPFやWindows Formsであれば、appsettings.jsonIConfiguration を使う構成も可能です。

ユーザーごとの設定、たとえばウィンドウ位置、テーマ、最近開いたファイルなどは、アプリケーション設定とは別に、ユーザープロファイル配下のファイルやアプリ設定機能で管理することもあります。

デスクトップアプリでは、サーバーアプリと違い、利用者の端末上にファイルが配置されます。そのため、秘密情報をクライアント側に置く設計には特に注意が必要です。

11-5. Webアプリ・APIでの使い分け

WebアプリやAPIでは、appsettings.json、環境別JSON、環境変数、シークレット管理を組み合わせるのが基本です。

おすすめは次の構成です。

appsettings.json
appsettings.Development.json
User Secrets
Environment Variables
Key Vault

ASP.NET Coreでは、WebApplication.CreateBuilder(args) によって設定、ログ、DIなどが統合されているため、builder.Configuration から設定を扱えます。

C#
var builder = WebApplication.CreateBuilder(args);

var apiUrl = builder.Configuration["ExternalApi:BaseUrl"];

小規模なWeb APIであれば IConfiguration で十分ですが、設定項目が増える場合はOptionsパターンに移行しましょう。

11-6. 迷ったときの判断基準

C#設定の管理方法で迷ったら、次の基準で判断すると分かりやすいです。

判断基準選択肢
.NET Frameworkの既存アプリかApp.config / Web.config
.NET Core/.NET 5以降の新規アプリかappsettings.json + IConfiguration
環境ごとに変わるかappsettings.{Environment}.json または環境変数
秘密情報かUser Secrets、環境変数、Key Vault
本番の高機密情報かKey Vaultなど外部シークレット管理
一時的に変えたいかコマンドライン引数
型安全に扱いたいかOptionsパターン

最も重要なのは、「どこに置くか」よりも「何を置いてよいか」を判断することです。公開可能な設定と秘密情報を分けるだけでも、C#設定管理の安全性は大きく向上します。

12. C#設定でよくあるエラーと解決方法

12-1. appsettings.jsonが読み込まれない

appsettings.json が読み込まれない原因として多いのは、ファイルが出力ディレクトリにコピーされていないことです。

コンソールアプリで次のように読み込んでいるとします。

C#
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();

この場合、実行時には bin/Debug/... 配下に appsettings.json が存在する必要があります。

.csproj に次の設定を追加します。

XML
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

また、ファイル名の大文字小文字にも注意しましょう。Windowsでは問題にならなくても、Linux環境では appsettings.jsonAppSettings.json は別ファイルとして扱われます。

12-2. 環境別の設定が反映されない

appsettings.Development.json が反映されない場合は、まず環境名を確認します。

C#
Console.WriteLine(builder.Environment.EnvironmentName);

期待通り Development になっていなければ、環境変数を設定します。

Bash
export ASPNETCORE_ENVIRONMENT=Development

また、ファイル名が環境名と一致しているか確認してください。

appsettings.Development.json

Development のスペルが違う、余計な空白がある、develop のように小文字になっている、といったミスでも読み込まれません。

ASP.NET Coreでは、環境名は DOTNET_ENVIRONMENTASPNETCORE_ENVIRONMENT から決まります。実行中に環境名を変更することはできないため、起動前に正しく設定する必要があります。

12-3. 環境変数で上書きできない

環境変数で設定を上書きできない場合は、キー名の書き方を確認しましょう。

JSONでは次のような階層構造だったとします。

JSON
{
"ExternalApi": {
"BaseUrl": "https://api.example.com"
}
}

環境変数では、次のようにダブルアンダースコアを使います。

Bash
export ExternalApi__BaseUrl="https://override.example.com"

C#側では次のキーで取得できます。

C#
var baseUrl = configuration["ExternalApi:BaseUrl"];

また、ConfigurationBuilderAddEnvironmentVariables() を追加しているか確認してください。

C#
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.Build();

順番も重要です。環境変数でJSONの値を上書きしたいなら、AddEnvironmentVariables()AddJsonFile() より後に追加します。

12-4. 接続文字列が取得できない

接続文字列が取得できない場合は、ConnectionStrings セクションに正しく書かれているか確認します。

JSON
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=SampleDb;Trusted_Connection=True;"
}
}

取得するコードは次の通りです。

C#
var connectionString = configuration.GetConnectionString("DefaultConnection");

よくある間違いは、セクション名を単数形にしてしまうことです。

JSON
{
"ConnectionString": {
"DefaultConnection": "..."
}
}

この場合、GetConnectionString("DefaultConnection") では取得できません。慣例通り ConnectionStrings にしましょう。

環境変数で上書きする場合は、次のようにします。

Bash
export ConnectionStrings__DefaultConnection="Server=prod;Database=ProdDb;User Id=app;Password=secret;"

12-5. nullが返ってくる原因

設定値を取得したときに null が返る原因は、主に次のどれかです。

原因確認ポイント
キー名が違うExternalApi:BaseUrl のスペル
ファイルが読み込まれていない出力ディレクトリに存在するか
環境名が違うDevelopment になっているか
環境変数名が違う__ を使っているか
設定ソースの順番が違う後勝ちになっているか
JSONの構文エラーカンマや引用符が正しいか

原因調査では、まず設定値を直接出力して確認します。

C#
Console.WriteLine(configuration["ExternalApi:BaseUrl"]);

セクション全体を確認したい場合は、次のように子要素を列挙できます。

C#
foreach (var child in configuration.GetSection("ExternalApi").GetChildren())
{
Console.WriteLine($"{child.Key} = {child.Value}");
}

12-6. デプロイ後だけ設定が変わらない原因

ローカルでは動くのにデプロイ後だけ設定が変わらない場合、次の点を確認しましょう。

まず、デプロイ先の環境変数が正しく設定されているか確認します。クラウド環境では、ポータル上で設定した後にアプリの再起動が必要になる場合があります。

次に、Dockerイメージに古い appsettings.json が含まれていないか確認します。イメージを再ビルドしていない場合、古い設定ファイルのまま動いている可能性があります。

また、Linux環境ではファイル名の大文字小文字が区別されます。

appsettings.Production.json

appsettings.production.json

は同じではありません。

最後に、どの設定ソースが最終的に使われているかを確認するため、起動時に環境名や重要な非機密設定をログ出力すると原因を追いやすくなります。ただし、接続文字列やAPIキーそのものをログに出してはいけません。

13. C#設定に関するよくある質問

13-1. appsettings.jsonとApp.configはどちらを使うべき?

新規開発で .NET Core/.NET 5以降を使うなら、基本的には appsettings.jsonIConfiguration を使うのがおすすめです。

一方、.NET Frameworkの既存アプリを保守している場合は、App.configWeb.config を使うのが自然です。Microsoftの .NET Framework向けドキュメントでも、App.configappSettings から ConfigurationManager.AppSettings で値を読み取る方法が説明されています。

判断基準はシンプルです。

アプリの種類おすすめ
.NET FrameworkApp.config / Web.config
ASP.NET Coreappsettings.json
.NET 5以降のコンソールアプリappsettings.json + IConfiguration
新規Web APIappsettings.json + Optionsパターン

13-2. appsettings.jsonにパスワードを書いてもよい?

原則として書くべきではありません。

特に本番DBのパスワード、APIキー、OAuthクライアントシークレット、JWT署名キーなどは、appsettings.json に直接書かないでください。設定ファイルはGitに含まれやすく、漏えいリスクがあります。

開発環境ではUser Secrets、本番環境では環境変数やAzure Key Vaultなどのシークレット管理サービスを使うのが安全です。Microsoftのドキュメントでも、機密情報はソースコードや設定ファイルに保存しないことが推奨されています。

13-3. 環境変数とappsettings.jsonはどちらが優先される?

設定ソースの追加順によります。

一般的には、appsettings.json を先に読み込み、その後に環境変数を読み込むため、同じキーがある場合は環境変数が優先されます。

C#
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.Build();

この場合、環境変数が appsettings.json の値を上書きします。

ASP.NET Coreの既定構成でも、複数の設定ソースが組み合わされ、後から登録された設定ソースが既存の値より優先される構成になります。User SecretsもJSONファイルより後に登録されるため、appsettings.json より優先されます。

13-4. Windowsアプリでもappsettings.jsonは使える?

はい、使えます。

.NET 6以降のWindows FormsやWPFアプリでも、必要なパッケージを追加すれば appsettings.jsonIConfiguration を利用できます。

例は次の通りです。

C#
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();

var theme = configuration["Theme"];

ただし、.NET Frameworkの既存Windowsアプリでは、App.config を使っているケースが多いため、既存設計との整合性を考えて選びましょう。

13-5. configファイルは今でも使われている?

はい、使われています。

特に .NET FrameworkのWindows Forms、WPF、Windowsサービス、ASP.NET Web Forms、ASP.NET MVCなどでは、App.configWeb.config が今でも使われています。

ただし、モダンな .NETアプリでは、appsettings.jsonIConfiguration、Optionsパターンを使う設計が一般的です。既存アプリの保守ではconfigファイル、新規開発ではappsettings、という使い分けが分かりやすいです。

13-6. 設定値を実行中に変更することはできる?

一部の設定は実行中に変更できます。

AddJsonFilereloadOnChange: true を指定すると、JSONファイル変更時に設定を再読み込みできる場合があります。

C#
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)

ただし、設定を再読み込みできても、アプリケーション側がその変更を反映する設計になっていなければ意味がありません。IOptions<T> は基本的に起動時の値を使うため、実行中の変更を扱いたい場合は IOptionsMonitor<T> を検討します。

C#
public class MyService
{
private readonly IOptionsMonitor<MyOptions> _options;

public MyService(IOptionsMonitor<MyOptions> options)
{
_options = options;
}

public string GetValue()
{
return _options.CurrentValue.SomeValue;
}
}

ただし、DB接続先や認証設定など、実行中に変えると危険な設定もあります。すべての設定を動的変更可能にするのではなく、変更してよい設定と再起動が必要な設定を分けて設計しましょう。

まとめ

C#設定を正しく管理することは、保守性、セキュリティ、運用性の高いアプリケーションを作るうえで欠かせません。

.NET Frameworkでは App.configWeb.config、.NET Core/.NET 5以降では appsettings.jsonIConfiguration が設定管理の中心になります。さらに、環境ごとの差分には appsettings.{Environment}.json、本番環境の上書きには環境変数、開発時の秘密情報にはUser Secrets、高機密の本番シークレットにはAzure Key Vaultなどの外部シークレット管理を使うと、安全で柔軟な構成になります。

基本の考え方は次の通りです。

用途推奨される管理方法
共通の既定値appsettings.json
環境ごとの差分appsettings.{Environment}.json
.NET Frameworkの設定App.config / Web.config
本番環境の上書き環境変数
開発時の秘密情報User Secrets
本番の高機密情報Azure Key Vaultなど
型安全な設定利用Optionsパターン

C#設定で大切なのは、設定値をただ外部ファイルに出すことではありません。公開してよい値、環境ごとに変わる値、秘密にすべき値を分け、適切な場所に配置することです。

小規模なアプリでは appsettings.jsonIConfiguration から始め、設定項目が増えてきたらOptionsパターンを導入しましょう。本番環境では、パスワードやAPIキーを設定ファイルに書かず、環境変数やシークレット管理サービスを使うことが重要です。

C#設定の基本を押さえておけば、開発環境と本番環境の切り替え、セキュアな秘密情報管理、クラウドやDockerへのデプロイがスムーズになります。C#アプリケーションを長く安全に運用するためにも、最初の設計段階から設定管理の方針を決めておきましょう。