Blazor01

BlazorでのWebアプリケーション開発手法1【C#】B23_値の受け渡しとしてのProtectedSessionStorage

今回は、値の受け渡しの手段としてProtectedSessionStorageを使う方法について解説します。

Counter.razorには、すでに前回までの内容でProtectedSessionStorageがinjectされており、IncrementCountメソッドの中でSetAsyncを使ってcurrentCountの値を保存する処理が組み込まれています。

図1 Counter.razorの冒頭。ProtectedSessionStorageをstorageという名前でinjectしている

OnInitializedAsyncメソッドの中では、GetAsyncでキー“currentCount”を指定して値を取得し、取得に成功していればcurrentCountフィールドにその値を代入しています。

図2 OnInitializedAsync内の処理。GetAsyncでキー“currentCount”の値を読み込み、成功していればcurrentCountに反映する

IncrementCountメソッドの側では、ボタンが押されるたびにcurrentCount++のあとでSetAsyncを呼び出し、同じキー“currentCount”で現在の値を保存し直しています。

図3 IncrementCountメソッド。ボタンクリックのたびにキー“currentCount”で値を保存し直している

@code {
    private int currentCount = 0;
 
    protected override async Task OnInitializedAsync()
    {
        var storageCurrentCount = await storage.GetAsync<int>("currentCount");
        if (storageCurrentCount.Success)
        {
            currentCount = storageCurrentCount.Value;
        }
    }
 
    private async Task IncrementCount()
    {
        currentCount++;
        await storage.SetAsync("currentCount", currentCount);
    }
}

 

ポイントは、このキー(“currentCount”)さえ分かっていれば、Counter画面以外の画面からでも同じ値を取得できるという点です。以前のレクチャーでは、URLのパラメータとして値を画面間で受け渡す方法を解説しましたが、それとは別に、ProtectedSessionStorageに保存しておいて他の画面から取り出すという値渡しの方法も可能というわけです。

Home画面からCounterの値を取得する

実際に、Home画面から「カウンターの値」というボタンを新しく用意し、Counter画面で保存したcurrentCountの値を取得して表示できるようにしてみます。まず、既存の「ボタンで計測画面を開く」ボタンをコピー&貼り付けし、@onclickの呼び出し先メソッド名をGetCounterValueに、表示テキストを「カウンターの値」に書き換えます。

図4 Home.razorに新しいボタンを追加。@onclickの呼び出し先を“GetCounterValue”に変更している

続けて、その下にpタグで@_counterと記述し、値を表示する場所を用意します。あわせて、@codeブロックにprivate int _counter = 0;というフィールドを追加します。

図5 カウンターの値を表示するpタグと、値を保持するprivate int _counterフィールドを追加

次に、GetCounterValueメソッド本体を実装します。中身は、Counter.razorのOnInitializedAsyncで行っていた「storageから値を取得し、成功していれば変数に代入する」処理とまったく同じです。そこで、OnInitializedAsyncの中身をコピーしてGetCounterValueに貼り付けます。ただし、この処理はawaitを使う非同期処理のため、メソッドの戻り値をasync Taskに変更する必要があります。

図6 GetCounterValueメソッドをasync Taskに変更しているところ

storageはCounter画面側でしかinjectされていないため、Home.razor側でも同様に@injectでProtectedSessionStorageをstorageという名前でinjectしておきます。

図7 Home.razorの冒頭に@injectでProtectedSessionStorageをstorageとして追加

最後に、コピーしてきた処理の中でcurrentCountに代入していた部分を、Home.razor側のフィールドである_counterへの代入に書き換えます。

図8 GetCounterValueの完成形。storageから取得した値を_counterに代入している

@inject Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
    .ProtectedSessionStorage storage
 
@code {
    private int _counter = 0;
 
    private async Task GetCounterValue()
    {
        var storageCurrentCount = await storage.GetAsync<int>("currentCount");
        if (storageCurrentCount.Success)
        {
            _counter = storageCurrentCount.Value;
        }
    }
}

 

これで、Home画面の「カウンターの値」ボタンを押すと、GetCounterValueメソッドが呼ばれ、storageに値があれば_counterに代入され、pタグでデータバインドされている@_counterの表示が更新されるという仕組みになりました。

動作確認

実行して確認してみます。最初、Home画面で「カウンターの値」を押しても、まだ保存された値がないため0のままです。

図9 実行直後のHome画面。「カウンターの値」ボタンの下には初期値の0が表示されている

次に、Counter画面に移動して「Click me」ボタンを何度か押し、Current countを4にします。このタイミングでIncrementCount内のSetAsyncによって、値がキー“currentCount”で保存されます。

図10 Counter画面でCurrent countを4にカウントアップ

この状態でHome画面に戻り、「カウンターの値」を押すと、Counter画面とは別の画面であるにもかかわらず、正しく4という値が表示されます。

図11 Home画面で「カウンターの値」を押すと4が表示される。Counter画面で保存した値がHome画面から取得できている

このように、ProtectedSessionStorageを使えば、画面をまたいで値をやり取りすることができます。URLパラメータでの値渡しと違い、floatやstring、intといった基本型に限らず、クラスのインスタンスなど何でも保存・取得できるという利点があります。たとえば、以前の計測画面で使っていたMeasureResultのようなクラスをまるごと覚えさせておいて、別の画面で取り出すといった使い方も可能です。

ProtectedSessionStorageを使ううえでの注意点

一方で、URLパラメータのように「その瞬間に渡される」仕組みとは違い、ProtectedSessionStorageに保存された値はいつ保存されたものかが分かりにくいという特性があります。そのため、画面遷移の直前に値を保存し、受け取った側は使い終えたら削除する、といった設計を自分で管理する必要があります。

値を削除するには、storageのDeleteAsyncメソッドを使います。試しに、GetCounterValueの末尾にawait storage.DeleteAsync(“currentCount”);という一行を追加し、取得した値を使い終えたタイミングで削除できることを確認します(この行は動作の説明のための一時的な追記で、このあとの動作確認のために元に戻します)。

図12 storage.DeleteAsyncでキーを指定して値を削除できることを確認

await storage.DeleteAsync("currentCount");

 

もうひとつの注意点は、キーの名前が他の画面と重複してしまうと、意図せず値が共有され、書き換わってしまう可能性があるという点です。これを避けるため、キーの名前には画面名などを含めておくとよいでしょう。今回の例で言えば、Counter画面のcurrentCountなので、“counter_currentCount”のように「画面名+アンダーバー+変数名」という命名にしておけば、他の画面のキーと重複する心配がなくなります。

そこで、Counter.razorのGetAsync・SetAsyncで使っているキーを、いずれも“currentCount”から“counter_currentCount”に書き換えます。

図13 Counter.razorのOnInitializedAsync内。GetAsyncのキーを“counter_currentCount”に変更

図14 Counter.razorのIncrementCount内。SetAsyncのキーも同様に“counter_currentCount”に変更

Home.razor側のGetCounterValueで使っているキーも、同じく“counter_currentCount”に合わせて書き換えます。

図15 Home.razorのGetCounterValue内。GetAsyncのキーも“counter_currentCount”に変更

// Counter.razor
var storageCurrentCount = await storage.GetAsync<int>("counter_currentCount");
// ...
await storage.SetAsync("counter_currentCount", currentCount);
 
// Home.razor
var storageCurrentCount = await storage.GetAsync<int>("counter_currentCount");

 

この状態で再度実行すると、Counter画面で5にカウントアップしたあと、Home画面の「カウンターの値」ボタンから正しく5が取得できることが確認できます。キー名を変更しても、Counter.razorとHome.razorの両方で同じキー名にそろえておけば、これまでどおり値の受け渡しができます。

図16 キー名を“counter_currentCount”に変更したあとも、Home画面の「カウンターの値」から正しく5が取得できる

このように、画面名を含めたキー名にしておくことで、他の画面とキーが重複してしまう心配なく、ProtectedSessionStorageを画面間の値渡しに活用できます。値の保存・削除のタイミングと、キー名の重複に注意しながら使ってみてください。

BlazorでのWebアプリケーション開発手法1【C#】

A01_はじめに
A02_バージョンの確認
A03_プロジェクトの作成
A04_アプリの実行
A05_サンプルプログラムの構成
A06_Razorコンポーネント
A07_Razor構文
A08_@pageでURLを指定する
A09_@rendermode
A10_PageTitle
A11_HTMLの見出し
A12_pタグ
A13_単方向データバインド
A14_単方向データバインドの詳細
A15_Bootstrap
A16_ボタンクリックイベント
A17_イベント引数の受け取り方
A18_ここまでのまとめ
B01_新しいWebページを追加する方法
B02_サイドバーから画面を表示する
B03_サイドバーのアイコンを変更する方法
B04_計測値を表示する
B05_変数に置き換える
B06_最新の値でデータを更新する
B07_@usingで通常のC#コードを呼び出す
B08_画面遷移_aタグ
B09_画面遷移_aタグの見た目をボタンにする
B10_画面遷移_NavigationManagerでの遷移
B11_画面間のパラメータの受け渡し方法
B12_EscapeDataStringでエスケープする
B13_複数のパラメータを渡す
B14_任意のパラメータにする
B15_string以外の型をパラメータで使う方法
B16_DateTime型をパラメータで渡す方法
B17_引数2個のURLも型指定に変更する
B18_パラメータ属性をつけるときの注意点
B19_OnParametersSet
B20_OnInitialized
B21_OnInitializedが2回通る問題の対応
B22_ブラウザが開いている間の値を記憶する方法
B23_値の受け渡しとしてのProtectedSessionStorage
B24_非同期を想定したUIの制御
C01_一覧表示
C02_非同期での一覧表示
C03_table-striped
D01_入力エリア
D02_双方向データバインド
D03_入力データをリアルタイムで通知する方法
D04_placeholder
D05_入力エリアの横幅の調整
D06_テキストチェンジイベントを拾う方法
D07_プルダウン
D08_プルダウンのbootstrap
D09_プルダウンの選択している値をデータバインドで操作する
D10_プルダウンにリストの値を表示する
D11_プルダウンに未選択行を入れる
D12_プルダウンの入力を禁止する
D13_プルダウンのチェンジイベントを取得する
D14_チェックボックス
D15_チェックボックスにラベルを付ける
D16_複数のチェックボックスを並べる
D17_ラジオボタン
D18_ラジオボタンのデータバインド
D19_ラジオボタンのチェンジイベント
D20_ラジオボタンにbootstrapを適応する