【ASP.NET Core】Razor Pagesを使って簡易的なTodoアプリを作った

# はじめに
業務でRazor Pagesを使うことになったので、Todoアプリを作りながらどんなものか勉強しました。
本記事では、Razor Pagesとは何か、自分が開発したもの、および学んだことをまとめていこうと思います！

# Razor Pagesの概要
Razor Pagesとは、**ASP.NET Coreで開発できる、ページコーディングに重点を置いたWebアプリケーション**です。

## ASP.NET Coreとは
> ASP.NET Core は、macOS、Linux、および Windows 上で実行される ASP.NET のオープンソース バージョンです。
> > https://dotnet.microsoft.com/ja-jp/learn/aspnet/what-is-aspnet-core

つまり、.NET環境で開発・動作するWeb開発フレームワークであるASP.NETを、クロスプラットフォームでオープンソースとして作り直したものが、ASP.NET Coreとなります。

以前はどちらも開発が進められていましたが、今は統合されてASP.NET Coreを本流としています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/8a36ef24-cba3-c1a9-822e-dca16976be5b.png)

これらは、以下の通り作成できるアプリケーションに違いがあります。

ASP.NET：
* Webフォーム
* MVC
* Webページ

ASP.NET Core：
* **Razor Pages**
* MVC
* Blazor

## ページコーディングに重点を置いたとは
MVCと比較すると分かりやすく、
MVCがコードとビューを分離し、複数のページを一つのコントローラーで集中管理しているのに対して、**Razor Pagesでは、コードとビューが1対1で対応しており、ページ単位で整理しながら開発を進める**ことができます。
（ASP.NET Webフォームや、デスクトップアプリであるWindowsフォームやWPF、UWPのように、画面とコードビハインドがセットになっています）

そのため、Razor Pagesは各ページ単位で完結するようなアプリケーションの開発に向いており、逆に複数ページで頻繁にデータを共有するようなケースは苦手としています。

# 開発したTodoアプリ
## 設計書
https://qiita.com/Saku731/items/741fcf0f40dd989ee4f8

ちょうど最近読んだこちらの記事が勉強になったので、参考にしてドキュメントを作るところから始めてみました。

**画面設計**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/3ea90fac-581e-a9e0-fbf7-8a176de117ff.png)

**機能設計**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/968281aa-b1ab-14a4-414a-4e920955ee52.png)
**データ設計**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/49e2f876-1b00-a94c-9481-c7616c253017.png)

## 画面
（一部抜粋）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/b0f8ead0-6381-ae6e-a327-c7477bb32c0c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/ab55caef-5607-5d87-f39d-8a97a5a071fd.png)

## リポジトリ
https://github.com/y1221/todo-asp.net-razor-pages.git

## 補足
「簡易的」とだけあって、明らかに不足している機能（ユーザごとのカテゴリ管理や、アカウントの編集・削除などなど）や、デザインについてほとんどノータッチである点など、改善の余地だらけですが、時間をかけずにRazor Pagesの理解に重点を置いたためこれでよしとしています。。

# 開発してみて
## 身についたこと
Razor Pagesのルーティングや、値を受け渡す方法、Entity Framework Coreを利用したスキャフォールディング、CRUD処理、DBマイグレーションなどに加えて、Razor構文、タグヘルパーやHTMLヘルパー、モデルの検証などを理解することができました。

## 便利だと思ったこと
### ページコーディング × Razor構文
ビュー・コードが密接に結びついているという特徴と、HTML内にC#コードを埋め込むことができるRazor構文の組み合わせがとても強力だと感じました。

実際に、Todoアプリのタスク一覧やカテゴリ一覧の表示には、コード側でDBからデータを取得して保持しておき、画面側でそのデータを参照しつつfor文を回してHTMLを生成することで実現しています。

このように、**ビュー・コード間でデータを簡単に渡すことができ、その上で制御構文を使って柔軟に画面を作れる**点がRazor Pagesの魅力的な特徴の一つだと実感しました。

### モデルの検証
モデル側で各項目の表示名やバリデーションなどを一元管理することができる点も便利だと感じました。
こちらはRazor Pages独自の機能ではなく、ASP.NET Coreで共通して使うことができます。

使い方としては、以下の通りモデルに定義しておけば、
```C#:Todo.cs
[Display(Name = "タスク")]
[DataType(DataType.Text)]
[Required(ErrorMessage = "必須項目です。")]
[StringLength(30, ErrorMessage = "30文字以下で入力してください。")]
public string Name { get; set; } = string.Empty;
```
各画面で以下の通り定義してあげるだけで、
```HTML:Create.cshtml.cs
<form>
    <label asp-for="Todo.Name"></label>
    <input asp-for="Todo.Name" />
    <span asp-validation-for="Todo.Name"></span>
</form>
```
* 文字列「タスク」のlabelタグ
* type="text"のinputタグ
* 必須チェックおよびエラーメッセージ
* 文字数チェックおよびエラーメッセージ

これらを自動で実装してくれます。

各画面で同じような処理を実装する必要がなく、モデルとして一括で管理できる点が使いやすかったです。

### <span>@</span>functionsディレクティブ
こちらもASP.NET Coreで共通の機能ですが、ページコーディングとの相性は抜群だと思います。

用途としては、コード（サーバ側）での処理結果に対し、ビュー（フロント側）で条件を満たす要素のみ振る舞いを変えたい時などに重宝します。

今回のTodoアプリでは、ユーザが選択したカテゴリにのみCSSを適用する処理を実装するのに利用しました。
具体的な実装方法は以下記事にまとめていますので、ご覧いただければ幸いです。

https://qiita.com/okayu__11/items/8ba157db72918c3bfbf9

# おわりに
Entity Framework Coreがデータアクセスを容易にし、Razor構文やタグヘルパーが画面の組み立てを柔軟にしていますが、
**Razor Pagesはこれらの間に入り、ビュー・コード間でデータの受け渡しを容易にすることで、高速なWebアプリケーション開発を実現している**のだと学ぶことができました。
まだまだ知らない便利機能があったり、Webアプリケーション自体の知識が足りないと思うので、引き続き学んでいけたらと思います。

また、簡易的なものであっても、手を動かしてアプリケーションを作ってみることで学びが定着することを改めて実感することができました。

ここまでご一読いただき、ありがとうございました！

# 動作環境
* Windows 11 Home（23H2）
* .NET 8.0（SDK 8.0.204）
* Visual Studio 2022

# 参考
Razor Pages全般
[チュートリアル: ASP.NET Core で Razor Pages Web アプリを作成する](https://learn.microsoft.com/ja-jp/aspnet/core/tutorials/razor-pages/?view=aspnetcore-8.0)

アクションの振り分け
[ASP.NET Core のアンカー タグ ヘルパー](https://learn.microsoft.com/ja-jp/aspnet/core/mvc/views/tag-helpers/built-in/anchor-tag-helper?view=aspnetcore-8.0#asp-page-handler)

Razor構文
[ASP.NET Core の Razor 構文リファレンス](https://learn.microsoft.com/ja-jp/aspnet/core/mvc/views/razor?view=aspnetcore-8.0)

Entity Framework Core（一対多リレーションシップ）
[一対多のリレーションシップ](https://learn.microsoft.com/ja-jp/ef/core/modeling/relationships/one-to-many)