ASP.NET Core Blazor WebAssembly の必要最低限のハロー ワールド (イベント対応)

2 min読了の目安(約2400字TECH技術記事

先日、以下のような記事を書いて最低限の ASP.NET Core Blazor WebAssembly でハローワールドを書きました。

https://zenn.dev/okazuki/articles/blazor-wasm-helloworld-step-by-steps

今日は、これにもう少しだけ処理を追加してみたいと思います。

まず App.razor を少し書き換えて App コンポーネントにプロパティを定義します。そのプロパティに Hello world を設定して h3 タグで表示します。

App.razor
<h3>@Message</h3>

@code {
    private string Message { get; set; } = "Hello world";
}

この時点では単純に Hello world のメッセージをプロパティに変えただけです。そして、ボタンを押したら Hello world が「こんにちは世界」に変わるようにしたいと思います。ということで素直にイベントハンドラを作って @onclickMessage プロパティの値を置き換えます。(.editorconfig あたりで UTF-8-BOM で保存するようにておかないと後で文字化けするので注意。)

App.razor
<h3>@Message</h3>

<button @onclick="ToJapanese">To Japanese</button>

@code {
    private string Message { get; set; } = "Hello world";
    private void ToJapanese() => Message = "こんにちは世界";
}

これを、実行すると無事動きません (!?!?)

イベントを動かすために必要なもの

App.razorMicrosoft.AspNetCore.Components.Webusing を追加するとイベントが使えるようになります。

App.razor
@using Microsoft.AspNetCore.Components.Web @* これが必要! *@
<h3>@Message</h3>

<button @onclick="ToJapanese">To Japanese</button>

@code {
    private string Message { get; set; } = "Hello world";
    private void ToJapanese() => Message = "こんにちは世界";
}

実行すると、今度はちゃんと動きました。

ちょっと見てみる

ということで、問題の Microsoft.AspNetCore.Components.Web 名前空間のソースコードを見てみようと思います。

https://github.com/dotnet/aspnetcore/tree/main/src/Components/Web/src/Web

このフォルダーを見てみると、なんとなくイベント関連のクラスが定義されていますが、多分ここにある EventHandlers クラスにイベント名とイベント引数の型のマッピングが定義されているので、このクラスがいないと onclick などの基本的なイベントが動かなさそうです。

https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web/src/Web/EventHandlers.cs

EventHandlers という名前のクラスがあると Razor の EventHandlerTagHelperDescriptorProvider クラスが拾ってくれるところくらいまではわかったのですが、同じコードが Blazor でも動いているかの裏もとってないし、そこからどうなるのか追いかけるのもメンドクサイので諦めました。とりあえず Microsoft.AspNetCore.Components.Webusing していないと基本的なタグに対するイベントが動かないということは頭の片隅に入れておきましょう。

プロジェクトテンプレートではどうなってるの…?

_Imports.razor という特殊な名前のファイルを用意しておくと自動的に、そのファイルがあるのと同じフォルダーとサブフォルダーの .razor ファイルに含まれます。プロジェクトテンプレートからプロジェクトを作ると、プロジェクトのルートフォルダーに _Imports.razor というファイルが作られていて、その中に @using Microsoft.AspNetCore.Components.Web という定義が含まれています。

そのため、プロジェクトテンプレートから作ったら何も考えずに @onclick などが動くっぽいです。

まとめ

Hello world をベースにプロジェクトいじって遊ぼうと思ったらイベントが動かなかったのでびっくりしました。
でも最終的には動いたのでめでたしめでたし。