このブラウザーはサポートされなくなりました。

Microsoft Edge にアップグレードすると、最新の機能、セキュリティ更新プログラム、およびテクニカル サポートを利用できます。

Microsoft Edge をダウンロードする Internet Explorer と Microsoft Edge の詳細情報

[作成]、[削除]、[詳細]、および [編集] ページ

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.cshtmlRazor ページを調べます。

@page
@model RazorPagesMovie.Pages.Movies.IndexModel
    ViewData["Title"] = "Index";
<h1>Index</h1>
    <a asp-page="Create">Create New</a>
<table class="table">
    <thead>
                @Html.DisplayNameFor(model => model.Movie[0].Title)
                @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
                @Html.DisplayNameFor(model => model.Movie[0].Genre)
                @Html.DisplayNameFor(model => model.Movie[0].Price)
            <th></th>
    </thead>
    <tbody>
@foreach (var item in Model.Movie) {
                @Html.DisplayFor(modelItem => item.Title)
                @Html.DisplayFor(modelItem => item.ReleaseDate)
                @Html.DisplayFor(modelItem => item.Genre)
                @Html.DisplayFor(modelItem => item.Price)
                <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>
    </tbody>
</table>

Razor では、HTML から C# または Razor 固有のマークアップに移行できます。 @ シンボルの後に Razor で予約済みのキーワードが続いている場合は、Razor 固有のマークアップに移行します。それ以外の場合は、C# に移行します。

@page ディレクティブ

@pageRazor ディレクティブを使うと、ファイルが MVC アクションになります。つまり、これで要求を処理できます。 @page はページ上で最初の Razor ディレクティブである必要があります。 @page および @model は、Razor 固有のマークアップへの移行の例です。 詳細については、「Razor の構文」を参照してください。

@model ディレクティブ

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@model ディレクティブは、Razor ページに渡されるモデルの型を指定します。 前の例では、@model 行によって、Razor ページで PageModel 派生クラスが使用できるようになります。 モデルは、ページの @Html.DisplayNameFor および @Html.DisplayForHTML ヘルパーで使用されます。

次の HTML ヘルパーで使用されるラムダ式を確認します。

@Html.DisplayNameFor(model => model.Movie[0].Title)

DisplayNameFor HTML ヘルパーは、ラムダ式で参照される Title プロパティを検査し、表示名を判別します。 ラムダ式は評価されるのではなく検査されます。 これは、modelmodel.Movie、または model.Movie[0]null または空である場合、アクセス違反がないことを意味します。 ラムダ式が (@Html.DisplayFor(modelItem => item.Title) などを使用して) 評価される場合は、モデルのプロパティ値が評価されます。

レイアウト ページ

RazorPagesMovieHomePrivacy の各メニュー リンクを選択します。 各ページには同じメニューのレイアウトが表示されます。 メニューのレイアウトは、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">
        <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">
        <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/IndexRazor ページへのリンクが作成されます。 asp-area 属性の値が空なので、リンクではこの区分が使用されていません。 詳細については、区分に関する記事を参照してください。

  • 変更内容を保存し、RpMovie リンクを選択してアプリをテストします。 問題がある場合は、GitHub の _Layout.cshtml ファイルを参照してください。

  • HomeRpMovieCreateEditDelete の各リンクをテストします。 各ページで、ブラウザー タブで表示できるタイトルを設定します。ページをブックマークすると、ブックマークでタイトルが使用されます。

    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.cshtmlRazor ページ ファイルを調べます。

    @page
    @model RazorPagesMovie.Pages.Movies.CreateModel
        ViewData["Title"] = "Create";
    <h1>Create</h1>
    <h4>Movie</h4>
    <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 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 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 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 class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
            </form>
        <a asp-page="Index">Back to List</a>
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    Visual Studio
    Visual Studio Code / Visual Studio for Mac
    
  • <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">
  • <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 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.csOnPostAsync メソッドでは、次の操作を行います。

        public async Task<IActionResult> OnPostAsync()
            if (!ModelState.IsValid)
                return Page();
            _context.Movie.Add(Movie);
            await _context.SaveChangesAsync();
            return RedirectToPage("./Index");
    

    Pages/Movies/Index.cshtmlRazor ページを調べます。

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
        ViewData["Title"] = "Index";
    <h1>Index</h1>
        <a asp-page="Create">Create New</a>
    <table class="table">
        <thead>
                    @Html.DisplayNameFor(model => model.Movie[0].Title)
                    @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
                    @Html.DisplayNameFor(model => model.Movie[0].Genre)
                    @Html.DisplayNameFor(model => model.Movie[0].Price)
                <th></th>
        </thead>
        <tbody>
    @foreach (var item in Model.Movie) {
                    @Html.DisplayFor(modelItem => item.Title)
                    @Html.DisplayFor(modelItem => item.ReleaseDate)
                    @Html.DisplayFor(modelItem => item.Genre)
                    @Html.DisplayFor(modelItem => item.Price)
                    <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>
        </tbody>
    </table>
    

    Razor では、HTML から C# または Razor 固有のマークアップに移行できます。 @ シンボルの後に Razor で予約済みのキーワードが続いている場合は、Razor 固有のマークアップに移行します。それ以外の場合は、C# に移行します。

    @page ディレクティブ

    @pageRazor ディレクティブを使うと、ファイルが MVC アクションになります。つまり、これで要求を処理できます。 @page はページ上で最初の Razor ディレクティブである必要があります。 @page および @model は、Razor 固有のマークアップへの移行の例です。 詳細については、「Razor の構文」を参照してください。

    @model ディレクティブ

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    

    @model ディレクティブは、Razor ページに渡されるモデルの型を指定します。 前の例の @model 行は、Razor ページで PageModel 派生クラスを使用できるようにします。 モデルは、ページの @Html.DisplayNameFor および @Html.DisplayForHTML ヘルパーで使用されます。

    次の HTML ヘルパーで使用されるラムダ式を確認します。

    @Html.DisplayNameFor(model => model.Movie[0].Title)
    

    DisplayNameFor HTML ヘルパーは、ラムダ式で参照される Title プロパティを検査し、表示名を判別します。 ラムダ式は評価されるのではなく検査されます。 これは、modelmodel.Movie、または model.Movie[0]null または空である場合、アクセス違反がないことを意味します。 ラムダ式が (@Html.DisplayFor(modelItem => item.Title) などを使用して) 評価される場合は、モデルのプロパティ値が評価されます。

    レイアウト ページ

    RazorPagesMovieHomePrivacy の各メニュー リンクを選択します。 各ページには同じメニューのレイアウトが表示されます。 メニューのレイアウトは、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>
        <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">
        <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/IndexRazor ページへのリンクが作成されます。 asp-area 属性の値が空なので、リンクではこの区分が使用されていません。 詳細については、区分に関する記事を参照してください。

  • 変更内容を保存し、RpMovie リンクを選択してアプリをテストします。 問題がある場合は、GitHub の _Layout.cshtml ファイルを参照してください。

  • HomeRpMovieCreateEditDelete の各リンクをテストします。 各ページで、ブラウザー タブで表示できるタイトルを設定します。ページをブックマークすると、ブックマークでタイトルが使用されます。

    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.cshtmlRazor ページ ファイルを調べます。

    @page
    @model RazorPagesMovie.Pages.Movies.CreateModel
        ViewData["Title"] = "Create";
    <h1>Create</h1>
    <h4>Movie</h4>
    <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 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 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 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 class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
            </form>
        <a asp-page="Index">Back to List</a>
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    Visual Studio
    Visual Studio Code / Visual Studio for Mac
    
  • <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">
  • <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 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.csOnPostAsync メソッドでは、次の操作を行います。

    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.cshtmlRazor ページを調べます。

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
        ViewData["Title"] = "Index";
    <h1>Index</h1>
        <a asp-page="Create">Create New</a>
    <table class="table">
        <thead>
                    @Html.DisplayNameFor(model => model.Movie[0].Title)
                    @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
                    @Html.DisplayNameFor(model => model.Movie[0].Genre)
                    @Html.DisplayNameFor(model => model.Movie[0].Price)
                <th></th>
        </thead>
        <tbody>
    @foreach (var item in Model.Movie) {
                    @Html.DisplayFor(modelItem => item.Title)
                    @Html.DisplayFor(modelItem => item.ReleaseDate)
                    @Html.DisplayFor(modelItem => item.Genre)
                    @Html.DisplayFor(modelItem => item.Price)
                    <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>
        </tbody>
    </table>
    

    Razor では、HTML から C# または Razor 固有のマークアップに移行できます。 @ シンボルの後に Razor で予約済みのキーワードが続いている場合は、Razor 固有のマークアップに移行します。それ以外の場合は、C# に移行します。

    @page ディレクティブ

    @pageRazor ディレクティブを使うと、ファイルが MVC アクションになります。つまり、これで要求を処理できます。 @page はページ上で最初の Razor ディレクティブである必要があります。 @page および @model は、Razor 固有のマークアップへの移行の例です。 詳細については、「Razor の構文」を参照してください。

    @model ディレクティブ

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    

    @model ディレクティブは、Razor ページに渡されるモデルの型を指定します。 前の例では、@model 行によって、Razor ページで PageModel 派生クラスが使用できるようになります。 モデルは、ページの @Html.DisplayNameFor および @Html.DisplayForHTML ヘルパーで使用されます。

    次の HTML ヘルパーで使用されるラムダ式を確認します。

    @Html.DisplayNameFor(model => model.Movie[0].Title)
    

    DisplayNameFor HTML ヘルパーは、ラムダ式で参照される Title プロパティを検査し、表示名を判別します。 ラムダ式は評価されるのではなく検査されます。 これは、modelmodel.Movie、または model.Movie[0]null または空である場合、アクセス違反がないことを意味します。 ラムダ式が (@Html.DisplayFor(modelItem => item.Title) などを使用して) 評価される場合は、モデルのプロパティ値が評価されます。

    レイアウト ページ

    RazorPagesMovieHomePrivacy の各メニュー リンクを選択します。 各ページには同じメニューのレイアウトが表示されます。 メニューのレイアウトは、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">
        <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">
        <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/IndexRazor ページへのリンクが作成されます。 asp-area 属性の値が空なので、リンクではこの区分が使用されていません。 詳細については、区分に関する記事を参照してください。

  • 変更内容を保存し、RpMovie リンクを選択してアプリをテストします。 問題がある場合は、GitHub の _Layout.cshtml ファイルを参照してください。

  • HomeRpMovieCreateEditDelete の各リンクをテストします。 各ページで、ブラウザー タブで表示できるタイトルを設定します。ページをブックマークすると、ブックマークでタイトルが使用されます。

    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.cshtmlRazor ページ ファイルを調べます。

    @page
    @model RazorPagesMovie.Pages.Movies.CreateModel
        ViewData["Title"] = "Create";
    <h1>Create</h1>
    <h4>Movie</h4>
    <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 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 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 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 class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
            </form>
        <a asp-page="Index">Back to List</a>
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    Visual Studio
    Visual Studio Code / Visual Studio for Mac
    
  • <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">
  • <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 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 のタグ ヘルパー」を参照してください。

    その他の技術情報

    前へ:モデルの追加次へ:データベースの操作

  •