はじめに
今回は前回に引き続き、Azure Tableを使ったWebアプリケーションの実装方法について説明します。前回登録処理を実装したWebアプリケーションに更新処理と削除処理を加えていきます。
更新処理の追加実装
まずは更新処理を追加していきます。一覧画面に表示されているアドレス情報を選択するとそのデータの内容を編集するための更新画面に遷移するように実装します。
Azure Table操作用サービスクラスの修正
Azure Table操作用のサービスクラスに、1件のデータを取得するためのメソッドとデータ更新用のメソッドを追加します。
データ更新のためのメソッド追加(Services/AddressService.cs)
public interface IAddressService
{
Task AddAsync(Address address);
Task<IList<Address>> GetAllAsync();
// 1件のデータを取得するメソッド・・・①-1
Task<Address> GetAsync(string partitionKey, string rowKey);
// データを更新するメソッド・・・②-1
Task UpdateAsync(Address address);
}
public class AddressService : IAddressService
{
// テーブルクライアント
private readonly TableClient tableClient;
・・・中略
// 1件のデータを取得するメソッド・・・①-2
public async Task<Address> GetAsync(string partitionKey, string rowKey)
{
var address = await this.tableClient.GetEntityAsync<Address>(partitionKey, rowKey);
return address.Value;
}
// データを更新するメソッド・・・②-2
public async Task UpdateAsync(Address address)
{
await this.tableClient.UpdateEntityAsync(address, ETag.All);
}
}
「AddressService.cs」内のインタフェースとクラスそれぞれにメソッドを追加していきます。まずは一覧画面で更新対象のデータを選択した際に、選択したデータの情報を取得するメソッドを追加します(①-1、①-2)。ここで取得した情報により、更新画面に更新前情報を表示することができるようになります。テーブルクライアントの「GetEntityAsync」メソッドを使用することで、Azure Tableから1件のデータを取得することができます。データを一意に特定するための情報として、パーティションキーとRowKeyをメソッドの引数に渡します。
次に編集した情報を更新するメソッドを追加します(②-1、②ー2)。テーブルクライアントの「UpdateEntityAsync」メソッドに編集したアドレス情報を渡すことでAzure Table内のデータを更新することができるようになります。また第二引数に設定している「ETag.All」ですが、これはETagと呼ばれるエンティティのバージョン管理用のタグを用いてデータ更新の挙動を指定するものです。「ETag.All」の場合、エンティティがテーブルに存在すれば更新処理を実行し、存在しない場合はエラーを返すという挙動になります。
編集画面の実装
次に編集画面を新たに実装していきます。Pagesフォルダに新たに「Edit.cshtml」と「Edit.cshtml.cs」というファイルを作成します。
編集画面の実装(Pages/Edit.cshtml)
@* パスにパーティションキーとRowKeyを追加する・・・① *@
@page "{partitionKey}/{rowKey}"
@model EditModel
@{
ViewData["Title"] = "Edit Address";
}
<h1>Edit Address</h1>
<form method="post">
<div class="form-group">
@* RowKeyが変更するのを防ぐためにhiddenでフォームに含める・・・② *@
<input asp-for="Address.RowKey" type="hidden" />
</div>
<div class="form-group">
<label asp-for="Address.Email">メールアドレス</label>
<input asp-for="Address.Email" class="form-control" readonly/>
</div>
<div class="form-group">
<label asp-for="Address.LastName">姓</label>
<input asp-for="Address.LastName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Address.FirstName">名</label>
<input asp-for="Address.FirstName" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">更新</button>
</form>
更新処理ではパーティションキーとRowKeyの指定が必要となるため、編集画面にこれらの値を引き継ぐ必要があります。ファイル冒頭の「@page」ディレクティブに続けて「"{partitionKey}/{rowKey}"」という文字列を追加することでそれがURLパスとなり、またモデルクラスでもこれらの値を利用することができます(①)。編集画面はフォームで実装します。メールアドレスと姓名を表示し、そのうち姓名のみ編集可能としています。メールアドレスのドメイン部分はパーティションキーとして使用しており、変更されてしまうとAzure Table内で別データ扱いとなってしまうため、readonly属性を付与して編集不可としています。また、フォームにはRowKeyの内容を非表示(hidden)で含めています(②)。これはAddressクラスのRowKeyの値が自動生成される実装のため、フォームを送信した際にRowKeyの値が意図しない値に置き換わってしまうことを防ぐために設けています。
次にこの画面に対応するモデルクラスを実装します。
編集画面モデルの実装(Pages/Edit.cshtml.cs)
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using AzureTableSample.Models;
using AzureTableSample.Services;
namespace AzureTableSample.Pages;
public class EditModel : PageModel
{
// 更新対象のデータを保持するプロパティ
[BindProperty]
public Address Address { get; set; }
// データアクセス用のサービス
private readonly IAddressService _addressService;
public EditModel(IAddressService addressService)
{
_addressService = addressService;
}
// 編集画面遷移時の挙動の実装・・・①
public async Task<IActionResult> OnGetAsync(string partitionKey, string rowKey)
{
Address = await _addressService.GetAsync(partitionKey, rowKey);
if (Address == null)
{
return NotFound();
}
return Page();
}
// 更新ボタン押下時の挙動の実装・・・②
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
// 更新対象データの存在チェック・・・③
var existingAddress = await _addressService.GetAsync(Address.PartitionKey, Address.RowKey);
if (existingAddress == null)
{
return NotFound();
}
existingAddress.LastName = Address.LastName;
existingAddress.FirstName = Address.FirstName;
await _addressService.UpdateAsync(existingAddress);
// 更新に成功したら一覧画面に遷移する
return RedirectToPage("/Index");
}
}
更新画面のモデルクラスでは、2つのメソッドを実装します。1つ目は編集画面に遷移したタイミングで呼び出される「OnGetAsync」メソッドです(①)。このメソッドは引数でパーティションキーとRowKeyを受取り、該当するアドレス情報をサービス経由で取得して画面に返します。2つ目は編集画面にある更新ボタンを押下した際に呼び出される「OnPostAsync」メソッドです(②)。編集画面で更新した内容は、このメソッド経由でAzure Tableに反映されます。今回は更新処理の実行前に、更新対象のデータがAzure Tableから削除されてしまっていないかを確認する存在チェックの処理を加えています(③)。
一覧画面の修正
更新処理実装の最後に一覧画面を編集します。一覧画面に表示されるアドレス情報リストの各行に編集ボタンを追加して編集画面へ遷移できるようにします。
一覧画面に編集ボタンを追加する(Index.cshtml)
・・・中略
<tbody>
@foreach (var address in Model.Addresses)
{
<tr>
<td>@address.Email</td>
<td>@address.LastName</td>
<td>@address.FirstName</td>
<td>@address.Timestamp</td>
@* 編集ボタンの追加・・・① *@
<td>
<form method="get" asp-page="/Edit" asp-route-partitionKey="@address.PartitionKey" asp-route-rowKey="@address.RowKey" style="display:inline;">
<button type="submit" class="btn btn-primary">編集</button>
</form>
</td>
</tr>
}
</tbody>
</table>
表の最終列に編集ボタンを追加します(①)。form要素の「asp-page」属性で遷移先の画面を指定し、「asp-route-partitionKey」と「asp-route-rowKe」属性で遷移先画面に渡す情報としてパーティションキーとRowKeyを指定しています。これにより「Edit.cshtml」でこれらの値を使用することができるようになります。
ここまで実装ができたら、アプリケーションを実行してみましょう。Visual Studio上部にある実行ボタンを選択しアプリケーションを起動します。
ビルドに成功するとWebブラウザが表示され、一覧画面が表示されます。その行の右端に追加されている「編集」ボタンから編集画面に遷移します。
編集画面で姓名を変更し、「更新」ボタンを選択します。
ボタン押下後に一覧画面に遷移し、編集した内容が画面に反映されていれば成功です。
Azure Tableのデータも確認します。Azureポータルにログインし、利用中のストレージアカウントの画面から「ストレージブラウザー」→「テーブル」→「address」の順に選択していきます。テーブル内のデータが更新した内容に反映されていれることが確認できます。
これで更新処理の動作確認ができたので、続いて削除処理を実装していきます。