【ASP.NET Core MVC】ASP.NET Core MVCであみだくじを作ってみる 5 (Razorを使う)

# 概要
前回：[ASP.NET Core MVCであみだくじを作ってみる 4 (cssの作成)](https://qiita.com/plusM/items/f13d2644689531c1c6c1)
今回は、Razorを使ってマスク領域を隠したり表示したりする機能を作ります。
また、くじの数の変更に対応できるよう、選択肢やくじを動的に描画するようにします。

[ASP.NET Core の Razor 構文リファレンス](https://docs.microsoft.com/ja-jp/aspnet/core/mvc/views/razor?view=aspnetcore-3.0)を参照しながら作っていきます。

# コントローラーにアクションを追加する
選択肢番号を押下した時に呼ぶアクションをKujiController.csに追加します。

```cs:KujiController.cs
using Amidakuji.Models;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace Amidakuji.Controllers
{
    public class KujiController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            ModelState.Clear();

            // 受け取ったTempDataからデータを取得する
            var json = TempData["kuji"]?.ToString();
            if (json != null)
            {
                var model = JsonConvert.DeserializeObject<KujiModel>(json);
                return View(model);
            }

            return View(new KujiModel());
        }

        /// <summary>
        /// 選択肢番号を押下した呼ばれるアクション
        /// </summary>
        /// <param name="id"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Index(int id, KujiModel model)
        {
            // 選択済の場合はやり直す
            if (model.SelectId > 0)
            {
                return View(model);
            }

            model.Title += " 結果";
            model.SelectId = id;    // 選択したくじ番号をセット

            return View(model);
        }
    }
}
```

# マスク領域の表示・非表示を切り替える
POSTされるように、Kuji\Index.cshtmlの\<div class="kuji-container">をformタグで囲み、
選択肢ボタンを\<a href="#"・・・からbuttonに変更します。
formタグには、[タグヘルパー](https://docs.microsoft.com/ja-jp/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-3.0#what-are-tag-helpers) asp-controller、asp-actionをセットし、KujiControllerのIndexアクションを呼ぶようにします。
buttonには、どのボタンを押下したかをIndexアクションのパラメータに渡せるよう、asp-route-idをセットします。

```html:Kuji\Index.cshtml
@model Amidakuji.Models.KujiModel

@{
    ViewData["Title"] = "あみだくじ";
}

<form method="post" asp-controller="Kuji" asp-action="Index">
    <div class="kuji-container">
        <h1>@Model.Title</h1>
        <p>くじの数は、@Model.NumberOfKuji 本です。</p>

        <!--あみだくじの領域(グリッドレイアウト)-->
        <div class="kuji-line">
            <!--選択肢ボタン-->
            <button class="select-btn" style="grid-row:2;grid-column:1" asp-route-id="1">1</button>
            <button class="select-btn" style="grid-row:2;grid-column:2" asp-route-id="2">2</button>
            <button class="select-btn" style="grid-row:2;grid-column:3" asp-route-id="3">3</button>
            <button class="select-btn" style="grid-row:2;grid-column:4" asp-route-id="4">4</button>
            <button class="select-btn" style="grid-row:2;grid-column:5" asp-route-id="5">5</button>

・・・省略・・・

            <!--あみだを隠すためのマスク領域-->
            @if (Model.SelectId == 0)
            {
                <div class="mask"></div>
            }
        </div>
    </div>

    <!--モデルをコントローラーへ通知-->
    <input type="hidden" asp-for="Title" value="@Model.Title" />
    <input type="hidden" asp-for="NumberOfKuji" value="@Model.NumberOfKuji" />
    @for (var i = 0; i < Model.Result.Count; i++)
    {
        <input type="hidden" asp-for="Result[i].Item" value="@Model.Result[i].Item" />
    }
    <input type="hidden" asp-for="SelectId" value="@Model.SelectId" />
</form>
```
KujiControllerのIndexアクションでSelectIdに選択したくじ番号をセットしています。
未選択の時は、SelectId＝0です。このため、SelectId＝0の時だけマスク領域を表示するようにしています。

\<!--モデルをコントローラーへ通知-->の部分は、KujiControllerのIndexアクションで自身のViewに戻るため、
モデルデータが消えないようにhidden項目にデータを持たせています。

# 選択肢ボタンやくじを動的に描画する
くじの数を固定で作ってきましたが、せっかくHomeビューで数を設定できるようにしたので、
選択肢ボタンやくじを、くじの数によって動的に描画することにします。

くじの縦線の長さや縦線と縦線の間に引く横線の数や位置がランダムになるよう、Randomクラスで乱数を発生させました。
また、縦線と縦線の間に引く横線が同じ行番号にならないよう工夫してみました。

\<div class="kuji-line">の中を以下のように変更します。

```html:Kuji\Index.cshtml
        <!--あみだくじの領域(グリッドレイアウト)-->
        <div class="kuji-line">
            @{
                var rd = new Random();
                var rcount = Math.Max(20, Model.Result.Count * 4);   // グリッドレイアウトの行数

                // 行番号リスト(4行目以降、全行数 - 上下のボタンや結果表示域で使用している行を除く行数)
                var rows = Enumerable.Range(4, rcount - 6).ToList();

                <!--人数の分だけループ-->
                for (var i = 1; i < Model.Result.Count + 1; i++)
                {
                    <!--選択肢ボタン-->
                    <button class="select-btn" style="grid-row:2;grid-column:@i" asp-route-id="@i">@i</button>

                    <!--縦線-->
                    <div class="vertical-line" style="grid-row:3 / span @(rcount - 4);grid-column:@i"></div>

                    <!--横線-->
                    if (i < Model.NumberOfKuji)
                    {
                        var hcount = rd.Next(1, rcount / 4);   // 横線の数

                        for (var j = 0; j < hcount; j++)
                        {
                            if (rows.Count <= 0) break; // 行が足りなくなったら終了

                            int rno = rows[rd.Next(0, rows.Count - 1)]; // 横線を引く行番号
                            rows.Remove(rno);   // 重複する行番号を使わないようにするため

                            <p class="horizontal-line" style="grid-row:@rno;grid-column:@i"></p>
                        }
                    }

                    <!--横幅を揃えるため、PadRightで5文字分に揃える-->
                    <div style="grid-row:@(rcount - 1);grid-column:@i">@Model.Result[i - 1].Item.PadRight(5, '　')</div>
                }

                <!--1行分を余白とする-->
                <div style="grid-row:@rcount;grid-column:1 / span @Model.NumberOfKuji"></div>
            }

            <!--あみだを隠すためのマスク領域-->
            @if (Model.SelectId == 0)
            {
                <div class="mask"></div>
            }
        </div>
```
@{ }とすると、{ }の中にC#コードを埋め込むことができます。
\<div>や\<button>などタグの中では、@{ }の中でも変数には＠を付ける必要があるようです。

# 実行してみる
Homeビューでくじの数を設定→結果の文字列を入力→くじを作る→選択肢ボタンを押下したのが下図の動きです。
![実行.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520699/e0ac0681-0a0f-fe8e-dec7-0d7362a1af93.gif)

# まとめ
今回は、Razorを使ってマスク領域を隠したり表示したりする機能を作成しました。
次回は、Razorを使って選択した番号のあみだを辿る処理を作ります。
次回分はこちら⇒[ASP.NET Core MVCであみだくじを作ってみる 6 (Razorを使う あみだを辿る編)](https://qiita.com/plusM/items/a77def9585ba787a3c40)