LoginSignup
42
42

More than 3 years have passed since last update.

【Blazor入門】Blazor初心者がログインからチャット機能まで付けてデプロイしてみた ~その1~

Last updated at Posted at 2020-08-09

はじめに

Blazorがリリースされてから1年程経ったのでしょうか。
ボチボチとドキュメントとか記事とかが上がってきているみたいなので重い腰をあげてやってみることにしました。

Blazorやってみたいけどどうすりゃいいんだろ、って人多いと思う(?)のでその手助けとなる記事になればと。

環境

  • VS2019
  • .NET Core SDK 3.1

情報収集

とりあえず色々とよくわかんないのでBlazor Advent Calendar 2019を一通り読んでみました。

分かった事としてはこう。

Razor記法

MVC時代razor記法という、HTMLC#を悪魔合体させられる記述が可能となった。cshtmlという拡張子。

例えば、こんな感じ。

hoge.cshtml
@for (int i = 0; i < 3; i++) {
  <p>for文のループの「@i」回目です。</p>
}

C#の構文と組み合わせる事で同じような記述を排除できるスグレモノ。
ただ、クライアントの処理は当然、JavaScriptで書く必要があった。まーしょうがないよね。

Blazor

そんな時に現れたのがBlazor
コイツはクライアント処理までC#で記述することができます。razorという拡張子。

counter.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++;
    }
}

counter.gif

フルC#により処理が完結させられるのは興奮しました。

これをみればある程度は分かる、かも。
キャプチャ.JPG

懸念

.razorファイルUIやらロジックやらを書いていけばいいのはわかった。十分に理解できた。ただ気になった事として、.razorファイルがめちゃめちゃfatになりませんか?ってのが非常に気になりました。

でも大丈夫っぽさそうで、
Blazorでコードビハインドでロジックとビューを分離して記述するに解決策が書いてあり、どうやらちゃんと分けて書くことができるようで安心しました。

今回はPartial Classでコードを書きます。ViewModelを使ってもよかったですが、DIをわざわざ書いてやる必要があったのでパス。

最終成果物

あとでGIFとソースコードを載せます。

アプリケーションの作成

さて、これから実際に作っていきます。

画面遷移図

特に要らないとも思いましたが、やったことないことをちゃんとやっていこうと思ったので簡易的ですが、LucidChartというサイトで作ってみました。
image.png

環境の構築

私の場合は色々と環境が整っていたのでやったのは.NET Core 3.1のSDKをインストールするぐらい。
Download .NET Core 3.1

Visual Studioが入ってないとかBlazorのテンプレートがない場合は以下の記事を参考にするとよいと思います。
C#でSPAを作るBlazorの、開発環境の作り方 - Visual Studio編

アプリケーションの作成

Blazor をお勧めできる人は誰か?を読んだんですが、サーバーとクライアントのどちらをどういう場合に使い分けるのかがよく分からなかったので取り急ぎはサーバーの方で作成します。

サーバー兼クライアントとして動かせるのでまーよいでしょう。
image.png

実行

↓↓↓↓↓↓↓ あなたの記事の内容
とりあえず実行してみて動くっていうのは初学者からすると物凄くハードルが下がるので非常にありがたいです。ということで作りたてほやほやのソリューションをデバッグしてみるとこうなります。
───────
とりあえず実行してみて動くっていうのは初学者からすると物凄く分かりやすいので非常にありがたいです。ということで作りたてほやほやのソリューションをデバッグしてみるとこうなります。
↑↑↑↑↑↑↑ 編集リクエストの内容
image.png

色合いがすげーイイ感じです。
では早速、このイイ感じの画面をぶっ壊していきます。

ログイン画面の生成

ログイン画面を生成していきましょう。

MainLayout.razorの修正

MainLayout.razorBodyだけにします。
左のナビゲーションからページ遷移をさせたくないので。

MainLayout.razor
@inherits LayoutComponentBase

<div class="main">
    <div class="content px-4">
        @Body
    </div>
</div>

Indexページの修正

インデックスページをログイン画面として使います。

当初は、こういう書き方をしていましたが、

Index.razor
<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をイイ感じにやってくれることが分かったので以下の様に変更しました。

Index.razor
@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フォルダ直下に作成してみてください。

すると、勝手に紐づけてくれます。しゅごい。
image.png

コードビハインドはこうなります。

Index.razor.cs
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を作成してください。
image.png

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"だけ記述されていれば遷移出来るはずです。
Counter.gif

テキストボックスへ未入力時にアノテーションが効いててイイ感じです。
ただ今の状態だと、何かしらの値がIDとパスワードに入ってさえいればログインできてしまうのでこの点は後で実装します。

まとめ

Blazorだとクライアント処理もC#で書ける反面、全ての処理をrazorファイルに記述しないといけないと思っていましたが、ちゃんとそこら辺を考えてあって分離できるのはよい機構だなと思いました。

次の記事では、遷移先のチャットページを作成してみたいと思います。

参考にさせて頂いたページ

42
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
42