次の方法で共有


ASP.NET Core Blazor の構成

Note

これは、この記事の最新バージョンではありません。 現在のリリースについては、 この記事の .NET 10 バージョンを参照してください。

警告

このバージョンの ASP.NET Core はサポートされなくなりました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、 この記事の .NET 10 バージョンを参照してください。

この記事では、アプリの設定、認証、ログの構成など、Blazor アプリの構成方法について説明します。

このガイダンスは、Blazor Web App またはスタンドアロン Blazor WebAssembly アプリのクライアント側プロジェクト構成に適用されます。

Blazor Web App での既定の動作:

  • サーバー側構成の場合:
    • ガイダンスについては、「ASP.NET Core における構成」を参照してください。
    • プロジェクトのルート アプリ設定ファイル内の構成のみ読み込まれます。
    • この記事の残りの部分は、.Client プロジェクトのクライアント側構成にのみ適用されます。
  • クライアント側構成 (.Client プロジェクト) では、構成は既定で次のアプリ設定ファイルから読み込まれます。
    • wwwroot/appsettings.json
    • wwwroot/appsettings.{ENVIRONMENT}.json。ここで、{ENVIRONMENT} プレースホルダーはアプリのランタイム環境です。

スタンドアロン Blazor WebAssembly アプリでは、構成は既定で次のアプリ設定ファイルから読み込まれます。

  • wwwroot/appsettings.json
  • wwwroot/appsettings.{ENVIRONMENT}.json。ここで、{ENVIRONMENT} プレースホルダーはアプリのランタイム環境です。

このガイダンスは、ホストされている Client ソリューションまたは Blazor WebAssembly アプリの Blazor WebAssembly プロジェクトに適用されます。

ホストされた Server ソリューションの Blazor WebAssembly プロジェクトのサーバー側 ASP.NET Core アプリの構成については、「ASP.NET Core における構成」を参照してください。

クライアント側では、次のアプリ設定ファイルから構成が読み込まれます。

  • wwwroot/appsettings.json
  • wwwroot/appsettings.{ENVIRONMENT}.json。ここで、{ENVIRONMENT} プレースホルダーはアプリのランタイム環境です。

Note

wwwroot のアプリ設定ファイルに配置されたログ構成は、既定では読み込まれません。 詳しくは、後の「ログの構成」セクションをご覧ください。

Azure サービスを使用する場合など、一部のシナリオでは、環境名と正確に一致する環境ファイル名セグメントを使用することが重要です。 たとえば、appsettings.Staging.json 環境には大文字 "S" を含むファイル名 Staging を使用します。 推奨される規則については、「ASP.NET Core Blazor 環境」の冒頭の解説を参照してください。

アプリによって登録されたその他の構成プロバイダーで構成を指定することもできますが、すべてのプロバイダーやプロバイダーの機能が適しているわけではありません。

  • Azure Key Vault 構成プロバイダーの: プロバイダーは、クライアント シークレットシナリオでのマネージド ID とアプリケーション ID (クライアント ID) ではサポートされていません。 クライアント シークレットを使用したアプリケーション ID は、ASP.NET Core アプリ、特にクライアント側のアプリでは推奨されません。これは、クライアント シークレットを Azure Key Vault サービスにアクセスするためにクライアント側ではセキュリティで保護できないためです。
  • Azure App Configuration プロバイダー: このプロバイダーはクライアント側アプリに適していません。これは、このアプリが Azure 内のサーバー上では実行されないためです。

構成プロバイダーについて詳しくは、「ASP.NET Core での構成」を参照してください。

警告

Web ルート (wwwroot フォルダー) 内の構成ファイルと設定ファイルはクライアント上のユーザーに表示されるため、ユーザーがデータを改ざんする可能性があります。 アプリ シークレット、資格情報、その他の機密データを Web ルート ファイルに保存しないでください。

アプリ設定の構成

アプリ設定ファイルの構成は既定で読み込まれます。 次の例では、UI 構成値がアプリ設定ファイルに格納され、Blazor フレームワークによって自動的に読み込まれます。 その値はコンポーネントによって読み取られます。

wwwroot/appsettings.json:

{
    "h1FontSize": "50px"
}

構成データにアクセスするために、コンポーネントに IConfiguration インスタンスを挿入します。

ConfigExample.razor:

@page "/config-example"
@inject IConfiguration Configuration

<PageTitle>Configuration</PageTitle>

<h1 style="font-size:@Configuration["h1FontSize"]">
    Configuration example (50px)
</h1>
@page "/config-example"
@inject IConfiguration Configuration

<PageTitle>Configuration</PageTitle>

<h1 style="font-size:@Configuration["h1FontSize"]">
    Configuration example (50px)
</h1>
@page "/config-example"
@inject IConfiguration Configuration

<h1 style="font-size:@Configuration["h1FontSize"]">
    Configuration example
</h1>
@page "/config-example"
@inject IConfiguration Configuration

<h1 style="font-size:@Configuration["h1FontSize"]">
    Configuration example
</h1>
@page "/config-example"
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<h1 style="font-size:@Configuration["h1FontSize"]">
    Configuration example
</h1>
@page "/config-example"
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<h1 style="font-size:@Configuration["h1FontSize"]">
    Configuration example
</h1>

クライアントのセキュリティ制限により、アプリ構成の設定ファイルなどのファイルへのユーザー コードからの直接アクセスが防止されます。 appsettings.json / appsettings.{ENVIRONMENT}.json に加えて構成ファイルを wwwroot フォルダーから構成に読み取るには、HttpClient を使用します。

警告

Web ルート (wwwroot フォルダー) 内の構成ファイルと設定ファイルはクライアント上のユーザーに表示されるため、ユーザーがデータを改ざんする可能性があります。 アプリ シークレット、資格情報、その他の機密データを Web ルート ファイルに保存しないでください。

次の例では、構成ファイル (cars.json) をアプリの構成に読み取ります。

wwwroot/cars.json:

{
    "size": "tiny"
}

Microsoft.Extensions.Configuration ファイルに Program の名前空間を追加します。

using Microsoft.Extensions.Configuration;

クライアントを使用してファイルを読み取るように、既存の HttpClient サービス登録を変更します。

var http = new HttpClient()
{
    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
};

builder.Services.AddScoped(sp => http);

using var response = await http.GetAsync("cars.json");
using var stream = await response.Content.ReadAsStreamAsync();

builder.Configuration.AddJsonStream(stream);

上記の例では builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress) を使用してベース アドレスを設定しています。これにより、アプリのベース アドレスが取得されますが、通常、ホスト ページの <base> タグの href 値に由来するものになります。

メモリ構成のソース

次の例では、MemoryConfigurationSource ファイルの Program を使用して追加の構成を指定します。

Microsoft.Extensions.Configuration.Memory ファイルに Program の名前空間を追加します。

using Microsoft.Extensions.Configuration.Memory;

Program ファイルで次の操作を行います。

var vehicleData = new Dictionary<string, string?>()
{
    { "color", "blue" },
    { "type", "car" },
    { "wheels:count", "3" },
    { "wheels:brand", "Blazin" },
    { "wheels:brand:type", "rally" },
    { "wheels:year", "2008" },
};

var memoryConfig = new MemoryConfigurationSource { InitialData = vehicleData };

builder.Configuration.Add(memoryConfig);

構成データにアクセスするために、コンポーネントに IConfiguration インスタンスを挿入します。

MemoryConfig.razor:

@page "/memory-config"
@inject IConfiguration Configuration

<PageTitle>Memory Configuration</PageTitle>

<h1>Memory Configuration Example</h1>

<h2>General specifications</h2>

<ul>
    <li>Color: @Configuration["color"]</li>
    <li>Type: @Configuration["type"]</li>
</ul>

<h2>Wheels</h2>

<ul>
    <li>Count: @Configuration["wheels:count"]</li>
    <li>Brand: @Configuration["wheels:brand"]</li>
    <li>Type: @Configuration["wheels:brand:type"]</li>
    <li>Year: @Configuration["wheels:year"]</li>
</ul>
@page "/memory-config"
@inject IConfiguration Configuration

<PageTitle>Memory Configuration</PageTitle>

<h1>Memory Configuration Example</h1>

<h2>General specifications</h2>

<ul>
    <li>Color: @Configuration["color"]</li>
    <li>Type: @Configuration["type"]</li>
</ul>

<h2>Wheels</h2>

<ul>
    <li>Count: @Configuration["wheels:count"]</li>
    <li>Brand: @Configuration["wheels:brand"]</li>
    <li>Type: @Configuration["wheels:brand:type"]</li>
    <li>Year: @Configuration["wheels:year"]</li>
</ul>
@page "/memory-config"
@inject IConfiguration Configuration

<h1>Memory configuration example</h1>

<h2>General specifications</h2>

<ul>
    <li>Color: @Configuration["color"]</li>
    <li>Type: @Configuration["type"]</li>
</ul>

<h2>Wheels</h2>

<ul>
    <li>Count: @Configuration["wheels:count"]</li>
    <li>Brand: @Configuration["wheels:brand"]</li>
    <li>Type: @Configuration["wheels:brand:type"]</li>
    <li>Year: @Configuration["wheels:year"]</li>
</ul>
@page "/memory-config"
@inject IConfiguration Configuration

<h1>Memory configuration example</h1>

<h2>General specifications</h2>

<ul>
    <li>Color: @Configuration["color"]</li>
    <li>Type: @Configuration["type"]</li>
</ul>

<h2>Wheels</h2>

<ul>
    <li>Count: @Configuration["wheels:count"]</li>
    <li>Brand: @Configuration["wheels:brand"]</li>
    <li>Type: @Configuration["wheels:brand:type"]</li>
    <li>Year: @Configuration["wheels:year"]</li>
</ul>
@page "/memory-config"
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<h1>Memory configuration example</h1>

<h2>General specifications</h2>

<ul>
    <li>Color: @Configuration["color"]</li>
    <li>Type: @Configuration["type"]</li>
</ul>

<h2>Wheels</h2>

<ul>
    <li>Count: @Configuration["wheels:count"]</li>
    <li>Brand: @Configuration["wheels:brand"]</li>
    <li>Type: @Configuration["wheels:brand:type"]</li>
    <li>Year: @Configuration["wheels:year"]</li>
</ul>
@page "/memory-config"
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<h1>Memory configuration example</h1>

<h2>General specifications</h2>

<ul>
    <li>Color: @Configuration["color"]</li>
    <li>Type: @Configuration["type"]</li>
</ul>

<h2>Wheels</h2>

<ul>
    <li>Count: @Configuration["wheels:count"]</li>
    <li>Brand: @Configuration["wheels:brand"]</li>
    <li>Type: @Configuration["wheels:brand:type"]</li>
    <li>Year: @Configuration["wheels:year"]</li>
</ul>

IConfiguration.GetSectionで C# コード内の構成セクションを取得します。 次の例では、前の例の構成の wheels セクションを取得します。

@code {
    protected override void OnInitialized()
    {
        var wheelsSection = Configuration.GetSection("wheels");

        ...
    }
}

認証の構成

アプリ設定ファイルでパブリック認証構成を指定します。

wwwroot/appsettings.json:

{
  "Local": {
    "Authority": "{AUTHORITY}",
    "ClientId": "{CLIENT ID}"
  }
}

Identity ファイルで ConfigurationBinder.Bind を使用して、Program プロバイダーの構成を読み込みます。 次の例では、OIDC プロバイダーの構成を読み込みます。

builder.Services.AddOidcAuthentication(options =>
    builder.Configuration.Bind("Local", options.ProviderOptions));

警告

Web ルート (wwwroot フォルダー) 内の構成ファイルと設定ファイルはクライアント上のユーザーに表示されるため、ユーザーがデータを改ざんする可能性があります。 アプリ シークレット、資格情報、その他の機密データを Web ルート ファイルに保存しないでください。

ログの構成

このセクションは、wwwroot フォルダー内のアプリ設定ファイルを使用してログを構成するアプリに適用されます。

アプリに Microsoft.Extensions.Logging.Configuration パッケージを追加します。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。

アプリ設定ファイルで、ログ構成を指定します。 ログ構成は Program ファイルに読み込まれます。

wwwroot/appsettings.json:

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

Program ファイルで次の操作を行います。

builder.Logging.AddConfiguration(
    builder.Configuration.GetSection("Logging"));

ホスト ビルダーの構成

WebAssemblyHostBuilder.Configuration ファイルの Program からホスト ビルダーの構成を読み取ります。

var hostname = builder.Configuration["HostName"];

キャッシュされた構成

構成ファイルは、オフラインで使用できるようにキャッシュされます。 プログレッシブ Web アプリケーション (PWA) では、新しい展開を作成するときにのみ構成ファイルを更新できます。 次の理由により、展開間で構成ファイルを編集しても意味がありません。

  • ユーザーには、引き続き使用するファイルのキャッシュされたバージョンがあります。
  • PWA の service-worker.jsservice-worker-assets.js のファイルは、コンパイル時に再構築される必要があります。これにより、ユーザーの次回のオンライン アクセス時に、アプリが再展開されたことが通知されます。

PWA によるバックグラウンド更新の処理方法について詳しくは、「ASP.NET Core Blazor プログレッシブ Web アプリケーション (PWA)」をご覧ください。

オプションの構成

オプションの構成では、Microsoft.Extensions.Options.ConfigurationExtensions NuGet パッケージに対するパッケージ参照を追加する必要があります。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。

例:

OptionsExample.cs:

public class OptionsExample
{
    public string? Option1 { get; set; }
    public string? Option2 { get; set; }
}

appsettings.jsonで:

"OptionsExample": {
  "Option1": "Option1 Value",
  "Option2": "Option2 Value"
}
builder.Services.Configure<OptionsExample>(
    builder.Configuration.GetSection("OptionsExample"));

次の Razor コンポーネントは、@inject ディレクティブまたは [Inject] 属性を使用して設定を取得します。

Options.razor:

@page "/options"
@using Microsoft.Extensions.Options
@inject IOptions<OptionsExample>? OptionsExample1

<h1>Options</h1>

<h2>
    &commat;inject approach
</h2>

<ul>
    <li>@OptionsExample1?.Value.Option1</li>
    <li>@OptionsExample1?.Value.Option2</li>
</ul>

<h2>
    [Inject] approach
</h2>

<ul>
    <li>@OptionsExample2?.Value.Option1</li>
    <li>@OptionsExample2?.Value.Option2</li>
</ul>

@code {
    [Inject]
    public IOptions<OptionsExample>? OptionsExample2 { get; set; }
}

ASP.NET Core オプションのすべての機能が、Razor コンポーネントでサポートされているわけではありません。 たとえば、IOptionsSnapshot<TOptions>IOptionsMonitor<TOptions> の構成はサポートされていますが、これらのインターフェイスのオプション値の再計算は、新しいブラウザー タブでアプリを要求するか、ブラウザーの再読み込みボタンを選択することによるアプリの再読み込み以外では、サポートされません。 基になる構成が変更されたとき、StateHasChanged を呼び出すだけでは、スナップショットまたは監視対象のオプション値は更新されません。