##はじめに
Blazor
がリリースされてから1年程経ったのでしょうか。
ボチボチとドキュメントとか記事とかが上がってきているみたいなので重い腰をあげてやってみることにしました。
Blazor
やってみたいけどどうすりゃいいんだろ、って人多いと思う(?)のでその手助けとなる記事になればと。
##環境
- VS2019
- .NET Core SDK 3.1
##情報収集
とりあえず色々とよくわかんないのでBlazor Advent Calendar 2019を一通り読んでみました。
分かった事としてはこう。
###Razor記法
MVC時代
にrazor記法
という、HTML
とC#
を悪魔合体させられる記述が可能となった。cshtml
という拡張子。
例えば、こんな感じ。
@for (int i = 0; i < 3; i++) {
<p>for文のループの「@i」回目です。</p>
}
C#
の構文と組み合わせる事で同じような記述を排除できるスグレモノ。
ただ、クライアントの処理は当然、JavaScript
で書く必要があった。まーしょうがないよね。
###Blazor
そんな時に現れたのがBlazor
。
コイツはクライアント処理までC#
で記述することができます。razor
という拡張子。
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
フルC#
により処理が完結させられるのは興奮しました。
###懸念
.razorファイル
にUI
やらロジックやらを書いていけばいいのはわかった。十分に理解できた。ただ気になった事として、.razorファイル
がめちゃめちゃfatになりませんか?ってのが非常に気になりました。
でも大丈夫っぽさそうで、
Blazorでコードビハインドでロジックとビューを分離して記述するに解決策が書いてあり、どうやらちゃんと分けて書くことができるようで安心しました。
今回はPartial Class
でコードを書きます。ViewModel
を使ってもよかったですが、DI
をわざわざ書いてやる必要があったのでパス。
##最終成果物
あとでGIFとソースコードを載せます。
##アプリケーションの作成
さて、これから実際に作っていきます。
###画面遷移図
特に要らないとも思いましたが、やったことないことをちゃんとやっていこうと思ったので簡易的ですが、LucidChartというサイトで作ってみました。
###環境の構築
私の場合は色々と環境が整っていたのでやったのは.NET Core 3.1のSDKをインストール
するぐらい。
Download .NET Core 3.1
Visual Studio
が入ってないとかBlazor
のテンプレートがない場合は以下の記事を参考にするとよいと思います。
C#でSPAを作るBlazorの、開発環境の作り方 - Visual Studio編
###アプリケーションの作成
Blazor をお勧めできる人は誰か?を読んだんですが、サーバーとクライアントのどちらをどういう場合に使い分けるのかがよく分からなかったので取り急ぎはサーバーの方で作成します。
####実行
↓↓↓↓↓↓↓ あなたの記事の内容
とりあえず実行してみて動くっていうのは初学者からすると物凄くハードルが下がるので非常にありがたいです。ということで作りたてほやほやのソリューションをデバッグしてみるとこうなります。
───────
とりあえず実行してみて動くっていうのは初学者からすると物凄く分かりやすいので非常にありがたいです。ということで作りたてほやほやのソリューションをデバッグしてみるとこうなります。
↑↑↑↑↑↑↑ 編集リクエストの内容
色合いがすげーイイ感じです。
では早速、このイイ感じの画面をぶっ壊していきます。
####ログイン画面の生成
ログイン画面を生成していきましょう。
####MainLayout.razorの修正
MainLayout.razor
をBody
だけにします。
左のナビゲーションからページ遷移をさせたくないので。
@inherits LayoutComponentBase
<div class="main">
<div class="content px-4">
@Body
</div>
</div>
####Indexページの修正
インデックスページをログイン画面として使います。
当初は、こういう書き方をしていましたが、
<table style="border:none">
<tr>
<th>
<p>ユーザID</p>
</th>
<td>
<input id="txtUserID" type="text" size="24" @bind="@UserID">
</td>
</tr>
<tr>
<th>
<p>パスワード</p>
</th>
<td>
<input id="txtPassword" type="password" size="24" @bind="@Password">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="ログイン">
<button class="btn btn-primary" @onclick="Login">ログイン</button>
</td>
</tr>
</table>
調べてみるとEditFormタグ
を使えばValidation
をイイ感じにやってくれることが分かったので以下の様に変更しました。
@page "/"
@* 本当はこのusingディレクティブが無くても動いてくれるけど、using追加しろと言われ続けてしまうのでしょうがなく追加 *@
@using LoginTest.Models
<div align="center">
<EditForm Model="@LoginData" OnValidSubmit="@OnValidSubmit" OnInvalidSubmit="@OnInvalidSubmit">
<DataAnnotationsValidator />
@* ValidationSummaryを配置した箇所に全てのValidationメッセージが表示される *@
@*<ValidationSummary />*@
<div class="form-group">
<label>ユーザーID</label>
<InputText id="txtUserID" @bind-Value="LoginData.UserID" />
<ValidationMessage For="@(() => LoginData.UserID)" />
</div>
<div>
<label>パスワード</label>
<InputText id="txtPassword" type="password" @bind-Value="LoginData.Password" />
<ValidationMessage For="@(() => LoginData.Password)" />
</div>
<button type="submit" class="btn btn-primary">ログイン</button>
</EditForm>
</div>
EditForm
については以下の記事を参考にさせていただきました。
Blazorでコードビハインドでロジックとビューを分離して記述するにも書いてありますが、razorファイル
に対応するcsファイル
を作成することでコードビハインドとして扱ってくれます。今回で言うと、Index.razor.csファイル
をPagesフォルダ
直下に作成してみてください。
コードビハインドはこうなります。
using System;
using LoginTest.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
namespace LoginTest.Pages
{
public partial class Index
{
#region プロパティ
/// <summary>
/// Inject属性を指定することで、NavigationManagerのサービスの依存関係を挿入します。
/// </summary>
[Inject]
public NavigationManager Navigation { get; set; }
/// <summary>
/// ログイン情報を保持
/// </summary>
public LoginData LoginData { get; set; }
#endregion
#region コンストラクタ
public Index()
{
//Index.razorから参照するのでインスタンス生成をしておかないとエラーとなる
LoginData = new LoginData();
}
#endregion
#region メソッド
/// <summary>
/// Validate処理成功時に処理
/// </summary>
/// <param name="context"></param>
public void OnValidSubmit(EditContext context)
{
Console.WriteLine($"OnValidSubmit()");
Navigation.NavigateTo("Chat", false);
}
/// <summary>
/// Validate処理失敗時に処理
/// </summary>
/// <param name="context"></param>
public void OnInvalidSubmit(EditContext context)
{
Console.WriteLine($"OnInvalidSubmit()");
}
#endregion
}
}
#####ハマりの共有
少しハマってしまったことが2点あります。
1点目に、Navigation.NavigateToメソッド
で遷移するにあたって、NavigationManager
を、Inject
する必要があります。
遷移先のページを保持している情報を取得しなければいけないということですね。
2点目に、OnSubmitイベント
とOnValidSubmit/OnInvalidSubmitイベント
は併用不可であり同時に定義すると実行時エラーが発生してしまいます。
念の為に書いておくと、
- OnSubmitイベント … Submitボタン押下時に必ず発生する
- OnValidSubmit/OnInvalidSubmitイベント … Submitボタン押下時、Validationが成功すればOnValidSubmit、失敗すればOnInvalidSubmitが発生する
実用的な使い勝手としては断然、OnValidSubmit/OnInvalidSubmitイベント
でしょうね。でも併用できても良いと思うんだけどなー。
####Modelの作成
ここまでくれば大体ログイン画面はできました。
Modelsフォルダ
とその中にLoginData.cs
を作成してください。
LoginData.cs
を以下の様なモデルを作成してやればある程度完成です!
using System.ComponentModel.DataAnnotations;
namespace LoginTest.Models
{
public class LoginData
{
[Required(ErrorMessage = "ユーザIDを入力してください。")]
[StringLength(16, ErrorMessage = "ユーザIDが長すぎます。")]
public string UserID { get; set; }
[Required(ErrorMessage = "パスワードを入力してください。")]
[StringLength(32, ErrorMessage = "パスワードが長すぎます。")]
public string Password { get; set; }
}
}
####動作確認
チャットページに遷移できるように、Pagesフォルダ
以下にChat.razorファイル
を追加することで以下のような動きになります。
最低限。@page "/Chat"
だけ記述されていれば遷移出来るはずです。
テキストボックスへ未入力時にアノテーションが効いててイイ感じです。
ただ今の状態だと、何かしらの値がIDとパスワードに入ってさえいればログインできてしまうのでこの点は後で実装します。
##まとめ
Blazor
だとクライアント処理もC#
で書ける反面、全ての処理をrazorファイル
に記述しないといけないと思っていましたが、ちゃんとそこら辺を考えてあって分離できるのはよい機構だなと思いました。
次の記事では、遷移先のチャットページを作成してみたいと思います。
参考にさせて頂いたページ
- Download .NET Core 3.1
- C#でSPAを作るBlazorの、開発環境の作り方 - Visual Studio編
- Blazor をお勧めできる人は誰か?
- Blazor Advent Calendar 2019
- Blazorでコードビハインドでロジックとビューを分離して記述する
- Blazorアプリケーションでボタンやリンクのクリックの処理で別のページに遷移する
- Blazorにおけるフォームバリデーション手法のまとめ
- BlazorでSPAするぞ!(8) - Validation -正式版対応済
- Using EditForm | Part - 29 | Using ASP.Net Blazor for Absolute Beginners