パート 3、ASP.NET Core でスキャフォールディングされた Razor ページ
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
作成者: Rick Anderson
このチュートリアルでは、前のチュートリアルでスキャフォールディングによって作成された Razor ページについて説明します。
[作成]、[削除]、[詳細]、および [編集] ページ
Pages/Movies/Index.cshtml.cs
ページ モデルを調べます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor ページは PageModel から派生します。 慣例により、PageModel
派生クラスには、PageNameModel
という名前が付けられます。 たとえば、Index ページには、IndexModel
という名前が付けられます。
コンストラクターは依存性の注入を使用して、RazorPagesMovieContext
をページに追加します。
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework での非同期プログラミングの詳細については、「非同期コード」を参照してください。
ページに対して GET
要求が行われると、OnGetAsync
メソッドにより Razor Page にムービーのリストが返されます。 Razor ページでは、OnGetAsync
または OnGet
が呼び出され、ページの状態が初期化されます。 この場合、OnGetAsync
でムービーのリストを取得し、表示します。
OnGet
によって void
が返される場合、または OnGetAsync
によって Task
が返される場合は、return ステートメントは使用されません。 たとえば、Privacy ページを調べます。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
戻り値の型が IActionResult または Task<IActionResult>
の場合は、return ステートメントを指定する必要があります。 たとえば、Pages/Movies/Create.cshtml.cs OnPostAsync
メソッドでは、次の操作を行います。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Pages/Movies/Index.cshtml
Razor ページを調べます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor では、HTML から C# または Razor 固有のマークアップに移行できます。 @
シンボルの後に Razor で予約済みのキーワードが続いている場合は、Razor 固有のマークアップに移行します。それ以外の場合は、C# に移行します。
@page ディレクティブ
@page
Razor ディレクティブを使うと、ファイルが MVC アクションになります。つまり、これで要求を処理できます。 @page
はページ上で最初の Razor ディレクティブである必要があります。 @page
および @model
は、Razor 固有のマークアップへの移行の例です。 詳細については、「Razor の構文」を参照してください。
@model ディレクティブ
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
ディレクティブは、Razor ページに渡されるモデルの型を指定します。 前の例では、@model
行によって、Razor ページで PageModel
派生クラスが使用できるようになります。 モデルは、ページの @Html.DisplayNameFor
および @Html.DisplayFor
HTML ヘルパーで使用されます。
次の HTML ヘルパーで使用されるラムダ式を確認します。
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML ヘルパーは、ラムダ式で参照される Title
プロパティを検査し、表示名を判別します。 ラムダ式は評価されるのではなく検査されます。 これは、model
、model.Movie
、または model.Movie[0]
が null
または空である場合、アクセス違反がないことを意味します。 ラムダ式が (@Html.DisplayFor(modelItem => item.Title)
などを使用して) 評価される場合は、モデルのプロパティ値が評価されます。
レイアウト ページ
メニューのリンク ([RazorPagesMovie]、[Home]、[Privacy]) を選択します。 各ページには同じメニューのレイアウトが表示されます。 メニューのレイアウトは、Pages/Shared/_Layout.cshtml
ファイルに実装されています。
Pages/Shared/_Layout.cshtml
ファイルを開いて調べます。
レイアウト テンプレートを使用すると、HTML コンテナーのレイアウトを次のようにすることができます。
- 1 つの場所で指定される。
- サイトの複数のページに適用される。
@RenderBody()
という行を見つけます。 RenderBody
は、ページ固有のビューがすべて表示されるプレースホルダーで、レイアウト ページに "ラップ" されます。 たとえば、 Privacy リンクを選択すると、RenderBody
メソッド内で Pages/Privacy.cshtml
ビューがレンダリングされます。
ViewData とレイアウト
Pages/Movies/Index.cshtml
ファイルの次のマークアップを考えてみます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
上の強調表示されたマークアップは、Razor の C# への移行例です。 {
文字と }
文字で C# コードのブロックを囲みます。
PageModel
基底クラスには ViewData
辞書プロパティが含まれており、これを使用してビューにデータを渡すことができます。 オブジェクトは、"キー値" のパターンを使用して、ViewData
辞書に追加されます。 上のサンプルでは、Title
プロパティが ViewData
辞書に追加されます。
Title
プロパティは、Pages/Shared/_Layout.cshtml
ファイルで使用されます。 次のマークアップは、 _Layout.cshtml
ファイルの最初の数行を示しています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
レイアウトの更新
RazorPagesMovie ではなく、Movie が表示されるように、
Pages/Shared/_Layout.cshtml
ファイルの<title>
要素を変更します。<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
Pages/Shared/_Layout.cshtml
ファイルで次のアンカー要素を見つけます。<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
上の要素を次のマークアップに置き換えます。
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
上のアンカー要素はタグ ヘルパーです。 この場合は、アンカー タグ ヘルパーです。
asp-page="/Movies/Index"
タグ ヘルパーの属性と値によって、/Movies/Index
Razor ページへのリンクが作成されます。asp-area
属性の値が空なので、リンクではこの区分が使用されていません。 詳細については、区分に関する記事を参照してください。変更内容を保存し、RpMovie リンクを選択してアプリをテストします。 問題がある場合は、GitHub の _Layout.cshtml ファイルを参照してください。
Home、RpMovie、Create、Edit、Delete の各リンクをテストします。 各ページで、ブラウザー タブで表示できるタイトルを設定します。ページをブックマークすると、ブックマークでタイトルが使用されます。
Note
Price
フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマの追加方法については、こちらの GitHub issue 4076 を参照してください。
Layout
プロパティは、Pages/_ViewStart.cshtml
ファイルに設定されます。
@{
Layout = "_Layout";
}
上のマークアップを使用すると、Pages フォルダーのすべての Razor ファイルについて、レイアウト ファイルを Pages/Shared/_Layout.cshtml
に設定します。 詳細については、「Layout」 (レイアウト) を参照してください。
Create ページのモデル
Pages/Movies/Create.cshtml.cs
ページ モデルを確認します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
メソッドは、ページに必要な状態を初期化します。 [作成] ページには初期化する状態はないため、Page
が返されます。 このチュートリアルの後半では、状態を初期化する OnGet
の例を示します。 Page
メソッドでは、Create.cshtml
ページをレンダリングする PageResult
オブジェクトが作成されます。
Movie
プロパティでは [BindProperty] 属性を使用して、モデル バインドにオプトインします。 [作成] フォームでフォーム値が投稿されると、ASP.NET Core ランタイムが投稿された値を Movie
モデルにバインドします。
OnPostAsync
メソッドは、ページでフォーム データが投稿されたときに実行されます。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
モデル エラーがある場合は、投稿されたフォーム データと共にフォームが再表示されます。 ほとんどのモデル エラーは、フォームが投稿される前にクライアント側でキャッチできます。 モデル エラーの例では、日付に変換できない日付フィールドの値が投稿されています。 クライアント側の検証とモデルの検証については、チュートリアルの後半で説明します。
モデル エラーがない場合は、次のようになります。
- データが保存されます。
- ブラウザーは Index ページにリダイレクトされます。
Razor の作成ページ
Pages/Movies/Create.cshtml
Razor ページ ファイルを調べます。
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<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="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio に、タグ ヘルパーで使用される独特な太字のフォントで次のタグが表示されます。
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
要素はフォーム タグ ヘルパーです。 フォーム タグ ヘルパーには自動的に偽造防止トークンが含まれます。
スキャフォールディング エンジンでは、次のような、(ID を除く) モデルの各フィールドの Razor マークアップが作成されます。
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
検証タグ ヘルパー (<div asp-validation-summary
と <span asp-validation-for
) には検証エラーが表示されます。 検証については、後で詳しく説明します。
ラベル タグ ヘルパー (<label asp-for="Movie.Title" class="control-label"></label>
) は、Title
プロパティのラベル キャプションと [for]
属性を生成します。
入力タグ ヘルパー (<input asp-for="Movie.Title" class="form-control">
) は DataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。
<form method="post">
などのタグ ヘルパーについては、「ASP.NET Core のタグ ヘルパー」を参照してください。
次のステップ
[作成]、[削除]、[詳細]、および [編集] ページ
Pages/Movies/Index.cshtml.cs
ページ モデルを調べます。
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor ページは PageModel から派生します。 慣例により、PageModel
派生クラスには、PageNameModel
という名前が付けられます。 たとえば、Index ページには、IndexModel
という名前が付けられます。
コンストラクターは依存性の注入を使用して、RazorPagesMovieContext
をページに追加します。
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework での非同期プログラミングの詳細については、「非同期コード」を参照してください。
ページに対して GET
要求が行われると、OnGetAsync
メソッドにより Razor Page にムービーのリストが返されます。 Razor ページでは、OnGetAsync
または OnGet
が呼び出され、ページの状態が初期化されます。 この場合、OnGetAsync
でムービーのリストを取得し、表示します。
OnGet
によって void
が返される場合、または OnGetAsync
によって Task
が返される場合は、return ステートメントは使用されません。 たとえば、Privacy ページを調べます。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
戻り値の型が IActionResult または Task<IActionResult>
の場合は、return ステートメントを指定する必要があります。 たとえば、Pages/Movies/Create.cshtml.cs OnPostAsync
メソッドでは、次の操作を行います。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Pages/Movies/Index.cshtml
Razor ページを調べます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor では、HTML から C# または Razor 固有のマークアップに移行できます。 @
シンボルの後に Razor で予約済みのキーワードが続いている場合は、Razor 固有のマークアップに移行します。それ以外の場合は、C# に移行します。
@page ディレクティブ
@page
Razor ディレクティブを使うと、ファイルが MVC アクションになります。つまり、これで要求を処理できます。 @page
はページ上で最初の Razor ディレクティブである必要があります。 @page
および @model
は、Razor 固有のマークアップへの移行の例です。 詳細については、「Razor の構文」を参照してください。
@model ディレクティブ
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
ディレクティブは、Razor ページに渡されるモデルの型を指定します。 前の例では、@model
行によって、Razor ページで PageModel
派生クラスが使用できるようになります。 モデルは、ページの @Html.DisplayNameFor
および @Html.DisplayFor
HTML ヘルパーで使用されます。
次の HTML ヘルパーで使用されるラムダ式を確認します。
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML ヘルパーは、ラムダ式で参照される Title
プロパティを検査し、表示名を判別します。 ラムダ式は評価されるのではなく検査されます。 これは、model
、model.Movie
、または model.Movie[0]
が null
または空である場合、アクセス違反がないことを意味します。 ラムダ式が (@Html.DisplayFor(modelItem => item.Title)
などを使用して) 評価される場合は、モデルのプロパティ値が評価されます。
レイアウト ページ
メニューのリンク ([RazorPagesMovie]、[Home]、[Privacy]) を選択します。 各ページには同じメニューのレイアウトが表示されます。 メニューのレイアウトは、Pages/Shared/_Layout.cshtml
ファイルに実装されています。
Pages/Shared/_Layout.cshtml
ファイルを開いて調べます。
レイアウト テンプレートを使用すると、HTML コンテナーのレイアウトを次のようにすることができます。
- 1 つの場所で指定される。
- サイトの複数のページに適用される。
@RenderBody()
という行を見つけます。 RenderBody
は、ページ固有のビューがすべて表示されるプレースホルダーで、レイアウト ページに "ラップ" されます。 たとえば、 Privacy リンクを選択すると、RenderBody
メソッド内で Pages/Privacy.cshtml
ビューがレンダリングされます。
ViewData とレイアウト
Pages/Movies/Index.cshtml
ファイルの次のマークアップを考えてみます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
上の強調表示されたマークアップは、Razor の C# への移行例です。 {
文字と }
文字で C# コードのブロックを囲みます。
PageModel
基底クラスには ViewData
辞書プロパティが含まれており、これを使用してビューにデータを渡すことができます。 オブジェクトは、"キー値" のパターンを使用して、ViewData
辞書に追加されます。 上のサンプルでは、Title
プロパティが ViewData
辞書に追加されます。
Title
プロパティは、Pages/Shared/_Layout.cshtml
ファイルで使用されます。 次のマークアップは、 _Layout.cshtml
ファイルの最初の数行を示しています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
レイアウトの更新
RazorPagesMovie ではなく、Movie が表示されるように、
Pages/Shared/_Layout.cshtml
ファイルの<title>
要素を変更します。<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
Pages/Shared/_Layout.cshtml
ファイルで次のアンカー要素を見つけます。<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
上の要素を次のマークアップに置き換えます。
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
上のアンカー要素はタグ ヘルパーです。 この場合は、アンカー タグ ヘルパーです。
asp-page="/Movies/Index"
タグ ヘルパーの属性と値によって、/Movies/Index
Razor ページへのリンクが作成されます。asp-area
属性の値が空なので、リンクではこの区分が使用されていません。 詳細については、区分に関する記事を参照してください。変更内容を保存し、RpMovie リンクを選択してアプリをテストします。 問題がある場合は、GitHub の _Layout.cshtml ファイルを参照してください。
Home、RpMovie、Create、Edit、Delete の各リンクをテストします。 各ページで、ブラウザー タブで表示できるタイトルを設定します。ページをブックマークすると、ブックマークでタイトルが使用されます。
Note
Price
フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマの追加方法については、こちらの GitHub issue 4076 を参照してください。
Layout
プロパティは、Pages/_ViewStart.cshtml
ファイルに設定されます。
@{
Layout = "_Layout";
}
上のマークアップを使用すると、Pages フォルダーのすべての Razor ファイルについて、レイアウト ファイルを Pages/Shared/_Layout.cshtml
に設定します。 詳細については、「Layout」 (レイアウト) を参照してください。
Create ページのモデル
Pages/Movies/Create.cshtml.cs
ページ モデルを確認します。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
メソッドは、ページに必要な状態を初期化します。 [作成] ページには初期化する状態はないため、Page
が返されます。 このチュートリアルの後半では、状態を初期化する OnGet
の例を示します。 Page
メソッドでは、Create.cshtml
ページをレンダリングする PageResult
オブジェクトが作成されます。
Movie
プロパティでは [BindProperty] 属性を使用して、モデル バインドにオプトインします。 [作成] フォームでフォーム値が投稿されると、ASP.NET Core ランタイムが投稿された値を Movie
モデルにバインドします。
OnPostAsync
メソッドは、ページでフォーム データが投稿されたときに実行されます。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
モデル エラーがある場合は、投稿されたフォーム データと共にフォームが再表示されます。 ほとんどのモデル エラーは、フォームが投稿される前にクライアント側でキャッチできます。 モデル エラーの例では、日付に変換できない日付フィールドの値が投稿されています。 クライアント側の検証とモデルの検証については、チュートリアルの後半で説明します。
モデル エラーがない場合は、次のようになります。
- データが保存されます。
- ブラウザーは Index ページにリダイレクトされます。
Razor の作成ページ
Pages/Movies/Create.cshtml
Razor ページ ファイルを調べます。
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<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="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio に、タグ ヘルパーで使用される独特な太字のフォントで次のタグが表示されます。
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
要素はフォーム タグ ヘルパーです。 フォーム タグ ヘルパーには自動的に偽造防止トークンが含まれます。
スキャフォールディング エンジンでは、次のような、(ID を除く) モデルの各フィールドの Razor マークアップが作成されます。
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
検証タグ ヘルパー (<div asp-validation-summary
と <span asp-validation-for
) には検証エラーが表示されます。 検証については、後で詳しく説明します。
ラベル タグ ヘルパー (<label asp-for="Movie.Title" class="control-label"></label>
) は、Title
プロパティのラベル キャプションと [for]
属性を生成します。
入力タグ ヘルパー (<input asp-for="Movie.Title" class="form-control">
) は DataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。
<form method="post">
などのタグ ヘルパーについては、「ASP.NET Core のタグ ヘルパー」を参照してください。
次のステップ
[作成]、[削除]、[詳細]、および [編集] ページ
Pages/Movies/Index.cshtml.cs
ページ モデルを調べます。
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor ページは PageModel から派生します。 慣例により、PageModel
派生クラスには、PageNameModel
という名前が付けられます。 たとえば、Index ページには、IndexModel
という名前が付けられます。
コンストラクターは依存性の注入を使用して、RazorPagesMovieContext
をページに追加します。
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework での非同期プログラミングの詳細については、「非同期コード」を参照してください。
ページに対して GET
要求が行われると、OnGetAsync
メソッドにより Razor Page にムービーのリストが返されます。 Razor ページでは、OnGetAsync
または OnGet
が呼び出され、ページの状態が初期化されます。 この場合、OnGetAsync
でムービーのリストを取得し、表示します。
OnGet
によって void
が返される場合、または OnGetAsync
によって Task
が返される場合は、return ステートメントは使用されません。 たとえば、Privacy ページを調べます。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
戻り値の型が IActionResult または Task<IActionResult>
の場合は、return ステートメントを指定する必要があります。 たとえば、Pages/Movies/Create.cshtml.cs OnPostAsync
メソッドでは、次の操作を行います。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Pages/Movies/Index.cshtml
Razor ページを調べます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor では、HTML から C# または Razor 固有のマークアップに移行できます。 @
シンボルの後に Razor で予約済みのキーワードが続いている場合は、Razor 固有のマークアップに移行します。それ以外の場合は、C# に移行します。
@page ディレクティブ
@page
Razor ディレクティブを使うと、ファイルが MVC アクションになります。つまり、これで要求を処理できます。 @page
はページ上で最初の Razor ディレクティブである必要があります。 @page
および @model
は、Razor 固有のマークアップへの移行の例です。 詳細については、「Razor の構文」を参照してください。
@model ディレクティブ
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
ディレクティブは、Razor ページに渡されるモデルの型を指定します。 前の例では、@model
行によって、Razor ページで PageModel
派生クラスが使用できるようになります。 モデルは、ページの @Html.DisplayNameFor
および @Html.DisplayFor
HTML ヘルパーで使用されます。
次の HTML ヘルパーで使用されるラムダ式を確認します。
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML ヘルパーは、ラムダ式で参照される Title
プロパティを検査し、表示名を判別します。 ラムダ式は評価されるのではなく検査されます。 これは、model
、model.Movie
、または model.Movie[0]
が null
または空である場合、アクセス違反がないことを意味します。 ラムダ式が (@Html.DisplayFor(modelItem => item.Title)
などを使用して) 評価される場合は、モデルのプロパティ値が評価されます。
レイアウト ページ
メニューのリンク ([RazorPagesMovie]、[Home]、[Privacy]) を選択します。 各ページには同じメニューのレイアウトが表示されます。 メニューのレイアウトは、Pages/Shared/_Layout.cshtml
ファイルに実装されています。
Pages/Shared/_Layout.cshtml
ファイルを開いて調べます。
レイアウト テンプレートを使用すると、HTML コンテナーのレイアウトを次のようにすることができます。
- 1 つの場所で指定される。
- サイトの複数のページに適用される。
@RenderBody()
という行を見つけます。 RenderBody
は、ページ固有のビューがすべて表示されるプレースホルダーで、レイアウト ページに "ラップ" されます。 たとえば、 Privacy リンクを選択すると、RenderBody
メソッド内で Pages/Privacy.cshtml
ビューがレンダリングされます。
ViewData とレイアウト
Pages/Movies/Index.cshtml
ファイルの次のマークアップを考えてみます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
上の強調表示されたマークアップは、Razor の C# への移行例です。 {
文字と }
文字で C# コードのブロックを囲みます。
PageModel
基底クラスには ViewData
辞書プロパティが含まれており、これを使用してビューにデータを渡すことができます。 オブジェクトは、"キー値" のパターンを使用して、ViewData
辞書に追加されます。 上のサンプルでは、Title
プロパティが ViewData
辞書に追加されます。
Title
プロパティは、Pages/Shared/_Layout.cshtml
ファイルで使用されます。 次のマークアップは、 _Layout.cshtml
ファイルの最初の数行を示しています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RazorPagesMovie.styles.css" asp-append-version="true" />
@*Markup removed for brevity.*@
行は Razor コメントです。 HTML コメント <!-- -->
とは異なり、Razor コメントはクライアントには送信されません。 詳細については、「MDN Web ドキュメント: HTML の概要」をご覧ください。
レイアウトの更新
RazorPagesMovie ではなく、Movie が表示されるように、
Pages/Shared/_Layout.cshtml
ファイルの<title>
要素を変更します。<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
Pages/Shared/_Layout.cshtml
ファイルで次のアンカー要素を見つけます。<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
上の要素を次のマークアップに置き換えます。
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
上のアンカー要素はタグ ヘルパーです。 この場合は、アンカー タグ ヘルパーです。
asp-page="/Movies/Index"
タグ ヘルパーの属性と値によって、/Movies/Index
Razor ページへのリンクが作成されます。asp-area
属性の値が空なので、リンクではこの区分が使用されていません。 詳細については、区分に関する記事を参照してください。変更内容を保存し、RpMovie リンクを選択してアプリをテストします。 問題がある場合は、GitHub の _Layout.cshtml ファイルを参照してください。
Home、RpMovie、Create、Edit、Delete の各リンクをテストします。 各ページで、ブラウザー タブで表示できるタイトルを設定します。ページをブックマークすると、ブックマークでタイトルが使用されます。
Note
Price
フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマの追加方法については、こちらの GitHub issue 4076 を参照してください。
Layout
プロパティは、Pages/_ViewStart.cshtml
ファイルに設定されます。
@{
Layout = "_Layout";
}
上のマークアップを使用すると、Pages フォルダーのすべての Razor ファイルについて、レイアウト ファイルを Pages/Shared/_Layout.cshtml
に設定します。 詳細については、「Layout」 (レイアウト) を参照してください。
Create ページのモデル
Pages/Movies/Create.cshtml.cs
ページ モデルを確認します。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
メソッドは、ページに必要な状態を初期化します。 [作成] ページには初期化する状態はないため、Page
が返されます。 このチュートリアルの後半では、状態を初期化する OnGet
の例を示します。 Page
メソッドでは、Create.cshtml
ページをレンダリングする PageResult
オブジェクトが作成されます。
Movie
プロパティでは [BindProperty] 属性を使用して、モデル バインドにオプトインします。 [作成] フォームでフォーム値が投稿されると、ASP.NET Core ランタイムが投稿された値を Movie
モデルにバインドします。
OnPostAsync
メソッドは、ページでフォーム データが投稿されたときに実行されます。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
モデル エラーがある場合は、投稿されたフォーム データと共にフォームが再表示されます。 ほとんどのモデル エラーは、フォームが投稿される前にクライアント側でキャッチできます。 モデル エラーの例では、日付に変換できない日付フィールドの値が投稿されています。 クライアント側の検証とモデルの検証については、チュートリアルの後半で説明します。
モデル エラーがない場合は、次のようになります。
- データが保存されます。
- ブラウザーは Index ページにリダイレクトされます。
Razor の作成ページ
Pages/Movies/Create.cshtml
Razor ページ ファイルを調べます。
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<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="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio に、タグ ヘルパーで使用される独特な太字のフォントで次のタグが表示されます。
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
要素はフォーム タグ ヘルパーです。 フォーム タグ ヘルパーには自動的に偽造防止トークンが含まれます。
スキャフォールディング エンジンでは、次のような、(ID を除く) モデルの各フィールドの Razor マークアップが作成されます。
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
検証タグ ヘルパー (<div asp-validation-summary
と <span asp-validation-for
) には検証エラーが表示されます。 検証については、後で詳しく説明します。
ラベル タグ ヘルパー (<label asp-for="Movie.Title" class="control-label"></label>
) は、Title
プロパティのラベル キャプションと [for]
属性を生成します。
入力タグ ヘルパー (<input asp-for="Movie.Title" class="form-control">
) は DataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。
<form method="post">
などのタグ ヘルパーについては、「ASP.NET Core のタグ ヘルパー」を参照してください。
次のステップ
[作成]、[削除]、[詳細]、および [編集] ページ
Pages/Movies/Index.cshtml.cs
ページ モデルを調べます。
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
}
Razor ページは PageModel から派生します。 慣例により、PageModel
派生クラスには、PageNameModel
という名前が付けられます。 たとえば、Index ページには、IndexModel
という名前が付けられます。
コンストラクターは依存性の注入を使用して、RazorPagesMovieContext
をページに追加します。
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework での非同期プログラミングの詳細については、「非同期コード」を参照してください。
ページに対して要求が行われると、OnGetAsync
メソッドは Razor ページにムービーのリストを返します。 Razor ページでは、OnGetAsync
または OnGet
が呼び出され、ページの状態が初期化されます。 この場合、OnGetAsync
でムービーのリストを取得し、表示します。
OnGet
によって void
が返される場合、または OnGetAsync
によって Task
が返される場合は、return ステートメントは使用されません。 たとえば、Privacy ページを調べます。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesMovie.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
戻り値の型が IActionResult または Task<IActionResult>
の場合は、return ステートメントを指定する必要があります。 たとえば、Pages/Movies/Create.cshtml.cs
OnPostAsync
メソッドでは、次の操作を行います。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Pages/Movies/Index.cshtml
Razor ページを調べます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor では、HTML から C# または Razor 固有のマークアップに移行できます。 @
シンボルの後に Razor で予約済みのキーワードが続いている場合は、Razor 固有のマークアップに移行します。それ以外の場合は、C# に移行します。
@page ディレクティブ
@page
Razor ディレクティブを使うと、ファイルが MVC アクションになります。つまり、これで要求を処理できます。 @page
はページ上で最初の Razor ディレクティブである必要があります。 @page
および @model
は、Razor 固有のマークアップへの移行の例です。 詳細については、「Razor の構文」を参照してください。
@model ディレクティブ
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
ディレクティブは、Razor ページに渡されるモデルの型を指定します。 前の例では、@model
行によって、Razor ページで PageModel
派生クラスが使用できるようになります。 モデルは、ページの @Html.DisplayNameFor
および @Html.DisplayFor
HTML ヘルパーで使用されます。
次の HTML ヘルパーで使用されるラムダ式を確認します。
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML ヘルパーは、ラムダ式で参照される Title
プロパティを検査し、表示名を判別します。 ラムダ式は評価されるのではなく検査されます。 これは、model
、model.Movie
、または model.Movie[0]
が null
または空である場合、アクセス違反がないことを意味します。 ラムダ式が (@Html.DisplayFor(modelItem => item.Title)
などを使用して) 評価される場合は、モデルのプロパティ値が評価されます。
レイアウト ページ
メニューのリンク ([RazorPagesMovie]、[Home]、[Privacy]) を選択します。 各ページには同じメニューのレイアウトが表示されます。 メニューのレイアウトは、Pages/Shared/_Layout.cshtml
ファイルに実装されています。
Pages/Shared/_Layout.cshtml
ファイルを開いて調べます。
レイアウト テンプレートを使用すると、HTML コンテナーのレイアウトを次のようにすることができます。
- 1 つの場所で指定される。
- サイトの複数のページに適用される。
@RenderBody()
という行を見つけます。 RenderBody
は、ページ固有のビューがすべて表示されるプレースホルダーで、レイアウト ページに "ラップ" されます。 たとえば、 Privacy リンクを選択すると、RenderBody
メソッド内で Pages/Privacy.cshtml
ビューがレンダリングされます。
ViewData とレイアウト
Pages/Movies/Index.cshtml
ファイルの次のマークアップを考えてみます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
上の強調表示されたマークアップは、Razor の C# への移行例です。 {
文字と }
文字で C# コードのブロックを囲みます。
PageModel
基底クラスには ViewData
辞書プロパティが含まれており、これを使用してビューにデータを渡すことができます。 オブジェクトは、"キー値" のパターンを使用して、ViewData
辞書に追加されます。 上のサンプルでは、Title
プロパティが ViewData
辞書に追加されます。
Title
プロパティは、Pages/Shared/_Layout.cshtml
ファイルで使用されます。 次のマークアップは、 _Layout.cshtml
ファイルの最初の数行を示しています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
@*Markup removed for brevity.*@
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
@*Markup removed for brevity.*@
行は Razor コメントです。 HTML コメント <!-- -->
とは異なり、Razor コメントはクライアントには送信されません。 詳細については、「MDN Web ドキュメント: HTML の概要」をご覧ください。
レイアウトの更新
RazorPagesMovie ではなく、Movie が表示されるように、
Pages/Shared/_Layout.cshtml
ファイルの<title>
要素を変更します。<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
Pages/Shared/_Layout.cshtml
ファイルで次のアンカー要素を見つけます。<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
上の要素を次のマークアップに置き換えます。
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
上のアンカー要素はタグ ヘルパーです。 この場合は、アンカー タグ ヘルパーです。
asp-page="/Movies/Index"
タグ ヘルパーの属性と値によって、/Movies/Index
Razor ページへのリンクが作成されます。asp-area
属性の値が空なので、リンクではこの区分が使用されていません。 詳細については、区分に関する記事を参照してください。変更内容を保存し、RpMovie リンクを選択してアプリをテストします。 問題がある場合は、GitHub の _Layout.cshtml ファイルを参照してください。
Home、RpMovie、Create、Edit、Delete の各リンクをテストします。 各ページで、ブラウザー タブで表示できるタイトルを設定します。ページをブックマークすると、ブックマークでタイトルが使用されます。
Note
Price
フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマの追加方法については、こちらの GitHub issue 4076 を参照してください。
Layout
プロパティは、Pages/_ViewStart.cshtml
ファイルに設定されます。
@{
Layout = "_Layout";
}
上のマークアップを使用すると、Pages フォルダーのすべての Razor ファイルについて、レイアウト ファイルを Pages/Shared/_Layout.cshtml
に設定します。 詳細については、「Layout」 (レイアウト) を参照してください。
Create ページのモデル
Pages/Movies/Create.cshtml.cs
ページ モデルを確認します。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
メソッドは、ページに必要な状態を初期化します。 [作成] ページには初期化する状態はないため、Page
が返されます。 このチュートリアルの後半では、状態を初期化する OnGet
の例を示します。 Page
メソッドでは、Create.cshtml
ページをレンダリングする PageResult
オブジェクトが作成されます。
Movie
プロパティでは [BindProperty] 属性を使用して、モデル バインドにオプトインします。 [作成] フォームでフォーム値が投稿されると、ASP.NET Core ランタイムが投稿された値を Movie
モデルにバインドします。
OnPostAsync
メソッドは、ページでフォーム データが投稿されたときに実行されます。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
モデル エラーがある場合は、投稿されたフォーム データと共にフォームが再表示されます。 ほとんどのモデル エラーは、フォームが投稿される前にクライアント側でキャッチできます。 モデル エラーの例では、日付に変換できない日付フィールドの値が投稿されています。 クライアント側の検証とモデルの検証については、チュートリアルの後半で説明します。
モデル エラーがない場合は、次のようになります。
- データが保存されます。
- ブラウザーは Index ページにリダイレクトされます。
Razor の作成ページ
Pages/Movies/Create.cshtml
Razor ページ ファイルを調べます。
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<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="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio に、タグ ヘルパーで使用される独特な太字のフォントで次のタグが表示されます。
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
要素はフォーム タグ ヘルパーです。 フォーム タグ ヘルパーには自動的に偽造防止トークンが含まれます。
スキャフォールディング エンジンでは、次のような、(ID を除く) モデルの各フィールドの Razor マークアップが作成されます。
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
検証タグ ヘルパー (<div asp-validation-summary
と <span asp-validation-for
) には検証エラーが表示されます。 検証については、後で詳しく説明します。
ラベル タグ ヘルパー (<label asp-for="Movie.Title" class="control-label"></label>
) は、Title
プロパティのラベル キャプションと [for]
属性を生成します。
入力タグ ヘルパー (<input asp-for="Movie.Title" class="form-control">
) は DataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。
<form method="post">
などのタグ ヘルパーについては、「ASP.NET Core のタグ ヘルパー」を参照してください。
次のステップ
[作成]、[削除]、[詳細]、および [編集] ページ
Pages/Movies/Index.cshtml.cs
ページ モデルを調べます。
// Unused usings removed.
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; }
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor ページは PageModel
から派生します。 慣例により、PageModel
派生クラスは <PageName>Model
と呼ばれます。 コンストラクターは依存性の注入を使用して、RazorPagesMovieContext
をページに追加します。
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Entity Framework での非同期プログラミングの詳細については、「非同期コード」を参照してください。
ページに対して要求が行われると、OnGetAsync
メソッドは Razor ページにムービーのリストを返します。 Razor ページでは、OnGetAsync
または OnGet
が呼び出され、ページの状態が初期化されます。 この場合、OnGetAsync
でムービーのリストを取得し、表示します。
OnGet
によって void
が返される場合、または OnGetAsync
によって Task
が返される場合は、return ステートメントは使用されません。 たとえば、Privacy ページは次のようになります。
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
戻り値の型が IActionResult
または Task<IActionResult>
の場合は、return ステートメントを指定する必要があります。 たとえば、Pages/Movies/Create.cshtml.cs
OnPostAsync
メソッドでは、次の操作を行います。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Pages/Movies/Index.cshtml
Razor ページを調べます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor では、HTML から C# または Razor 固有のマークアップに移行できます。 @
シンボルの後に Razor で予約済みのキーワードが続いている場合は、Razor 固有のマークアップに移行します。それ以外の場合は、C# に移行します。
@page ディレクティブ
@page
Razor ディレクティブを使うと、ファイルが MVC アクションになります。つまり、これで要求を処理できます。 @page
はページ上で最初の Razor ディレクティブである必要があります。 @page
および @model
は、Razor 固有のマークアップへの移行の例です。 詳細については、「Razor の構文」を参照してください。
@model ディレクティブ
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model
ディレクティブは、Razor ページに渡されるモデルの型を指定します。 前の例の @model
行は、Razor ページで PageModel
派生クラスを使用できるようにします。 モデルは、ページの @Html.DisplayNameFor
および @Html.DisplayFor
HTML ヘルパーで使用されます。
次の HTML ヘルパーで使用されるラムダ式を確認します。
@Html.DisplayNameFor(model => model.Movie[0].Title)
DisplayNameFor HTML ヘルパーは、ラムダ式で参照される Title
プロパティを検査し、表示名を判別します。 ラムダ式は評価されるのではなく検査されます。 これは、model
、model.Movie
、または model.Movie[0]
が null
または空である場合、アクセス違反がないことを意味します。 ラムダ式が (@Html.DisplayFor(modelItem => item.Title)
などを使用して) 評価される場合は、モデルのプロパティ値が評価されます。
レイアウト ページ
メニューのリンク ([RazorPagesMovie]、[Home]、[Privacy]) を選択します。 各ページには同じメニューのレイアウトが表示されます。 メニューのレイアウトは、Pages/Shared/_Layout.cshtml
ファイルに実装されています。
Pages/Shared/_Layout.cshtml
ファイルを開いて調べます。
レイアウト テンプレートを使用すると、HTML コンテナーのレイアウトを次のようにすることができます。
- 1 つの場所で指定される。
- サイトの複数のページに適用される。
@RenderBody()
という行を見つけます。 RenderBody
は、ページ固有のビューがすべて表示されるプレースホルダーで、レイアウト ページに "ラップ" されます。 たとえば、 Privacy リンクを選択すると、RenderBody
メソッド内で Pages/Privacy.cshtml
ビューがレンダリングされます。
ViewData とレイアウト
Pages/Movies/Index.cshtml
ファイルの次のマークアップを考えてみます。
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
上の強調表示されたマークアップは、Razor の C# への移行例です。 {
文字と }
文字で C# コードのブロックを囲みます。
PageModel
基底クラスには ViewData
辞書プロパティが含まれており、これを使用してビューにデータを渡すことができます。 オブジェクトは、"キー値" のパターンを使用して、ViewData
辞書に追加されます。 上のサンプルでは、Title
プロパティが ViewData
辞書に追加されます。
Title
プロパティは、Pages/Shared/_Layout.cshtml
ファイルで使用されます。 次のマークアップは、 _Layout.cshtml
ファイルの最初の数行を示しています。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
@*Markup removed for brevity.*@
@*Markup removed for brevity.*@
行は Razor コメントです。 HTML コメント <!-- -->
とは異なり、Razor コメントはクライアントには送信されません。 詳細については、「MDN Web ドキュメント: HTML の概要」をご覧ください。
レイアウトの更新
RazorPagesMovie ではなく、Movie が表示されるように、
Pages/Shared/_Layout.cshtml
ファイルの<title>
要素を変更します。<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - Movie</title>
Pages/Shared/_Layout.cshtml
ファイルで次のアンカー要素を見つけます。<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
上の要素を次のマークアップに置き換えます。
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
上のアンカー要素はタグ ヘルパーです。 この場合は、アンカー タグ ヘルパーです。
asp-page="/Movies/Index"
タグ ヘルパーの属性と値によって、/Movies/Index
Razor ページへのリンクが作成されます。asp-area
属性の値が空なので、リンクではこの区分が使用されていません。 詳細については、区分に関する記事を参照してください。変更内容を保存し、RpMovie リンクを選択してアプリをテストします。 問題がある場合は、GitHub の _Layout.cshtml ファイルを参照してください。
Home、RpMovie、Create、Edit、Delete の各リンクをテストします。 各ページで、ブラウザー タブで表示できるタイトルを設定します。ページをブックマークすると、ブックマークでタイトルが使用されます。
Note
Price
フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマの追加方法については、こちらの GitHub issue 4076 を参照してください。
Layout
プロパティは、Pages/_ViewStart.cshtml
ファイルに設定されます。
@{
Layout = "_Layout";
}
上のマークアップを使用すると、Pages フォルダーのすべての Razor ファイルについて、レイアウト ファイルを Pages/Shared/_Layout.cshtml
に設定します。 詳細については、「Layout」 (レイアウト) を参照してください。
Create ページのモデル
Pages/Movies/Create.cshtml.cs
ページ モデルを確認します。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet
メソッドは、ページに必要な状態を初期化します。 [作成] ページには初期化する状態はないため、Page
が返されます。 このチュートリアルの後半では、状態を初期化する OnGet
の例を示します。 Page
メソッドでは、Create.cshtml
ページをレンダリングする PageResult
オブジェクトが作成されます。
Movie
プロパティでは [BindProperty] 属性を使用して、モデル バインドにオプトインします。 [作成] フォームでフォーム値が投稿されると、ASP.NET Core ランタイムが投稿された値を Movie
モデルにバインドします。
OnPostAsync
メソッドは、ページでフォーム データが投稿されたときに実行されます。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
モデル エラーがある場合は、投稿されたフォーム データと共にフォームが再表示されます。 ほとんどのモデル エラーは、フォームが投稿される前にクライアント側でキャッチできます。 モデル エラーの例では、日付に変換できない日付フィールドの値が投稿されています。 クライアント側の検証とモデルの検証については、チュートリアルの後半で説明します。
モデル エラーがない場合は、次のようになります。
- データが保存されます。
- ブラウザーは Index ページにリダイレクトされます。
Razor の作成ページ
Pages/Movies/Create.cshtml
Razor ページ ファイルを調べます。
@page
@model RazorPagesMovie.Pages.Movies.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</h4>
<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="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Visual Studio に、タグ ヘルパーで使用される独特な太字のフォントで次のタグが表示されます。
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
<form method="post">
要素はフォーム タグ ヘルパーです。 フォーム タグ ヘルパーには自動的に偽造防止トークンが含まれます。
スキャフォールディング エンジンでは、次のような、(ID を除く) モデルの各フィールドの Razor マークアップが作成されます。
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
検証タグ ヘルパー (<div asp-validation-summary
と <span asp-validation-for
) には検証エラーが表示されます。 検証については、後で詳しく説明します。
ラベル タグ ヘルパー (<label asp-for="Movie.Title" class="control-label"></label>
) は、Title
プロパティのラベル キャプションと [for]
属性を生成します。
入力タグ ヘルパー (<input asp-for="Movie.Title" class="form-control">
) は DataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。
<form method="post">
などのタグ ヘルパーについては、「ASP.NET Core のタグ ヘルパー」を参照してください。
次のステップ
ASP.NET Core