ASP.NET Core BlazorSignalR ガイダンス

この記事では、Blazor アプリで SignalR 接続を構成および管理する方法について説明します。

ASP.NET Core SignalR の構成の一般的なガイダンスについては、ドキュメントの ASP.NET Core SignalR の概要に関するトピックをご覧ください。 ホステッド Blazor WebAssembly ソリューションに追加されたSignalR を構成する方法については、「ASP.NET Core SignalR の構成」をご覧ください。

認証のための SignalR のクロスオリジン ネゴシエーション (Blazor WebAssembly)

cookie や HTTP 認証ヘッダーなどの資格情報を送信するように SignalR の基となるクライアントを構成するには:

  • SetBrowserRequestCredentials を使用して、クロスオリジン fetch 要求に Include を設定します。

    IncludeRequestCredentialsMessageHandler.cs:

    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Components.WebAssembly.Http;
    
    public class IncludeRequestCredentialsMessageHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
        {
            request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
            return base.SendAsync(request, cancellationToken);
        }
    }
    
  • ハブ接続が構築されている場合は、HttpMessageHandlerHttpMessageHandlerFactory オプションに割り当てます。

    private HubConnectionBuilder? hubConnection;
    
    ...
    
    hubConnection = new HubConnectionBuilder()
        .WithUrl(new Uri(NavigationManager.ToAbsoluteUri("/chathub")), options =>
        {
            options.HttpMessageHandlerFactory = innerHandler => 
                new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler };
        }).Build();
    

    前の例では、ハブ接続 URL を /chathub の絶対 URI アドレスに構成しています。これは、Index コンポーネント (Pages/Index.razor) の Blazor と SignalR のチュートリアルで使用されている URL です。 URI は、文字列 (https://signalr.example.com など) または構成を使用して設定することもできます。

詳しくは、「ASP.NET Core SignalR の構成」をご覧ください。

レンダリング モード (Blazor WebAssembly)

プリレンダリングするために SignalR を使用する Blazor WebAssembly アプリがサーバーに構成されている場合、サーバーへのクライアント接続が確立される前に、プリレンダリングが行われます。 詳細については、次の記事を参照してください。

Blazor WebAssembly アプリに関するその他のリソース

webfarm ホスティングにスティッキー セッションを使う (Blazor Server)

最初のクライアント要求への応答として、Blazor Server アプリによってプリレンダリングされます。これにより、サーバー上で UI の状態が作成されます。 クライアントで SignalR 接続の作成が再試行される際は、クライアントを同じサーバーに再接続する必要があります。 複数のバックエンド サーバーを使用する Blazor Server アプリでは、SignalR 接続に "スティッキー セッション" を実装する必要があります。

Note

Webfarm でスティッキー セッションを有効にしていないアプリからは次のエラーがスローされます。

blazor.server.js:1 Uncaught (in promise) Error: Invocation canceled due to the underlying connection being closed. (blazor.server.js:1 捕捉されない (promise 内の) エラー: 基となる接続が閉じられたため、呼び出しが取り消されました。)

Azure SignalR Service (Blazor Server)

Microsoft Azure でホストされている Blazor Server アプリには、Azure SignalR Service を使用することをお勧めします。 このサービスはアプリの Blazor Hub と連携して、Blazor Server アプリを多数の SignalR 同時接続にスケールアップします。 さらに、SignalR Service のグローバル リーチとハイパフォーマンスのデータ センターは、地理的条件による待機時間の短縮に役立ちます。

Azure SignalR サービスでは、サービスの ServerStickyMode オプションまたは構成値を Required に設定することにより、スティッキー セッションが有効になります。 詳細については、「ASP.NET Core Blazor Server のホストと展開」を参照してください。

Blazor Server アプリの回線ハンドラーのオプション

次の表に示す CircuitOptions を使用して Blazor Server の回線を構成してください。

オプション Default 説明
DetailedErrors false 回線でハンドルされない例外が発生した場合、または JS 相互運用機能を介した .NET メソッドの呼び出しの結果として例外が発生した場合に、詳細な例外メッセージを JavaScript に送信します。
DisconnectedCircuitMaxRetained 100 サーバーが一度にメモリに保持する切断された回線の最大数。
DisconnectedCircuitRetentionPeriod 3 分 切断された回線が破棄されるまでにメモリに保持される最大時間。
JSInteropDefaultCallTimeout 1 分 非同期の JavaScript 関数呼び出しがタイムアウトするまでにサーバーが待機する最大時間。
MaxBufferedUnacknowledgedRenderBatches 10 堅牢な再接続をサポートするために、サーバーが一定期間、メモリに保持する回線あたりの未確認のレンダリング バッチの最大数。 制限に達すると、クライアントによって 1 つ以上のバッチが確認されるまで、サーバーにより新しいレンダリング バッチの生成が停止されます。

オプションの AddServerSideBlazor へのデリゲートを使用して Program.cs のオプションを構成します。 次の例では、前の表に示した既定のオプション値を割り当てます。 Program.csSystem 名前空間が使用されていることを確認します (using System;)。

Program.csの場合:

builder.Services.AddServerSideBlazor(options =>
{
    options.DetailedErrors = false;
    options.DisconnectedCircuitMaxRetained = 100;
    options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3);
    options.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(1);
    options.MaxBufferedUnacknowledgedRenderBatches = 10;
});

HubConnectionContext を構成するには、HubConnectionContextOptions と共に AddHubOptions を使用します。 オプションの説明については、「ASP.NET Core SignalR の構成」をご覧ください。 次の例では、既定のオプション値を割り当てます。 Program.csSystem 名前空間が使用されていることを確認します (using System;)。

Program.csの場合:

builder.Services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
        options.EnableDetailedErrors = false;
        options.HandshakeTimeout = TimeSpan.FromSeconds(15);
        options.KeepAliveInterval = TimeSpan.FromSeconds(15);
        options.MaximumParallelInvocationsPerClient = 1;
        options.MaximumReceiveMessageSize = 32 * 1024;
        options.StreamBufferCapacity = 10;
    });

Blazor Hub のエンドポイント ルートの構成 (Blazor Server)

Program.cs で、Blazor Server アプリによって MapBlazorHub が呼び出され、BlazorHub がアプリの既定のパスにマップされます。 Blazor Server スクリプト (blazor.server.js) は、MapBlazorHub によって作成されたエンドポイントを自動的に指します。

UI に接続状態を反映する (Blazor Server)

接続が失われたことがクライアントで検出されると、クライアントによって再接続が試行される間、ユーザーに対して既定の UI が表示されます。 再接続に失敗した場合、ユーザーには再試行のオプションが表示されます。

UI をカスタマイズするには、_Layout.cshtmlRazor ページの <body> に、components-reconnect-modalid を持つ要素を定義します。

Pages/_Layout.cshtml:

<div id="components-reconnect-modal">
    ...
</div>

次の CSS スタイルをサイトのスタイルシートに追加します。

wwwroot/css/site.css:

#components-reconnect-modal {
    display: none;
}

#components-reconnect-modal.components-reconnect-show {
    display: block;
}

次の表で、Blazor フレームワークによってcomponents-reconnect-modal 要素に適用される CSS クラスについて説明します。

CSS クラス 示す内容...
components-reconnect-show 接続が失われました。 クライアントによって再接続が試行されています。 モーダルを表示します。
components-reconnect-hide サーバーへのアクティブな接続が再確立されます。 モーダルを非表示にします。
components-reconnect-failed 再接続に失敗しました。ネットワーク障害が原因である可能性があります。 再接続を試みるには、JavaScript で window.Blazor.reconnect() を呼び出します。
components-reconnect-rejected 再接続が拒否されました。 サーバーに到達したが接続が拒否されたため、サーバー上のユーザーの状態が失われました。 アプリを再度読み込むには、JavaScript で location.reload() を呼び出します。 この接続状態は、次の場合に発生する可能性があります。
  • サーバー側回線でクラッシュが発生した場合。
  • クライアントが長時間切断されているため、サーバーでユーザーの状態が削除された場合。 ユーザーのコンポーネントのインスタンスは破棄されます。
  • サーバーが再起動されたか、アプリのワーカー プロセスがリサイクルされた場合。

モーダル要素に対して、サイトの CSS で transition-delay プロパティを設定して、再接続表示が表示されるまでの遅延時間をカスタマイズします。 次の例では、移行遅延時間を 500 ms (既定値) から 1,000 ms (1 秒) に設定しています。

wwwroot/css/site.css:

#components-reconnect-modal {
    transition: visibility 0s linear 1000ms;
}

レンダリング モード (Blazor Server)

既定では、サーバーへのクライアント接続が確立される前に、Blazor Server アプリによってサーバー上の UI がプリレンダリングされます。 詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。

Blazor の起動 (Blazor Server)

Pages/_Layout.cshtml ファイル内にある Blazor Server アプリの SignalR 回線の手動での起動を構成します。

  • blazor.server.js スクリプトの <script> タグに autostart="false" 属性を追加します。
  • Blazor.start を呼び出すスクリプトを、blazor.server.js スクリプトの <script> タグの後の終了 </body> タグ内に配置します。

autostart が無効になっている場合、回線に依存しないアプリのすべての側面が正常に動作します。 たとえば、クライアント側のルーティングは動作します。 ただし、回線に依存する側面はすべて、Blazor.start が呼び出されるまで動作しません。 回線が確立されていなければ、アプリの動作は予測不可能です。 たとえば、回線が切断されている間、コンポーネント メソッドは実行できません。

ドキュメントの準備ができたときに Blazor を初期化する方法や、JS Promise に連結する方法などについて詳しくは、「ASP.NET Core Blazor の起動」をご覧ください。

SignalR クライアント ログを構成する (Blazor Server)

クライアント ビルダーで、ログ レベルを指定して configureLogging を呼び出す configureSignalR 構成オブジェクトを渡します。

Pages/_Layout.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        configureSignalR: function (builder) {
          builder.configureLogging("information");
        }
      });
    </script>
</body>

前の例で、information はログ レベル LogLevel.Information と同じです。

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

再接続ハンドラーを変更する (Blazor Server)

再接続ハンドラーの回線接続イベントは、次のようなカスタム動作を行うように変更できます。

  • 接続が切断された場合にユーザーに通知する。
  • 回線が接続されているときに (クライアントから) ログ記録を実行する。

接続イベントを変更するには、次の接続の変更に対してコールバックを登録します。

  • 切断された接続では、onConnectionDown が使用されます。
  • 確立または再確立された接続では、onConnectionUp が使用されます。

onConnectionDownonConnectionUp の両方を指定する必要があります。

Pages/_Layout.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        reconnectionHandler: {
          onConnectionDown: (options, error) => console.error(error),
          onConnectionUp: () => console.log("Up, up, and away!")
        }
      });
    </script>
</body>

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

再接続の再試行回数と間隔を調整する (Blazor Server)

再接続の再試行の回数と間隔を調整するには、再試行の回数 (maxRetries) と、各再試行で許可されるミリ秒単位の期間 (retryIntervalMilliseconds) を設定します。

Pages/_Layout.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        reconnectionOptions: {
          maxRetries: 3,
          retryIntervalMilliseconds: 2000
        }
      });
    </script>
</body>

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

クライアントから Blazor 回線を切断する (Blazor Server)

既定では、unload ページ イベントがトリガーされると、Blazor 回線が切断されます。 クライアント上の他のシナリオで回線を切断するには、適切なイベント ハンドラーで Blazor.disconnect を呼び出します。 次の例では、ページが非表示になると、回線が切断されます (pagehide イベント)。

window.addEventListener('pagehide', () => {
  Blazor.disconnect();
});

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

Blazor Server 回線ハンドラー

Blazor Server を使用すると、コードで "回線ハンドラー" を定義できます。これにより、ユーザーの回線の状態の変更時にコードを実行できます。 回線ハンドラーは、CircuitHandler から派生させ、そのクラスをアプリのサービス コンテナーに登録することで実装します。 次の回線ハンドラーの例では、開いている SignalR 接続を追跡します。

TrackingCircuitHandler.cs:

using Microsoft.AspNetCore.Components.Server.Circuits;

public class TrackingCircuitHandler : CircuitHandler
{
    private HashSet<Circuit> circuits = new();

    public override Task OnConnectionUpAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Add(circuit);

        return Task.CompletedTask;
    }

    public override Task OnConnectionDownAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Remove(circuit);

        return Task.CompletedTask;
    }

    public int ConnectedCircuits => circuits.Count;
}

回線ハンドラーは DI を使用して登録されます。 スコープを持つインスタンスは、回線のインスタンスごとに作成されます。 前の例の TrackingCircuitHandler を使用すると、すべての回線の状態を追跡する必要があるため、シングルトン サービスが作成されます。

Program.cs:

builder.Services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();

カスタム回線ハンドラーのメソッドでハンドルされない例外がスローされる場合は、その例外は Blazor Server 回線にとって致命的です。 ハンドラーのコードまたはメソッドで例外が許容されるようにするには、エラー処理とログを含む 1 つ以上の try-catch ステートメントでコードをラップします。

ユーザーが切断し、フレームワークで回線の状態がクリーンアップされていることが原因で回線が終了すると、フレームワークによって回線の DI スコープが破棄されます。 スコープが破棄されると、System.IDisposable を実装するサーキットスコープの DI サービスはすべて破棄されます。 破棄中にいずれかの DI サービスでハンドルされない例外がスローされると、フレームワークによって例外がログに記録されます。 詳細については、「ASP.NET Core Blazor の依存関係の挿入」を参照してください。

Blazor Server アプリに関するその他のリソース

ASP.NET Core SignalR の構成の一般的なガイダンスについては、ドキュメントの ASP.NET Core SignalR の概要に関するトピックをご覧ください。 ホステッド Blazor WebAssembly ソリューションに追加されたSignalR を構成する方法については、「ASP.NET Core SignalR の構成」をご覧ください。

認証のための SignalR のクロスオリジン ネゴシエーション (Blazor WebAssembly)

cookie や HTTP 認証ヘッダーなどの資格情報を送信するように SignalR の基となるクライアントを構成するには:

  • SetBrowserRequestCredentials を使用して、クロスオリジン fetch 要求に Include を設定します。

    IncludeRequestCredentialsMessageHandler.cs:

    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Components.WebAssembly.Http;
    
    public class IncludeRequestCredentialsMessageHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
        {
            request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
            return base.SendAsync(request, cancellationToken);
        }
    }
    
  • ハブ接続が構築されている場合は、HttpMessageHandlerHttpMessageHandlerFactory オプションに割り当てます。

    HubConnectionBuilder hubConnection;
    
    ...
    
    hubConnection = new HubConnectionBuilder()
        .WithUrl(new Uri(NavigationManager.ToAbsoluteUri("/chathub")), options =>
        {
            options.HttpMessageHandlerFactory = innerHandler => 
                new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler };
        }).Build();
    

    前の例では、ハブ接続 URL を /chathub の絶対 URI アドレスに構成しています。これは、Index コンポーネント (Pages/Index.razor) の Blazor と SignalR のチュートリアルで使用されている URL です。 URI は、文字列 (https://signalr.example.com など) または構成を使用して設定することもできます。

詳しくは、「ASP.NET Core SignalR の構成」をご覧ください。

レンダリング モード (Blazor WebAssembly)

プリレンダリングするために SignalR を使用する Blazor WebAssembly アプリがサーバーに構成されている場合、サーバーへのクライアント接続が確立される前に、プリレンダリングが行われます。 詳細については、次の記事を参照してください。

Blazor WebAssembly アプリに関するその他のリソース

webfarm ホスティングにスティッキー セッションを使う (Blazor Server)

最初のクライアント要求への応答として、Blazor Server アプリによってプリレンダリングされます。これにより、サーバー上で UI の状態が作成されます。 クライアントで SignalR 接続の作成が再試行される際は、クライアントを同じサーバーに再接続する必要があります。 複数のバックエンド サーバーを使用する Blazor Server アプリでは、SignalR 接続に "スティッキー セッション" を実装する必要があります。

Note

Webfarm でスティッキー セッションを有効にしていないアプリからは次のエラーがスローされます。

blazor.server.js:1 Uncaught (in promise) Error: Invocation canceled due to the underlying connection being closed. (blazor.server.js:1 捕捉されない (promise 内の) エラー: 基となる接続が閉じられたため、呼び出しが取り消されました。)

Azure SignalR Service (Blazor Server)

Microsoft Azure でホストされている Blazor Server アプリには、Azure SignalR Service を使用することをお勧めします。 このサービスはアプリの Blazor Hub と連携して、Blazor Server アプリを多数の SignalR 同時接続にスケールアップします。 さらに、SignalR Service のグローバル リーチとハイパフォーマンスのデータ センターは、地理的条件による待機時間の短縮に役立ちます。

Azure SignalR Service でのプリレンダリング サポートについては、"スティッキー セッション" を使用するようにアプリを構成します。 詳細については、「ASP.NET Core Blazor Server のホストと展開」を参照してください。

Blazor Server アプリの回線ハンドラーのオプション

次の表に示す CircuitOptions を使用して Blazor Server の回線を構成してください。

オプション Default 説明
DetailedErrors false 回線でハンドルされない例外が発生した場合、または JS 相互運用機能を介した .NET メソッドの呼び出しの結果として例外が発生した場合に、詳細な例外メッセージを JavaScript に送信します。
DisconnectedCircuitMaxRetained 100 サーバーが一度にメモリに保持する切断された回線の最大数。
DisconnectedCircuitRetentionPeriod 3 分 切断された回線が破棄されるまでにメモリに保持される最大時間。
JSInteropDefaultCallTimeout 1 分 非同期の JavaScript 関数呼び出しがタイムアウトするまでにサーバーが待機する最大時間。
MaxBufferedUnacknowledgedRenderBatches 10 堅牢な再接続をサポートするために、サーバーが一定期間、メモリに保持する回線あたりの未確認のレンダリング バッチの最大数。 制限に達すると、クライアントによって 1 つ以上のバッチが確認されるまで、サーバーにより新しいレンダリング バッチの生成が停止されます。

オプションの AddServerSideBlazor へのデリゲートを使用して Startup.ConfigureServices のオプションを構成します。 次の例では、前の表に示した既定のオプション値を割り当てます。 Startup.csSystem 名前空間が使用されていることを確認します (using System;)。

Startup.ConfigureServices:

services.AddServerSideBlazor(options =>
{
    options.DetailedErrors = false;
    options.DisconnectedCircuitMaxRetained = 100;
    options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3);
    options.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(1);
    options.MaxBufferedUnacknowledgedRenderBatches = 10;
});

HubConnectionContext を構成するには、HubConnectionContextOptions と共に AddHubOptions を使用します。 オプションの説明については、「ASP.NET Core SignalR の構成」をご覧ください。 次の例では、既定のオプション値を割り当てます。 Startup.csSystem 名前空間が使用されていることを確認します (using System;)。

Startup.ConfigureServices:

services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
        options.EnableDetailedErrors = false;
        options.HandshakeTimeout = TimeSpan.FromSeconds(15);
        options.KeepAliveInterval = TimeSpan.FromSeconds(15);
        options.MaximumParallelInvocationsPerClient = 1;
        options.MaximumReceiveMessageSize = 32 * 1024;
        options.StreamBufferCapacity = 10;
    });

Blazor Hub のエンドポイント ルートの構成 (Blazor Server)

Startup.Configure で、Blazor Server アプリによって UseEndpointsIEndpointRouteBuilderMapBlazorHub が呼び出されて、BlazorHub がアプリの既定のパスにマップされます。 Blazor Server スクリプト (blazor.server.js) は、MapBlazorHub によって作成されたエンドポイントを自動的に指します。

UI に接続状態を反映する (Blazor Server)

接続が失われたことがクライアントで検出されると、クライアントによって再接続が試行される間、ユーザーに対して既定の UI が表示されます。 再接続に失敗した場合、ユーザーには再試行のオプションが表示されます。

UI をカスタマイズするには、_Host.cshtmlRazor ページの <body> に、components-reconnect-modalid を持つ要素を定義します。

Pages/_Host.cshtml:

<div id="components-reconnect-modal">
    ...
</div>

次の CSS スタイルをサイトのスタイルシートに追加します。

wwwroot/css/site.css:

#components-reconnect-modal {
    display: none;
}

#components-reconnect-modal.components-reconnect-show {
    display: block;
}

次の表で、Blazor フレームワークによってcomponents-reconnect-modal 要素に適用される CSS クラスについて説明します。

CSS クラス 示す内容...
components-reconnect-show 接続が失われました。 クライアントによって再接続が試行されています。 モーダルを表示します。
components-reconnect-hide サーバーへのアクティブな接続が再確立されます。 モーダルを非表示にします。
components-reconnect-failed 再接続に失敗しました。ネットワーク障害が原因である可能性があります。 再接続を試みるには、JavaScript で window.Blazor.reconnect() を呼び出します。
components-reconnect-rejected 再接続が拒否されました。 サーバーに到達したが接続が拒否されたため、サーバー上のユーザーの状態が失われました。 アプリを再度読み込むには、JavaScript で location.reload() を呼び出します。 この接続状態は、次の場合に発生する可能性があります。
  • サーバー側回線でクラッシュが発生した場合。
  • クライアントが長時間切断されているため、サーバーでユーザーの状態が削除された場合。 ユーザーのコンポーネントのインスタンスは破棄されます。
  • サーバーが再起動されたか、アプリのワーカー プロセスがリサイクルされた場合。

モーダル要素に対して、サイトの CSS で transition-delay プロパティを設定して、再接続表示が表示されるまでの遅延時間をカスタマイズします。 次の例では、移行遅延時間を 500 ms (既定値) から 1,000 ms (1 秒) に設定しています。

wwwroot/css/site.css:

#components-reconnect-modal {
    transition: visibility 0s linear 1000ms;
}

レンダリング モード (Blazor Server)

既定では、サーバーへのクライアント接続が確立される前に、Blazor Server アプリによってサーバー上の UI がプリレンダリングされます。 詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。

Blazor の起動 (Blazor Server)

Pages/_Host.cshtml ファイル内にある Blazor Server アプリの SignalR 回線の手動での起動を構成します。

  • blazor.server.js スクリプトの <script> タグに autostart="false" 属性を追加します。
  • Blazor.start を呼び出すスクリプトを、blazor.server.js スクリプトの <script> タグの後の終了 </body> タグ内に配置します。

autostart が無効になっている場合、回線に依存しないアプリのすべての側面が正常に動作します。 たとえば、クライアント側のルーティングは動作します。 ただし、回線に依存する側面はすべて、Blazor.start が呼び出されるまで動作しません。 回線が確立されていなければ、アプリの動作は予測不可能です。 たとえば、回線が切断されている間、コンポーネント メソッドは実行できません。

ドキュメントの準備ができたときに Blazor を初期化する方法や、JS Promise に連結する方法などについて詳しくは、「ASP.NET Core Blazor の起動」をご覧ください。

SignalR クライアント ログを構成する (Blazor Server)

クライアント ビルダーで、ログ レベルを指定して configureLogging を呼び出す configureSignalR 構成オブジェクトを渡します。

Pages/_Host.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        configureSignalR: function (builder) {
          builder.configureLogging("information");
        }
      });
    </script>
</body>

前の例で、information はログ レベル LogLevel.Information と同じです。

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

再接続ハンドラーを変更する (Blazor Server)

再接続ハンドラーの回線接続イベントは、次のようなカスタム動作を行うように変更できます。

  • 接続が切断された場合にユーザーに通知する。
  • 回線が接続されているときに (クライアントから) ログ記録を実行する。

接続イベントを変更するには、次の接続の変更に対してコールバックを登録します。

  • 切断された接続では、onConnectionDown が使用されます。
  • 確立または再確立された接続では、onConnectionUp が使用されます。

onConnectionDownonConnectionUp の両方を指定する必要があります。

Pages/_Host.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        reconnectionHandler: {
          onConnectionDown: (options, error) => console.error(error),
          onConnectionUp: () => console.log("Up, up, and away!")
        }
      });
    </script>
</body>

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

再接続の再試行回数と間隔を調整する (Blazor Server)

再接続の再試行の回数と間隔を調整するには、再試行の回数 (maxRetries) と、各再試行で許可されるミリ秒単位の期間 (retryIntervalMilliseconds) を設定します。

Pages/_Host.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        reconnectionOptions: {
          maxRetries: 3,
          retryIntervalMilliseconds: 2000
        }
      });
    </script>
</body>

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

クライアントから Blazor 回線を切断する (Blazor Server)

既定では、unload ページ イベントがトリガーされると、Blazor 回線が切断されます。 クライアント上の他のシナリオで回線を切断するには、適切なイベント ハンドラーで Blazor.disconnect を呼び出します。 次の例では、ページが非表示になると、回線が切断されます (pagehide イベント)。

window.addEventListener('pagehide', () => {
  Blazor.disconnect();
});

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

Blazor Server 回線ハンドラー

Blazor Server を使用すると、コードで "回線ハンドラー" を定義できます。これにより、ユーザーの回線の状態の変更時にコードを実行できます。 回線ハンドラーは、CircuitHandler から派生させ、そのクラスをアプリのサービス コンテナーに登録することで実装します。 次の回線ハンドラーの例では、開いている SignalR 接続を追跡します。

TrackingCircuitHandler.cs:

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Server.Circuits;

public class TrackingCircuitHandler : CircuitHandler
{
    private HashSet<Circuit> circuits = new();

    public override Task OnConnectionUpAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Add(circuit);

        return Task.CompletedTask;
    }

    public override Task OnConnectionDownAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Remove(circuit);

        return Task.CompletedTask;
    }

    public int ConnectedCircuits => circuits.Count;
}

回線ハンドラーは DI を使用して登録されます。 スコープを持つインスタンスは、回線のインスタンスごとに作成されます。 前の例の TrackingCircuitHandler を使用すると、すべての回線の状態を追跡する必要があるため、シングルトン サービスが作成されます。

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();
}

カスタム回線ハンドラーのメソッドでハンドルされない例外がスローされる場合は、その例外は Blazor Server 回線にとって致命的です。 ハンドラーのコードまたはメソッドで例外が許容されるようにするには、エラー処理とログを含む 1 つ以上の try-catch ステートメントでコードをラップします。

ユーザーが切断し、フレームワークで回線の状態がクリーンアップされていることが原因で回線が終了すると、フレームワークによって回線の DI スコープが破棄されます。 スコープが破棄されると、System.IDisposable を実装するサーキットスコープの DI サービスはすべて破棄されます。 破棄中にいずれかの DI サービスでハンドルされない例外がスローされると、フレームワークによって例外がログに記録されます。 詳細については、「ASP.NET Core Blazor の依存関係の挿入」を参照してください。

Blazor Server アプリに関するその他のリソース

ASP.NET Core SignalR の構成の一般的なガイダンスについては、ドキュメントの ASP.NET Core SignalR の概要に関するトピックをご覧ください。 ホステッド Blazor WebAssembly ソリューションに追加されたSignalR を構成する方法については、「ASP.NET Core SignalR の構成」をご覧ください。

認証のための SignalR のクロスオリジン ネゴシエーション (Blazor WebAssembly)

cookie や HTTP 認証ヘッダーなどの資格情報を送信するように SignalR の基となるクライアントを構成するには:

  • SetBrowserRequestCredentials を使用して、クロスオリジン fetch 要求に Include を設定します。

    IncludeRequestCredentialsMessageHandler.cs:

    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Components.WebAssembly.Http;
    
    public class IncludeRequestCredentialsMessageHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
        {
            request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
            return base.SendAsync(request, cancellationToken);
        }
    }
    
  • ハブ接続が構築されている場合は、HttpMessageHandlerHttpMessageHandlerFactory オプションに割り当てます。

    HubConnectionBuilder hubConnection;
    
    ...
    
    hubConnection = new HubConnectionBuilder()
        .WithUrl(new Uri(NavigationManager.ToAbsoluteUri("/chathub")), options =>
        {
            options.HttpMessageHandlerFactory = innerHandler => 
                new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler };
        }).Build();
    

    前の例では、ハブ接続 URL を /chathub の絶対 URI アドレスに構成しています。これは、Index コンポーネント (Pages/Index.razor) の Blazor と SignalR のチュートリアルで使用されている URL です。 URI は、文字列 (https://signalr.example.com など) または構成を使用して設定することもできます。

詳しくは、「ASP.NET Core SignalR の構成」をご覧ください。

Blazor WebAssembly アプリに関するその他のリソース

webfarm ホスティングにスティッキー セッションを使う (Blazor Server)

最初のクライアント要求への応答として、Blazor Server アプリによってプリレンダリングされます。これにより、サーバー上で UI の状態が作成されます。 クライアントで SignalR 接続の作成が再試行される際は、クライアントを同じサーバーに再接続する必要があります。 複数のバックエンド サーバーを使用する Blazor Server アプリでは、SignalR 接続に "スティッキー セッション" を実装する必要があります。 詳細については、「ASP.NET Core Blazor Server のホストと展開」を参照してください。

Note

Webfarm でスティッキー セッションを有効にしていないアプリからは次のエラーがスローされます。

blazor.server.js:1 Uncaught (in promise) Error: Invocation canceled due to the underlying connection being closed. (blazor.server.js:1 捕捉されない (promise 内の) エラー: 基となる接続が閉じられたため、呼び出しが取り消されました。)

Azure SignalR Service (Blazor Server)

Microsoft Azure でホストされている Blazor Server アプリには、Azure SignalR Service を使用することをお勧めします。 このサービスはアプリの Blazor Hub と連携して、Blazor Server アプリを多数の SignalR 同時接続にスケールアップします。 さらに、SignalR Service のグローバル リーチとハイパフォーマンスのデータ センターは、地理的条件による待機時間の短縮に役立ちます。

Azure SignalR Service でのプリレンダリング サポートについては、"スティッキー セッション" を使用するようにアプリを構成します。 詳細については、「ASP.NET Core Blazor Server のホストと展開」を参照してください。

Blazor Server アプリの回線ハンドラーのオプション

次の表に示す CircuitOptions を使用して Blazor Server の回線を構成してください。

オプション Default 説明
DetailedErrors false 回線でハンドルされない例外が発生した場合、または JS 相互運用機能を介した .NET メソッドの呼び出しの結果として例外が発生した場合に、詳細な例外メッセージを JavaScript に送信します。
DisconnectedCircuitMaxRetained 100 サーバーが一度にメモリに保持する切断された回線の最大数。
DisconnectedCircuitRetentionPeriod 3 分 切断された回線が破棄されるまでにメモリに保持される最大時間。
JSInteropDefaultCallTimeout 1 分 非同期の JavaScript 関数呼び出しがタイムアウトするまでにサーバーが待機する最大時間。
MaxBufferedUnacknowledgedRenderBatches 10 堅牢な再接続をサポートするために、サーバーが一定期間、メモリに保持する回線あたりの未確認のレンダリング バッチの最大数。 制限に達すると、クライアントによって 1 つ以上のバッチが確認されるまで、サーバーにより新しいレンダリング バッチの生成が停止されます。

オプションの AddServerSideBlazor へのデリゲートを使用して Startup.ConfigureServices のオプションを構成します。 次の例では、前の表に示した既定のオプション値を割り当てます。 Startup.csSystem 名前空間が使用されていることを確認します (using System;)。

Startup.ConfigureServices:

services.AddServerSideBlazor(options =>
{
    options.DetailedErrors = false;
    options.DisconnectedCircuitMaxRetained = 100;
    options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3);
    options.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(1);
    options.MaxBufferedUnacknowledgedRenderBatches = 10;
});

HubConnectionContext を構成するには、HubConnectionContextOptions と共に AddHubOptions を使用します。 オプションの説明については、「ASP.NET Core SignalR の構成」をご覧ください。 次の例では、既定のオプション値を割り当てます。 Startup.csSystem 名前空間が使用されていることを確認します (using System;)。

Startup.ConfigureServices:

services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
        options.EnableDetailedErrors = false;
        options.HandshakeTimeout = TimeSpan.FromSeconds(15);
        options.KeepAliveInterval = TimeSpan.FromSeconds(15);
        options.MaximumParallelInvocationsPerClient = 1;
        options.MaximumReceiveMessageSize = 32 * 1024;
        options.StreamBufferCapacity = 10;
    });

Blazor Hub のエンドポイント ルートの構成 (Blazor Server)

Startup.Configure で、Blazor Server アプリによって UseEndpointsIEndpointRouteBuilderMapBlazorHub が呼び出されて、BlazorHub がアプリの既定のパスにマップされます。 Blazor Server スクリプト (blazor.server.js) は、MapBlazorHub によって作成されたエンドポイントを自動的に指します。

UI に接続状態を反映する (Blazor Server)

接続が失われたことがクライアントで検出されると、クライアントによって再接続が試行される間、ユーザーに対して既定の UI が表示されます。 再接続に失敗した場合、ユーザーには再試行のオプションが表示されます。

UI をカスタマイズするには、_Host.cshtmlRazor ページの <body> に、components-reconnect-modalid を持つ要素を定義します。

Pages/_Host.cshtml:

<div id="components-reconnect-modal">
    ...
</div>

次の CSS スタイルをサイトのスタイルシートに追加します。

wwwroot/css/site.css:

#components-reconnect-modal {
    display: none;
}

#components-reconnect-modal.components-reconnect-show {
    display: block;
}

次の表で、Blazor フレームワークによってcomponents-reconnect-modal 要素に適用される CSS クラスについて説明します。

CSS クラス 示す内容...
components-reconnect-show 接続が失われました。 クライアントによって再接続が試行されています。 モーダルを表示します。
components-reconnect-hide サーバーへのアクティブな接続が再確立されます。 モーダルを非表示にします。
components-reconnect-failed 再接続に失敗しました。ネットワーク障害が原因である可能性があります。 再接続を試みるには、JavaScript で window.Blazor.reconnect() を呼び出します。
components-reconnect-rejected 再接続が拒否されました。 サーバーに到達したが接続が拒否されたため、サーバー上のユーザーの状態が失われました。 アプリを再度読み込むには、JavaScript で location.reload() を呼び出します。 この接続状態は、次の場合に発生する可能性があります。
  • サーバー側回線でクラッシュが発生した場合。
  • クライアントが長時間切断されているため、サーバーでユーザーの状態が削除された場合。 ユーザーのコンポーネントのインスタンスは破棄されます。
  • サーバーが再起動されたか、アプリのワーカー プロセスがリサイクルされた場合。

レンダリング モード (Blazor Server)

既定では、サーバーへのクライアント接続が確立される前に、Blazor Server アプリによってサーバー上の UI がプリレンダリングされます。 詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。

Blazor の起動 (Blazor Server)

Pages/_Host.cshtml ファイル内にある Blazor Server アプリの SignalR 回線の手動での起動を構成します。

  • blazor.server.js スクリプトの <script> タグに autostart="false" 属性を追加します。
  • Blazor.start を呼び出すスクリプトを、blazor.server.js スクリプトの <script> タグの後の終了 </body> タグ内に配置します。

autostart が無効になっている場合、回線に依存しないアプリのすべての側面が正常に動作します。 たとえば、クライアント側のルーティングは動作します。 ただし、回線に依存する側面はすべて、Blazor.start が呼び出されるまで動作しません。 回線が確立されていなければ、アプリの動作は予測不可能です。 たとえば、回線が切断されている間、コンポーネント メソッドは実行できません。

ドキュメントの準備ができたときに Blazor を初期化する方法や、JS Promise に連結する方法などについて詳しくは、「ASP.NET Core Blazor の起動」をご覧ください。

SignalR クライアント ログを構成する (Blazor Server)

クライアント ビルダーで、ログ レベルを指定して configureLogging を呼び出す configureSignalR 構成オブジェクトを渡します。

Pages/_Host.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        configureSignalR: function (builder) {
          builder.configureLogging("information");
        }
      });
    </script>
</body>

前の例で、information はログ レベル LogLevel.Information と同じです。

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

再接続ハンドラーを変更する (Blazor Server)

再接続ハンドラーの回線接続イベントは、次のようなカスタム動作を行うように変更できます。

  • 接続が切断された場合にユーザーに通知する。
  • 回線が接続されているときに (クライアントから) ログ記録を実行する。

接続イベントを変更するには、次の接続の変更に対してコールバックを登録します。

  • 切断された接続では、onConnectionDown が使用されます。
  • 確立または再確立された接続では、onConnectionUp が使用されます。

onConnectionDownonConnectionUp の両方を指定する必要があります。

Pages/_Host.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        reconnectionHandler: {
          onConnectionDown: (options, error) => console.error(error),
          onConnectionUp: () => console.log("Up, up, and away!")
        }
      });
    </script>
</body>

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

再接続の再試行回数と間隔を調整する (Blazor Server)

再接続の再試行の回数と間隔を調整するには、再試行の回数 (maxRetries) と、各再試行で許可されるミリ秒単位の期間 (retryIntervalMilliseconds) を設定します。

Pages/_Host.cshtml:

<body>
    ...

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      Blazor.start({
        reconnectionOptions: {
          maxRetries: 3,
          retryIntervalMilliseconds: 2000
        }
      });
    </script>
</body>

Blazor の起動の詳細については、「ASP.NET Core Blazor の起動」をご覧ください。

Blazor Server 回線ハンドラー

Blazor Server を使用すると、コードで "回線ハンドラー" を定義できます。これにより、ユーザーの回線の状態の変更時にコードを実行できます。 回線ハンドラーは、CircuitHandler から派生させ、そのクラスをアプリのサービス コンテナーに登録することで実装します。 次の回線ハンドラーの例では、開いている SignalR 接続を追跡します。

TrackingCircuitHandler.cs:

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Server.Circuits;

public class TrackingCircuitHandler : CircuitHandler
{
    private HashSet<Circuit> circuits = new HashSet<Circuit>();

    public override Task OnConnectionUpAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Add(circuit);

        return Task.CompletedTask;
    }

    public override Task OnConnectionDownAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        circuits.Remove(circuit);

        return Task.CompletedTask;
    }

    public int ConnectedCircuits => circuits.Count;
}

回線ハンドラーは DI を使用して登録されます。 スコープを持つインスタンスは、回線のインスタンスごとに作成されます。 前の例の TrackingCircuitHandler を使用すると、すべての回線の状態を追跡する必要があるため、シングルトン サービスが作成されます。

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();
}

カスタム回線ハンドラーのメソッドでハンドルされない例外がスローされる場合は、その例外は Blazor Server 回線にとって致命的です。 ハンドラーのコードまたはメソッドで例外が許容されるようにするには、エラー処理とログを含む 1 つ以上の try-catch ステートメントでコードをラップします。

ユーザーが切断し、フレームワークで回線の状態がクリーンアップされていることが原因で回線が終了すると、フレームワークによって回線の DI スコープが破棄されます。 スコープが破棄されると、System.IDisposable を実装するサーキットスコープの DI サービスはすべて破棄されます。 破棄中にいずれかの DI サービスでハンドルされない例外がスローされると、フレームワークによって例外がログに記録されます。 詳細については、「ASP.NET Core Blazor の依存関係の挿入」を参照してください。

Blazor Server アプリに関するその他のリソース