前回のおさらい
https://qiita.com/CheerfulGeneral/items/be34fcccfe397c27d064 1行掲示板を モダンになったASP.net coreで作ってみようという試みです。 前回は ・Model(掲示板データ)を定義 ・データベースのマイグレーション(初期化) ・スキャフォールディング(骨組みページ)の作成 を行いました。 今回はスキャフォールディングを編集して、掲示板を完成させたいと思います。 軽くRazorも見てみましょう。1.CRUDページ
https://wa3.i-3-i.info/word123.html CRUD(クラッドと読むらしい)とは Create, Read, Update, Delete の頭文字であり、要するにデータを作ったり処理することです。 スキャフォールディングを作成すると、このCRUDページが自動作成されます。 以下の名前でページが作成されています。 ・Index (データを表示させるページ CRUDのR) ・Create (データを作成するページ CRUDのC) ・Edit (データを編集するページ CRUDのU) ・Detail (データを詳細にみるページ CRUDのR 2つめ) ・Delete (データを削除するページ CRUDのD)前回はIndexとCreateをそのまま表示させて
1行掲示板みたいに使いました。
今回はこの2つをベースに、もっと掲示板ぽくしてみようと思いいます。
2.Indexページから見るRazorコード
![index.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595683/31728acb-4426-5ef7-1f37-01c623ae38e0.png)@page
@model RasorSample.Pages.BBS.IndexModel
@{
ViewData["Title"] = "1行掲示板";
}
<h1>1行掲示板</h1>
<p>
<a asp-page="Create">投稿する</a>
</p>
<table class="table">
<tbody>
@foreach (var item in Model.Writing) {
<tr>
<td>
<h2>@Html.DisplayFor(modelItem => item.Name)</h2>
</td>
<td>
<h2>@Html.DisplayFor(modelItem => item.Comment)</h2>
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">編集</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">削除</a>
</td>
</tr>
}
</tbody>
</table>
Indexページを上記のように改修しました。
ページは.cshtmlという拡張子ファイルで出来います。
改修箇所とRazor
Indexで改修したのは 1.Tableのtheadを消去して、掲示板ぽくした。 2.Titleおよび他用語の日本語化 です。 Razorの形式を見ながら、改修箇所を見ていきましょう。@page
@page
Razorはアットマーク(@)の後に
コードを書く形式となっております。
@pageは、このファイルがRazorですよーという合図のようです。
@model
@model RasorSample.Pages.BBS.IndexModel
モデルを参照するコードです。
WPFの開発をしたことがる人はわかるかもしれませんが、
Razorページは.cshtmlの裏にC#ファイル(.cshtml.cs)があります。
このC#ファイルのクラスが「IndexModel」という名前です。
モデルをC#で扱う形式に変換するというイメージかもしれません。
@ViewData
``` @{ ViewData["Title"] = "1行掲示板"; } ``` @の中の「ViewData["Title"]でページタイトルを編集します。 ViewDataというのはページ表示項目を集めた辞書となっており その"Title"キーの値を編集します。asp属性
htmlのaタグに「asp-○○」という属性があります。<a asp-page="Create">投稿する</a>
<a asp-page="./Edit" asp-route-id="@item.ID">編集</a> |
asp-pageは指定したアドレスに移行します。
(FormのGetメソッドみたい)
asp-route-idはルートidをつける属性みたいです。
ルートidを調べてみましたが、よくわかりませんでした...
(ページ移行アクションで間違いがないように、IDを送るみたいですが...)
この辺りを改修すれば、掲示板みたいな表示になりました。
3.Createページ
![Create.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595683/560d0078-53c0-9748-b13f-4e8547a89f00.png)@page
@model RasorSample.Pages.BBS.CreateModel
@{
ViewData["Title"] = "投稿ページ";
}
<h1>投稿する</h1>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Writing.Name" class="control-label"></label>
<input asp-for="Writing.Name" class="form-control" />
<span asp-validation-for="Writing.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label class="control-label">書き込み内容</label>
<input asp-for="Writing.Comment" class="form-control" />
<span asp-validation-for="Writing.Comment" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Writing.ReleaseDate" class="control-label"></label>
<input asp-for="Writing.ReleaseDate" class="form-control" />
<span asp-validation-for="Writing.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="投稿" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">掲示板に戻る</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
記入したデータをCreate(掲示板に投稿)する画面です。
基本的に改修はIndexと同様に
必要な表示箇所を直すくらいです。
ここでは、Indexでは見なかったC#ファイルを見てみましょう。
using RasorSample.Model;
namespace RasorSample.Pages.BBS
{
public class CreateModel : PageModel
{
private readonly RasorSample.Data.RasorSampleContext _context;
public CreateModel(RasorSample.Data.RasorSampleContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Writing Writing { get; set; }
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Writing.Add(Writing);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
上の方ではcontext(ページ内容を含むクラス?)を作成しています。
OnGetメソッドでページを初期化します。
真ん中の[BindProperty]では、作ったModelクラスのプロパティを作成しております。
Createで重要なのは OnPostAsync()メソッドです。
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Writing.Add(Writing);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
これはページでデータが送信された際に処理されます。
データフォームが正常であれば、Post送信されてIndexに戻ります。
4.その他ページ・通常MVCとの違い
![Edit.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595683/8f4c1aa9-dfb6-933a-bb2d-b2975e99ec29.png) ![Delete.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595683/6023b9ef-44ba-2cca-87b8-d77d98806d5d.png)CRUDには他にもページがありますが、
Indexなどの要領で同様に改修しました。
ASP.net coreではスキャフォールディングを作成すれば
Webアプリの基本動作は自動で実装してくれます。
他Webフレームワークのように、最初からViewやControllerを作らなくても
簡単にWebアプリケーションを作れてしまいます。
Createの箇所を見て気づいた方がいらっしゃると思いますが
RazorでWebアプリを作成する場合
1ページ(1 View)に1つのC#ファイル(1 Controller)が付きます。
そのため、ページごとに動作・Controllerを書きます。
通常のMVCはControllerを一括で書いて、
ルーティングごとにViewの切り替えをしていたと思います。
ここがRazorと通常MVCフレームワークの違いです。
個人的にはRazorの方が作りやすいなーと感じました。
(WPFの経験があるのも関係あるかもしれません。)
5.IndexとCreateをくっつけてみた
これで1行掲示板になった!と安心していましたが 第1回で載せた掲示板イメージはこんなのでした。 ![1行掲示板イメージズ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595683/eeaebe5b-cde6-5aa4-8993-2585b83935ba.png)てなわけで、イメージ通りになるように
IndexとCreateをくっつけてみました。
@page
@model RasorSample.Pages.BBS.IndexModel
@{
ViewData["Title"] = "1行掲示板";
}
<h1>1行掲示板</h1>
<div class="row">
<div class="col-3"></div>
<div class="col-6">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="WritingCreator.Name" class="control-label"></label>
<input asp-for="WritingCreator.Name" class="form-control" />
<span asp-validation-for="WritingCreator.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label class="control-label">書き込み内容</label>
<input asp-for="WritingCreator.Comment" class="form-control" />
<span asp-validation-for="WritingCreator.Comment" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="投稿" class="btn btn-primary" />
</div>
</form>
</div>
<div class="col-3"></div>
</div>
<table class="table">
<tbody>
@foreach (var item in Model.Writing) {
<tr>
<td>
<h2>@Html.DisplayFor(modelItem => item.Name)</h2>
</td>
<td>
<h2>@Html.DisplayFor(modelItem => item.Comment)</h2>
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">編集</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">削除</a>
</td>
</tr>
}
</tbody>
</table>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RasorSample.Model;
namespace RasorSample.Pages.BBS
{
public class IndexModel : PageModel
{
private readonly RasorSample.Data.RasorSampleContext _context;
public IndexModel(RasorSample.Data.RasorSampleContext context)
{
_context = context;
}
public IList<Writing> Writing { get;set; } //For Index
[BindProperty]
public Writing WritingCreator { get; set; } //For Create
public async Task OnGetAsync() //For Index
{
Writing = await _context.Writing.ToListAsync();
}
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync() //For Create
{
if (!ModelState.IsValid)
{
return Page();
}
WritingCreator.ReleaseDate = DateTime.Now; //投稿時の日付を自動記載
_context.Writing.Add(WritingCreator);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
IndexにCreateを貼り付けただけですね(笑
日付の選択が面倒だと思ったので、書き込み時の日付を
自動的に記入するようにしました。
スキャフォールディングで素材が全てそろっているので
コピペだけでもここまで出来てしまいます。
(余談)cshtmlを編集していた際に、col-○○を使用して思いましたが
このRazorページってBootstrapを標準装備しているんですね。
(ASP.netの標準装備に同様なcolクラスがあるのかもしれないが)
まとめと今後の展望
Razorでスキャフォールディングを使えば とても楽にMVCのWebアプリが作れました。 今度はSPA(シングルページアプリケーション)に挑戦してみたいと思います。私も勉強しながら投稿しているため、
随分知識不足で正しくなさそうな書き込みとなってしまいました...oTL
もし間違いや指摘がありましたら、遠慮なくコメントお願いします。
また、ご存じの方がいらしましたら下記の情報提供をお願いします。
・ASP.net core 5.0のアプリを公開できるシステムorレンタルサーバー
本来はVPSやクラウドに実行環境載せるのだと思いますが、このあたりの知識がまだ乏しくて...
・ASP.net core 5.0でMySQLを使う
調査してみましたが、Web勉強中素人の私ではよく扱えませんでした...
(この辺りはASP.net core 5.0がリリースしてまだ3カ月しか経ってないため
情報もそんなないと思いますが...)
参考文献
https://demi-urge.com/razor-mvc-difference/ MVCとRazorの違いがわかりやすく図示されております。https://github.com/Sho-Zhao/RasorSample
GitHubにRazorで作った1行掲示板をアップロードしました。