zukucode
主にWEB関連の情報を技術メモとして発信しています。

ASP.NET Core IOptionsでappsettings.jsonの設定値を読み込む

ASP.NET Coreでは、アプリケーションの設定をappsettings.jsonへ記述できます。

IOptions<T>を使用すると、設定値を文字列のキーで毎回取得せず、C#のクラスとして読み込めます。

今回はサイト名と問い合わせ先を設定し、Controllerから取得する方法を紹介します。

文字列キーで直接取得する方法もありますが、キーのタイプミスや変換失敗が実行するまで分かりません。IOptions<T>を選ぶ理由は、関連する設定を1つの型へまとめ、利用箇所を型付きにし、必要な設定を起動時に検証できるためです。

appsettings.jsonへ設定を書く

Siteというセクションを追加します。

appsettings.json
{
  "Site": {
    "Name": "サンプルショップ",
    "ContactEmail": "support@example.com",
    "ItemsPerPage": 20
  }
}

設定を用途ごとのセクションへまとめると、項目が増えても管理しやすくなります。

設定用のクラスを作成する

JSONの項目と対応するプロパティを定義します。

SiteOptions.cs
public sealed class SiteOptions
{
    public const string SectionName = "Site";

    public string Name { get; init; } = string.Empty;
    public string ContactEmail { get; init; } = string.Empty;
    public int ItemsPerPage { get; init; }
}

SectionNameを定数にすると、登録時に"Site"という文字列を直接書かずに済みます。

プロパティ名は、appsettings.jsonの項目名に対応させます。大文字と小文字は区別されません。

Program.csで登録する

Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<SiteOptions>(
    builder.Configuration.GetSection(SiteOptions.SectionName)
);

builder.Services.AddControllers();

var app = builder.Build();
app.MapControllers();
app.Run();

Configure<SiteOptions>で、SiteセクションをSiteOptionsへ結び付けます。

Controllerから読み込む

コンストラクターでIOptions<SiteOptions>を受け取ります。

SiteController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

[ApiController]
[Route("api/site")]
public sealed class SiteController(IOptions<SiteOptions> options) : ControllerBase
{
    private readonly SiteOptions _siteOptions = options.Value;

    [HttpGet]
    public IActionResult Find()
    {
        return Ok(new
        {
            _siteOptions.Name,
            _siteOptions.ContactEmail,
            _siteOptions.ItemsPerPage,
        });
    }
}

設定の値はoptions.Valueから取得します。

DIによってIOptions<SiteOptions>が自動でControllerへ渡されます。

起動時に設定値を検証する

必須の値が空の場合や件数が不正な場合は、起動時に検出できます。

検証を追加する
builder.Services
    .AddOptions<SiteOptions>()
    .Bind(builder.Configuration.GetSection(SiteOptions.SectionName))
    .Validate(
        options => !string.IsNullOrWhiteSpace(options.Name),
        "Site:Nameは必須です。"
    )
    .Validate(
        options => options.ItemsPerPage > 0,
        "Site:ItemsPerPageは1以上にしてください。"
    )
    .ValidateOnStart();

この書き方を使用する場合は、前に記載したConfigure<SiteOptions>の代わりに登録します。

ValidateOnStartを付けると、設定を初めて使用したときではなく、アプリケーションの起動時に確認できます。

開発環境だけ設定を変える

開発環境ではappsettings.Development.jsonの値で上書きできます。

appsettings.Development.json
{
  "Site": {
    "Name": "サンプルショップ 開発環境",
    "ContactEmail": "developer@example.com"
  }
}

記載していないItemsPerPageは、元のappsettings.jsonの値が使用されます。

パスワードはappsettings.jsonへ保存しない

データベースのパスワードやAPIキーを、Gitで管理するappsettings.jsonへ書くことは避けます。

開発環境ではUser Secrets、本番環境では環境変数やクラウドのシークレット管理サービスなどを使用します。

環境変数で階層を表す場合は、区切りに__を使用します。

Site__Name="本番ショップ"
Site__ItemsPerPage="50"

IOptions<T>は基本的に起動時の設定を使用します。実行中の変更を読み取りたい場合はIOptionsMonitor<T>などを検討します。

IOptions<T>を使うと、設定項目を型付きのクラスへまとめられ、入力補完や起動時の検証を利用できます。


関連記事