Delen via


Deel 3, geveerde Razor pagina's in ASP.NET Core

Opmerking

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikel voor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.

Belangrijk

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikel voor de huidige release.

Door Rick Anderson

In deze zelfstudie worden de pagina's die door scaffolding zijn gemaakt in de Razor onderzocht.

De pagina's Maken, Verwijderen, Details en Bewerken

Bekijk het Pages/Movies/Index.cshtml.cs paginamodel:

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 Pagina's zijn afgeleid van PageModel. Volgens conventie heeft de afgeleide klasse de PageModel naam PageNameModel. De indexpagina heeft bijvoorbeeld de naam IndexModel.

De constructor gebruikt afhankelijkheidsinjectie om RazorPagesMovieContext aan de pagina toe te voegen.

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

Zie Asynchrone code voor meer informatie over asynchrone programmering met Entity Framework.

Wanneer er een GET aanvraag voor de pagina wordt ingediend, retourneert de OnGetAsync methode een lijst met films naar de Razor pagina. Op een Razor pagina OnGetAsync of OnGet wordt aangeroepen om de status van de pagina te initialiseren. In dit geval haalt OnGetAsync een lijst met films op en geeft deze weer.

Wanneer OnGetvoid teruggeeft of OnGetAsyncTask teruggeeft, wordt er geen return-statement gebruikt. Bekijk bijvoorbeeld de Privacy pagina:

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()
        {
        }
    }

}

Wanneer het retourtype IActionResult of Task<IActionResult> is, moet er een returninstructie worden opgegeven. Bijvoorbeeld de Pages/Movies/Create.cshtml.cs OnPostAsync methode:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movie.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Bekijk de Pages/Movies/Index.cshtmlRazor pagina:

@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 kan worden overgestapt van HTML naar C# of naar Razor-specifieke markeringen. Wanneer een @ symbool wordt gevolgd door een Razor gereserveerd trefwoord, wordt het overgegaan naar Razor-specifieke markeringen, anders wordt het overgegaan naar C#.

De richtlijn @page

De @pageRazor instructie maakt het bestand een MVC-actie, wat betekent dat het aanvragen kan verwerken. @page moet de eerste Razor instructie op een pagina zijn. @page en @model zijn voorbeelden van overgang naar Razor-specifieke markeringen. Zie Razor de syntaxis voor meer informatie.

De richtlijn @model

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

De @model richtlijn geeft het type model aan dat aan de Razor pagina wordt doorgegeven. In het voorgaande voorbeeld maakt de @model regel de PageModel afgeleide klasse beschikbaar voor de Razor pagina. Het model wordt gebruikt in de @Html.DisplayNameFor@Html.DisplayForHTML-Helpers op de pagina.

Bekijk de lambda-expressie die wordt gebruikt in de volgende HTML-helper:

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

De DisplayNameFor HTML Helper inspecteert de Title eigenschap waarnaar wordt verwezen in de lambda-expressie om de weergavenaam te bepalen. De lambda-expressie wordt geïnspecteerd in plaats van geëvalueerd. Dit betekent dat er geen toegangsschending is wanneer model, model.Movie, of model.Movie[0]null of leeg is. Wanneer de lambda-expressie wordt geëvalueerd, bijvoorbeeld met @Html.DisplayFor(modelItem => item.Title), worden de eigenschapswaarden van het model geëvalueerd.

De indelingspagina

Selecteer de menukoppelingen RazorPagesMovie, Home, en Privacy. Elke pagina bevat dezelfde menu-indeling. De menu-indeling wordt geïmplementeerd in het Pages/Shared/_Layout.cshtml bestand.

Open het Pages/Shared/_Layout.cshtml bestand en bekijk het.

Met indelingssjablonen kan de HTML-containerindeling het volgende zijn:

  • Gespecificeerd op één plaats.
  • Toegepast op meerdere pagina's op de site.

Zoek de @RenderBody() lijn. RenderBody is een tijdelijke aanduiding waarin alle paginaspecifieke weergaven worden weergegeven, verpakt op de indelingspagina. Selecteer bijvoorbeeld de Privacy koppeling en de Pages/Privacy.cshtml weergave wordt weergegeven in de RenderBody methode.

Weergavegegevens en layout

Houd rekening met de volgende markeringen uit het Pages/Movies/Index.cshtml bestand:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

De vooraf gemarkeerde markeringen zijn een voorbeeld van Razor dat overgaat naar C#. De { tekens en } bevatten een blok C#-code.

De PageModel basisklasse bevat een ViewData woordenlijsteigenschap die kan worden gebruikt om gegevens door te geven aan een weergave. Objecten worden aan de ViewData woordenlijst toegevoegd met behulp van een sleutelwaardepatroon . In het voorgaande voorbeeld wordt de Title eigenschap toegevoegd aan de ViewData woordenlijst.

De Title eigenschap wordt gebruikt in het Pages/Shared/_Layout.cshtml bestand. In de volgende markeringen worden de eerste regels van het _Layout.cshtml bestand weergegeven.

<!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" />

De indeling bijwerken

  1. Wijzig het <title> element in het Pages/Shared/_Layout.cshtml bestand om Film weer te geven in plaats van RazorPagesMovie.

    <!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>
    
  2. Zoek het volgende ankerelement in het Pages/Shared/_Layout.cshtml bestand.

    <a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
    
  3. Vervang het voorgaande element door de volgende markeringen:

    <a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
    

    Het voorgaande ankerelement is een Tag Helper. In dit geval is het de Anchor Tag Helper. Het asp-page="/Movies/Index" Tag Helper-kenmerk en -waarde maken een koppeling naar de /Movies/IndexRazor pagina. De asp-area kenmerkwaarde is leeg, dus het gebied wordt niet gebruikt in de koppeling. Zie Gebieden voor meer informatie.

  4. Sla de wijzigingen op en test de app door de RpMovie-koppeling te selecteren. Zie het bestand _Layout.cshtml in GitHub als u problemen ondervindt.

  5. Test de koppelingen Home, RpMovie, Maken, Bewerken en Verwijderen. Op elke pagina wordt de titel ingesteld die je in het tabblad van de browser kunt zien. Wanneer je een pagina als bladwijzer opslaat, wordt de titel gebruikt voor de bladwijzer.

Opmerking

Mogelijk kunt u geen decimale komma's invoeren in het veld Price. Als u jQuery-validatie wilt ondersteunen voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en niet-US-English datumnotaties, moet u stappen ondernemen om de app te globaliseren. Zie dit GitHub-probleem 4076 voor instructies over het toevoegen van decimale komma's.

De Layout eigenschap is ingesteld in het Pages/_ViewStart.cshtml bestand:

@{
    Layout = "_Layout";
}

Met de voorgaande opmaak wordt het indelingsbestand ingesteld Pages/Shared/_Layout.cshtml op alle Razor bestanden onder de map Pagina's . Zie Indeling voor meer informatie.

Het paginamodel maken

Bekijk het Pages/Movies/Create.cshtml.cs paginamodel:

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");
        }
    }
}

De OnGet methode initialiseert alle statussen die nodig zijn voor de pagina. De Maakpagina heeft geen status die hoeft te worden geïnitialiseerd, dus Page wordt geretourneerd. Verderop in de zelfstudie wordt een voorbeeld van OnGet de initialisatiestatus weergegeven. Met de Page methode wordt een PageResult object gemaakt waarmee de Create.cshtml pagina wordt weergegeven.

De Movie eigenschap maakt gebruik van het kenmerk [BindProperty] om deel te nemen aan modelbinding. Wanneer het formulier maken de formulierwaarden plaatst, verbindt de ASP.NET Core-runtime de geplaatste waarden aan het Movie model.

De OnPostAsync methode wordt uitgevoerd wanneer de formuliergegevens van de pagina worden geplaatst:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movie.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Als er modelfouten zijn, wordt het formulier opnieuw weergegeven, samen met eventuele formuliergegevens die zijn gepost. De meeste modelfouten kunnen aan de clientzijde worden opgevangen voordat het formulier wordt geplaatst. Een voorbeeld van een modelfout is het posten van een waarde voor het datumveld dat niet kan worden geconverteerd naar een datum. Validatie aan de clientzijde en modelvalidatie worden verderop in de zelfstudie besproken.

Als er geen modelfouten zijn:

  • De gegevens worden opgeslagen.
  • De browser wordt omgeleid naar de pagina Index.

De pagina Maken Razor

Bekijk het Pages/Movies/Create.cshtmlRazor paginabestand:

@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 geeft de volgende tags weer in een opvallend vet lettertype dat wordt gebruikt voor Tag Helpers:

  • <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>

VS-weergave van de pagina Create.cshtml

Het <form method="post"> element is een Helper voor formuliertags. De Helper voor formuliertags bevat automatisch een antiforgery-token.

De scaffolding-engine creëert Razor markup voor elk veld in het model, behalve de ID, zoals de volgende:

<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>

In de Helpers voor validatietags (<div asp-validation-summary en <span asp-validation-for) worden validatiefouten weergegeven. De validatie wordt verderop in deze reeks uitgebreider besproken.

De Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genereert het labelbijschrift en [for] kenmerk voor de Title eigenschap.

De Helper voor invoertags (<input asp-for="Movie.Title" class="form-control">) maakt gebruik van de kenmerken DataAnnotations en produceert HTML-kenmerken die nodig zijn voor jQuery-validatie aan de clientzijde.

Zie <form method="post"> voor meer informatie over Tag Helpers zoals.

Volgende stappen

De pagina's Maken, Verwijderen, Details en Bewerken

Bekijk het Pages/Movies/Index.cshtml.cs paginamodel:

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 Pagina's zijn afgeleid van PageModel. Volgens conventie heeft de afgeleide klasse de PageModel naam PageNameModel. De indexpagina heeft bijvoorbeeld de naam IndexModel.

De constructor gebruikt afhankelijkheidsinjectie om RazorPagesMovieContext aan de pagina toe te voegen.

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

Zie Asynchrone code voor meer informatie over asynchrone programmering met Entity Framework.

Wanneer er een GET aanvraag voor de pagina wordt ingediend, retourneert de OnGetAsync methode een lijst met films naar de Razor pagina. Op een Razor pagina OnGetAsync of OnGet wordt aangeroepen om de status van de pagina te initialiseren. In dit geval haalt OnGetAsync een lijst met films op en geeft deze weer.

Wanneer OnGetvoid teruggeeft of OnGetAsyncTask teruggeeft, wordt er geen return-statement gebruikt. Bekijk bijvoorbeeld de Privacy pagina:

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()
        {
        }
    }
}

Wanneer het retourtype IActionResult of Task<IActionResult> is, moet er een returninstructie worden opgegeven. Bijvoorbeeld de Pages/Movies/Create.cshtml.cs OnPostAsync methode:

public async Task<IActionResult> OnPostAsync()
{
  if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movie.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Bekijk de Pages/Movies/Index.cshtmlRazor pagina:

@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 kan worden overgestapt van HTML naar C# of naar Razor-specifieke markeringen. Wanneer een @ symbool wordt gevolgd door een Razor gereserveerd trefwoord, wordt het overgegaan naar Razor-specifieke markeringen, anders wordt het overgegaan naar C#.

De richtlijn @page

De @pageRazor instructie maakt het bestand een MVC-actie, wat betekent dat het aanvragen kan verwerken. @page moet de eerste Razor instructie op een pagina zijn. @page en @model zijn voorbeelden van overgang naar Razor-specifieke markeringen. Zie Razor de syntaxis voor meer informatie.

De richtlijn @model

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

De @model richtlijn geeft het type model aan dat aan de Razor pagina wordt doorgegeven. In het voorgaande voorbeeld maakt de @model regel de PageModel afgeleide klasse beschikbaar voor de Razor pagina. Het model wordt gebruikt in de @Html.DisplayNameFor@Html.DisplayForHTML-Helpers op de pagina.

Bekijk de lambda-expressie die wordt gebruikt in de volgende HTML-helper:

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

De DisplayNameFor HTML Helper inspecteert de Title eigenschap waarnaar wordt verwezen in de lambda-expressie om de weergavenaam te bepalen. De lambda-expressie wordt geïnspecteerd in plaats van geëvalueerd. Dit betekent dat er geen toegangsschending is wanneer model, model.Movie, of model.Movie[0]null of leeg is. Wanneer de lambda-expressie wordt geëvalueerd, bijvoorbeeld met @Html.DisplayFor(modelItem => item.Title), worden de eigenschapswaarden van het model geëvalueerd.

De indelingspagina

Selecteer de menukoppelingen RazorPagesMovie, Home, en Privacy. Elke pagina bevat dezelfde menu-indeling. De menu-indeling wordt geïmplementeerd in het Pages/Shared/_Layout.cshtml bestand.

Open het Pages/Shared/_Layout.cshtml bestand en bekijk het.

Met indelingssjablonen kan de HTML-containerindeling het volgende zijn:

  • Gespecificeerd op één plaats.
  • Toegepast op meerdere pagina's op de site.

Zoek de @RenderBody() lijn. RenderBody is een tijdelijke aanduiding waarin alle paginaspecifieke weergaven worden weergegeven, verpakt op de indelingspagina. Selecteer bijvoorbeeld de Privacy koppeling en de Pages/Privacy.cshtml weergave wordt weergegeven in de RenderBody methode.

Weergavegegevens en layout

Houd rekening met de volgende markeringen uit het Pages/Movies/Index.cshtml bestand:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

De vooraf gemarkeerde markeringen zijn een voorbeeld van Razor dat overgaat naar C#. De { tekens en } bevatten een blok C#-code.

De PageModel basisklasse bevat een ViewData woordenlijsteigenschap die kan worden gebruikt om gegevens door te geven aan een weergave. Objecten worden aan de ViewData woordenlijst toegevoegd met behulp van een sleutelwaardepatroon . In het voorgaande voorbeeld wordt de Title eigenschap toegevoegd aan de ViewData woordenlijst.

De Title eigenschap wordt gebruikt in het Pages/Shared/_Layout.cshtml bestand. In de volgende markeringen worden de eerste regels van het _Layout.cshtml bestand weergegeven.

<!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" />

De indeling bijwerken

  1. Wijzig het <title> element in het Pages/Shared/_Layout.cshtml bestand om Film weer te geven in plaats van RazorPagesMovie.

    <!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>
    
  2. Zoek het volgende ankerelement in het Pages/Shared/_Layout.cshtml bestand.

    <a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
    
  3. Vervang het voorgaande element door de volgende markeringen:

    <a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
    

    Het voorgaande ankerelement is een Tag Helper. In dit geval is het de Anchor Tag Helper. Het asp-page="/Movies/Index" Tag Helper-kenmerk en -waarde maken een koppeling naar de /Movies/IndexRazor pagina. De asp-area kenmerkwaarde is leeg, dus het gebied wordt niet gebruikt in de koppeling. Zie Gebieden voor meer informatie.

  4. Sla de wijzigingen op en test de app door de RpMovie-koppeling te selecteren. Zie het bestand _Layout.cshtml in GitHub als u problemen ondervindt.

  5. Test de koppelingen Home, RpMovie, Maken, Bewerken en Verwijderen. Op elke pagina wordt de titel ingesteld die je in het tabblad van de browser kunt zien. Wanneer je een pagina als bladwijzer opslaat, wordt de titel gebruikt voor de bladwijzer.

Opmerking

Mogelijk kunt u geen decimale komma's invoeren in het veld Price. Als u jQuery-validatie wilt ondersteunen voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en niet-US-English datumnotaties, moet u stappen ondernemen om de app te globaliseren. Zie dit GitHub-probleem 4076 voor instructies over het toevoegen van decimale komma's.

De Layout eigenschap is ingesteld in het Pages/_ViewStart.cshtml bestand:

@{
    Layout = "_Layout";
}

Met de voorgaande opmaak wordt het indelingsbestand ingesteld Pages/Shared/_Layout.cshtml op alle Razor bestanden onder de map Pagina's . Zie Indeling voor meer informatie.

Het paginamodel maken

Bekijk het Pages/Movies/Create.cshtml.cs paginamodel:

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");
        }
    }
}

De OnGet methode initialiseert alle statussen die nodig zijn voor de pagina. De Maakpagina heeft geen status die hoeft te worden geïnitialiseerd, dus Page wordt geretourneerd. Verderop in de zelfstudie wordt een voorbeeld van OnGet de initialisatiestatus weergegeven. Met de Page methode wordt een PageResult object gemaakt waarmee de Create.cshtml pagina wordt weergegeven.

De Movie eigenschap maakt gebruik van het kenmerk [BindProperty] om deel te nemen aan modelbinding. Wanneer het formulier maken de formulierwaarden plaatst, verbindt de ASP.NET Core-runtime de geplaatste waarden aan het Movie model.

De OnPostAsync methode wordt uitgevoerd wanneer de formuliergegevens van de pagina worden geplaatst:

public async Task<IActionResult> OnPostAsync()
{
  if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movie.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Als er modelfouten zijn, wordt het formulier opnieuw weergegeven, samen met eventuele formuliergegevens die zijn gepost. De meeste modelfouten kunnen aan de clientzijde worden opgevangen voordat het formulier wordt geplaatst. Een voorbeeld van een modelfout is het posten van een waarde voor het datumveld dat niet kan worden geconverteerd naar een datum. Validatie aan de clientzijde en modelvalidatie worden verderop in de zelfstudie besproken.

Als er geen modelfouten zijn:

  • De gegevens worden opgeslagen.
  • De browser wordt omgeleid naar de pagina Index.

De pagina Maken Razor

Bekijk het Pages/Movies/Create.cshtmlRazor paginabestand:

@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 geeft de volgende tags weer in een opvallend vet lettertype dat wordt gebruikt voor Tag Helpers:

  • <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>

VS17-weergave van de pagina Create.cshtml

Het <form method="post"> element is een Helper voor formuliertags. De Helper voor formuliertags bevat automatisch een antiforgery-token.

De scaffolding-engine creëert Razor markup voor elk veld in het model, behalve de ID, zoals de volgende:

<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>

In de Helpers voor validatietags (<div asp-validation-summary en <span asp-validation-for) worden validatiefouten weergegeven. De validatie wordt verderop in deze reeks uitgebreider besproken.

De Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genereert het labelbijschrift en [for] kenmerk voor de Title eigenschap.

De Helper voor invoertags (<input asp-for="Movie.Title" class="form-control">) maakt gebruik van de kenmerken DataAnnotations en produceert HTML-kenmerken die nodig zijn voor jQuery-validatie aan de clientzijde.

Zie <form method="post"> voor meer informatie over Tag Helpers zoals.

Volgende stappen

De pagina's Maken, Verwijderen, Details en Bewerken

Bekijk het Pages/Movies/Index.cshtml.cs paginamodel:

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 Pagina's zijn afgeleid van PageModel. Volgens conventie heeft de afgeleide klasse de PageModel naam PageNameModel. De indexpagina heeft bijvoorbeeld de naam IndexModel.

De constructor gebruikt afhankelijkheidsinjectie om RazorPagesMovieContext aan de pagina toe te voegen.

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

Zie Asynchrone code voor meer informatie over asynchrone programmering met Entity Framework.

Wanneer er een GET aanvraag voor de pagina wordt ingediend, retourneert de OnGetAsync methode een lijst met films naar de Razor pagina. Op een Razor pagina OnGetAsync of OnGet wordt aangeroepen om de status van de pagina te initialiseren. In dit geval haalt OnGetAsync een lijst met films op en geeft deze weer.

Wanneer OnGetvoid teruggeeft of OnGetAsyncTask teruggeeft, wordt er geen return-statement gebruikt. Bekijk bijvoorbeeld de Privacy pagina:

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()
        {
        }
    }
}

Wanneer het retourtype IActionResult of Task<IActionResult> is, moet er een returninstructie worden opgegeven. Bijvoorbeeld de Pages/Movies/Create.cshtml.cs OnPostAsync methode:

public async Task<IActionResult> OnPostAsync()
{
  if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movie.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Bekijk de Pages/Movies/Index.cshtmlRazor pagina:

@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 kan worden overgestapt van HTML naar C# of naar Razor-specifieke markeringen. Wanneer een @ symbool wordt gevolgd door een Razor gereserveerd trefwoord, wordt het overgegaan naar Razor-specifieke markeringen, anders wordt het overgegaan naar C#.

De richtlijn @page

De @pageRazor instructie maakt het bestand een MVC-actie, wat betekent dat het aanvragen kan verwerken. @page moet de eerste Razor instructie op een pagina zijn. @page en @model zijn voorbeelden van overgang naar Razor-specifieke markeringen. Zie Razor de syntaxis voor meer informatie.

De richtlijn @model

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

De @model richtlijn geeft het type model aan dat aan de Razor pagina wordt doorgegeven. In het voorgaande voorbeeld maakt de @model regel de PageModel afgeleide klasse beschikbaar voor de Razor pagina. Het model wordt gebruikt in de @Html.DisplayNameFor@Html.DisplayForHTML-Helpers op de pagina.

Bekijk de lambda-expressie die wordt gebruikt in de volgende HTML-helper:

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

De DisplayNameFor HTML Helper inspecteert de Title eigenschap waarnaar wordt verwezen in de lambda-expressie om de weergavenaam te bepalen. De lambda-expressie wordt geïnspecteerd in plaats van geëvalueerd. Dit betekent dat er geen toegangsschending is wanneer model, model.Movie, of model.Movie[0]null of leeg is. Wanneer de lambda-expressie wordt geëvalueerd, bijvoorbeeld met @Html.DisplayFor(modelItem => item.Title), worden de eigenschapswaarden van het model geëvalueerd.

De indelingspagina

Selecteer de menukoppelingen RazorPagesMovie, Home, en Privacy. Elke pagina bevat dezelfde menu-indeling. De menu-indeling wordt geïmplementeerd in het Pages/Shared/_Layout.cshtml bestand.

Open het Pages/Shared/_Layout.cshtml bestand en bekijk het.

Met indelingssjablonen kan de HTML-containerindeling het volgende zijn:

  • Gespecificeerd op één plaats.
  • Toegepast op meerdere pagina's op de site.

Zoek de @RenderBody() lijn. RenderBody is een tijdelijke aanduiding waarin alle paginaspecifieke weergaven worden weergegeven, verpakt op de indelingspagina. Selecteer bijvoorbeeld de Privacy koppeling en de Pages/Privacy.cshtml weergave wordt weergegeven in de RenderBody methode.

Weergavegegevens en layout

Houd rekening met de volgende markeringen uit het Pages/Movies/Index.cshtml bestand:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

De vooraf gemarkeerde markeringen zijn een voorbeeld van Razor dat overgaat naar C#. De { tekens en } bevatten een blok C#-code.

De PageModel basisklasse bevat een ViewData woordenlijsteigenschap die kan worden gebruikt om gegevens door te geven aan een weergave. Objecten worden aan de ViewData woordenlijst toegevoegd met behulp van een sleutelwaardepatroon . In het voorgaande voorbeeld wordt de Title eigenschap toegevoegd aan de ViewData woordenlijst.

De Title eigenschap wordt gebruikt in het Pages/Shared/_Layout.cshtml bestand. In de volgende markeringen worden de eerste regels van het _Layout.cshtml bestand weergegeven.

<!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" />

De regel @*Markup removed for brevity.*@ is een Razor opmerking. In tegenstelling tot HTML-opmerkingen <!-- -->worden Razor opmerkingen niet naar de client verzonden. Zie MDN-webdocumenten: Aan de slag met HTML voor meer informatie.

De indeling bijwerken

  1. Wijzig het <title> element in het Pages/Shared/_Layout.cshtml bestand om Film weer te geven in plaats van RazorPagesMovie.

    <!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>
    
  2. Zoek het volgende ankerelement in het Pages/Shared/_Layout.cshtml bestand.

    <a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
    
  3. Vervang het voorgaande element door de volgende markeringen:

    <a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
    

    Het voorgaande ankerelement is een Tag Helper. In dit geval is het de Anchor Tag Helper. Het asp-page="/Movies/Index" Tag Helper-kenmerk en -waarde maken een koppeling naar de /Movies/IndexRazor pagina. De asp-area kenmerkwaarde is leeg, dus het gebied wordt niet gebruikt in de koppeling. Zie Gebieden voor meer informatie.

  4. Sla de wijzigingen op en test de app door de RpMovie-koppeling te selecteren. Zie het bestand _Layout.cshtml in GitHub als u problemen ondervindt.

  5. Test de koppelingen Home, RpMovie, Maken, Bewerken en Verwijderen. Op elke pagina wordt de titel ingesteld die je in het tabblad van de browser kunt zien. Wanneer je een pagina als bladwijzer opslaat, wordt de titel gebruikt voor de bladwijzer.

Opmerking

Mogelijk kunt u geen decimale komma's invoeren in het veld Price. Als u jQuery-validatie wilt ondersteunen voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en niet-US-English datumnotaties, moet u stappen ondernemen om de app te globaliseren. Zie dit GitHub-probleem 4076 voor instructies over het toevoegen van decimale komma's.

De Layout eigenschap is ingesteld in het Pages/_ViewStart.cshtml bestand:

@{
    Layout = "_Layout";
}

Met de voorgaande opmaak wordt het indelingsbestand ingesteld Pages/Shared/_Layout.cshtml op alle Razor bestanden onder de map Pagina's . Zie Indeling voor meer informatie.

Het paginamodel maken

Bekijk het Pages/Movies/Create.cshtml.cs paginamodel:

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");
        }
    }
}

De OnGet methode initialiseert alle statussen die nodig zijn voor de pagina. De Maakpagina heeft geen status die hoeft te worden geïnitialiseerd, dus Page wordt geretourneerd. Verderop in de zelfstudie wordt een voorbeeld van OnGet de initialisatiestatus weergegeven. Met de Page methode wordt een PageResult object gemaakt waarmee de Create.cshtml pagina wordt weergegeven.

De Movie eigenschap maakt gebruik van het kenmerk [BindProperty] om deel te nemen aan modelbinding. Wanneer het formulier maken de formulierwaarden plaatst, verbindt de ASP.NET Core-runtime de geplaatste waarden aan het Movie model.

De OnPostAsync methode wordt uitgevoerd wanneer de formuliergegevens van de pagina worden geplaatst:

public async Task<IActionResult> OnPostAsync()
{
  if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movie.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Als er modelfouten zijn, wordt het formulier opnieuw weergegeven, samen met eventuele formuliergegevens die zijn gepost. De meeste modelfouten kunnen aan de clientzijde worden opgevangen voordat het formulier wordt geplaatst. Een voorbeeld van een modelfout is het posten van een waarde voor het datumveld dat niet kan worden geconverteerd naar een datum. Validatie aan de clientzijde en modelvalidatie worden verderop in de zelfstudie besproken.

Als er geen modelfouten zijn:

  • De gegevens worden opgeslagen.
  • De browser wordt omgeleid naar de pagina Index.

De pagina Maken Razor

Bekijk het Pages/Movies/Create.cshtmlRazor paginabestand:

@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 geeft de volgende tags weer in een opvallend vet lettertype dat wordt gebruikt voor Tag Helpers:

  • <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>

VS17-weergave van de pagina Create.cshtml

Het <form method="post"> element is een Helper voor formuliertags. De Helper voor formuliertags bevat automatisch een antiforgery-token.

De scaffolding-engine creëert Razor markup voor elk veld in het model, behalve de ID, zoals de volgende:

<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>

In de Helpers voor validatietags (<div asp-validation-summary en <span asp-validation-for) worden validatiefouten weergegeven. De validatie wordt verderop in deze reeks uitgebreider besproken.

De Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genereert het labelbijschrift en [for] kenmerk voor de Title eigenschap.

De Helper voor invoertags (<input asp-for="Movie.Title" class="form-control">) maakt gebruik van de kenmerken DataAnnotations en produceert HTML-kenmerken die nodig zijn voor jQuery-validatie aan de clientzijde.

Zie <form method="post"> voor meer informatie over Tag Helpers zoals.

Volgende stappen

De pagina's Maken, Verwijderen, Details en Bewerken

Bekijk het Pages/Movies/Index.cshtml.cs paginamodel:

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 Pagina's zijn afgeleid van PageModel. Volgens conventie heeft de afgeleide klasse de PageModel naam PageNameModel. De indexpagina heeft bijvoorbeeld de naam IndexModel.

De constructor gebruikt afhankelijkheidsinjectie om RazorPagesMovieContext aan de pagina toe te voegen.

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

Zie Asynchrone code voor meer informatie over asynchrone programmering met Entity Framework.

Wanneer er een aanvraag voor de pagina wordt ingediend, retourneert de OnGetAsync methode een lijst met films naar de Razor pagina. Op een Razor pagina OnGetAsync of OnGet wordt aangeroepen om de status van de pagina te initialiseren. In dit geval haalt OnGetAsync een lijst met films op en geeft deze weer.

Wanneer OnGetvoid teruggeeft of OnGetAsyncTask teruggeeft, wordt er geen return-statement gebruikt. Bekijk bijvoorbeeld de Privacy pagina:

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()
        {
        }
    }
}

Wanneer het retourtype IActionResult of Task<IActionResult> is, moet er een returninstructie worden opgegeven. Bijvoorbeeld de Pages/Movies/Create.cshtml.csOnPostAsync methode:

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");
}

Bekijk de Pages/Movies/Index.cshtmlRazor pagina:

@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 kan worden overgestapt van HTML naar C# of naar Razor-specifieke markeringen. Wanneer een @ symbool wordt gevolgd door een Razor gereserveerd trefwoord, wordt het overgegaan naar Razor-specifieke markeringen, anders wordt het overgegaan naar C#.

De richtlijn @page

De @pageRazor instructie maakt het bestand een MVC-actie, wat betekent dat het aanvragen kan verwerken. @page moet de eerste Razor instructie op een pagina zijn. @page en @model zijn voorbeelden van overgang naar Razor-specifieke markeringen. Zie Razor de syntaxis voor meer informatie.

De richtlijn @model

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

De @model richtlijn geeft het type model aan dat aan de Razor pagina wordt doorgegeven. In het voorgaande voorbeeld maakt de @model regel de PageModel afgeleide klasse beschikbaar voor de Razor pagina. Het model wordt gebruikt in de @Html.DisplayNameFor@Html.DisplayForHTML-Helpers op de pagina.

Bekijk de lambda-expressie die wordt gebruikt in de volgende HTML-helper:

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

De DisplayNameFor HTML Helper inspecteert de Title eigenschap waarnaar wordt verwezen in de lambda-expressie om de weergavenaam te bepalen. De lambda-expressie wordt geïnspecteerd in plaats van geëvalueerd. Dit betekent dat er geen toegangsschending is wanneer model, model.Movie, of model.Movie[0]null of leeg is. Wanneer de lambda-expressie wordt geëvalueerd, bijvoorbeeld met @Html.DisplayFor(modelItem => item.Title), worden de eigenschapswaarden van het model geëvalueerd.

De indelingspagina

Selecteer de menukoppelingen RazorPagesMovie, Home, en Privacy. Elke pagina bevat dezelfde menu-indeling. De menu-indeling wordt geïmplementeerd in het Pages/Shared/_Layout.cshtml bestand.

Open het Pages/Shared/_Layout.cshtml bestand en bekijk het.

Met indelingssjablonen kan de HTML-containerindeling het volgende zijn:

  • Gespecificeerd op één plaats.
  • Toegepast op meerdere pagina's op de site.

Zoek de @RenderBody() lijn. RenderBody is een tijdelijke aanduiding waarin alle paginaspecifieke weergaven worden weergegeven, verpakt op de indelingspagina. Selecteer bijvoorbeeld de Privacy koppeling en de Pages/Privacy.cshtml weergave wordt weergegeven in de RenderBody methode.

Weergavegegevens en layout

Houd rekening met de volgende markeringen uit het Pages/Movies/Index.cshtml bestand:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

De vooraf gemarkeerde markeringen zijn een voorbeeld van Razor dat overgaat naar C#. De { tekens en } bevatten een blok C#-code.

De PageModel basisklasse bevat een ViewData woordenlijsteigenschap die kan worden gebruikt om gegevens door te geven aan een weergave. Objecten worden aan de ViewData woordenlijst toegevoegd met behulp van een sleutelwaardepatroon . In het voorgaande voorbeeld wordt de Title eigenschap toegevoegd aan de ViewData woordenlijst.

De Title eigenschap wordt gebruikt in het Pages/Shared/_Layout.cshtml bestand. In de volgende markeringen worden de eerste regels van het _Layout.cshtml bestand weergegeven.

<!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" />

De regel @*Markup removed for brevity.*@ is een Razor opmerking. In tegenstelling tot HTML-opmerkingen <!-- -->worden Razor opmerkingen niet naar de client verzonden. Zie MDN-webdocumenten: Aan de slag met HTML voor meer informatie.

De indeling bijwerken

  1. Wijzig het <title> element in het Pages/Shared/_Layout.cshtml bestand om Film weer te geven in plaats van RazorPagesMovie.

    <!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>
    
  2. Zoek het volgende ankerelement in het Pages/Shared/_Layout.cshtml bestand.

    <a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
    
  3. Vervang het voorgaande element door de volgende markeringen:

    <a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
    

    Het voorgaande ankerelement is een Tag Helper. In dit geval is het de Anchor Tag Helper. Het asp-page="/Movies/Index" Tag Helper-kenmerk en -waarde maken een koppeling naar de /Movies/IndexRazor pagina. De asp-area kenmerkwaarde is leeg, dus het gebied wordt niet gebruikt in de koppeling. Zie Gebieden voor meer informatie.

  4. Sla de wijzigingen op en test de app door de RpMovie-koppeling te selecteren. Zie het bestand _Layout.cshtml in GitHub als u problemen ondervindt.

  5. Test de koppelingen Home, RpMovie, Maken, Bewerken en Verwijderen. Op elke pagina wordt de titel ingesteld die je in het tabblad van de browser kunt zien. Wanneer je een pagina als bladwijzer opslaat, wordt de titel gebruikt voor de bladwijzer.

Opmerking

Mogelijk kunt u geen decimale komma's invoeren in het veld Price. Als u jQuery-validatie wilt ondersteunen voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en niet-US-English datumnotaties, moet u stappen ondernemen om de app te globaliseren. Zie dit GitHub-probleem 4076 voor instructies over het toevoegen van decimale komma's.

De Layout eigenschap is ingesteld in het Pages/_ViewStart.cshtml bestand:

@{
    Layout = "_Layout";
}

Met de voorgaande opmaak wordt het indelingsbestand ingesteld Pages/Shared/_Layout.cshtml op alle Razor bestanden onder de map Pagina's . Zie Indeling voor meer informatie.

Het paginamodel maken

Bekijk het Pages/Movies/Create.cshtml.cs paginamodel:

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");
        }
    }
}

De OnGet methode initialiseert alle statussen die nodig zijn voor de pagina. De Maakpagina heeft geen status die hoeft te worden geïnitialiseerd, dus Page wordt geretourneerd. Verderop in de zelfstudie wordt een voorbeeld van OnGet de initialisatiestatus weergegeven. Met de Page methode wordt een PageResult object gemaakt waarmee de Create.cshtml pagina wordt weergegeven.

De Movie eigenschap maakt gebruik van het kenmerk [BindProperty] om deel te nemen aan modelbinding. Wanneer het formulier maken de formulierwaarden plaatst, verbindt de ASP.NET Core-runtime de geplaatste waarden aan het Movie model.

De OnPostAsync methode wordt uitgevoerd wanneer de formuliergegevens van de pagina worden geplaatst:

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");
}

Als er modelfouten zijn, wordt het formulier opnieuw weergegeven, samen met eventuele formuliergegevens die zijn gepost. De meeste modelfouten kunnen aan de clientzijde worden opgevangen voordat het formulier wordt geplaatst. Een voorbeeld van een modelfout is het posten van een waarde voor het datumveld dat niet kan worden geconverteerd naar een datum. Validatie aan de clientzijde en modelvalidatie worden verderop in de zelfstudie besproken.

Als er geen modelfouten zijn:

  • De gegevens worden opgeslagen.
  • De browser wordt omgeleid naar de pagina Index.

De pagina Maken Razor

Bekijk het Pages/Movies/Create.cshtmlRazor paginabestand:

@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 geeft de volgende tags weer in een opvallend vet lettertype dat wordt gebruikt voor Tag Helpers:

  • <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>

VS17-weergave van de pagina Create.cshtml

Het <form method="post"> element is een Helper voor formuliertags. De Helper voor formuliertags bevat automatisch een antiforgery-token.

De scaffolding-engine creëert Razor markup voor elk veld in het model, behalve de ID, zoals de volgende:

<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>

In de Helpers voor validatietags (<div asp-validation-summary en <span asp-validation-for) worden validatiefouten weergegeven. De validatie wordt verderop in deze reeks uitgebreider besproken.

De Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genereert het labelbijschrift en [for] kenmerk voor de Title eigenschap.

De Helper voor invoertags (<input asp-for="Movie.Title" class="form-control">) maakt gebruik van de kenmerken DataAnnotations en produceert HTML-kenmerken die nodig zijn voor jQuery-validatie aan de clientzijde.

Zie <form method="post"> voor meer informatie over Tag Helpers zoals.

Volgende stappen

De pagina's Maken, Verwijderen, Details en Bewerken

Bekijk het Pages/Movies/Index.cshtml.cs paginamodel:

// 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 Pagina's zijn afgeleid van PageModel. Volgens conventie wordt de PageModel-afgeleide klasse <PageName>Model genoemd. De constructor gebruikt afhankelijkheidsinjectie om RazorPagesMovieContext aan de pagina toe te voegen.

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

Zie Asynchrone code voor meer informatie over asynchrone programmering met Entity Framework.

Wanneer er een aanvraag voor de pagina wordt ingediend, retourneert de OnGetAsync methode een lijst met films naar de Razor pagina. Op een Razor pagina OnGetAsync of OnGet wordt aangeroepen om de status van de pagina te initialiseren. In dit geval haalt OnGetAsync een lijst met films op en geeft deze weer.

Wanneer OnGetvoid teruggeeft of OnGetAsyncTask teruggeeft, wordt er geen return-statement gebruikt. Bijvoorbeeld de Privacy pagina:

public class PrivacyModel : PageModel
{
    private readonly ILogger<PrivacyModel> _logger;

    public PrivacyModel(ILogger<PrivacyModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
    }
}

Wanneer het retourtype IActionResult of Task<IActionResult> is, moet er een returninstructie worden opgegeven. Bijvoorbeeld de Pages/Movies/Create.cshtml.csOnPostAsync methode:

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Movie.Add(Movie);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

Bekijk de Pages/Movies/Index.cshtmlRazor pagina:

@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 kan worden overgestapt van HTML naar C# of naar Razor-specifieke markeringen. Wanneer een @ symbool wordt gevolgd door een Razor gereserveerd trefwoord, wordt het overgegaan naar Razor-specifieke markeringen, anders wordt het overgegaan naar C#.

De richtlijn @page

De @pageRazor instructie maakt het bestand een MVC-actie, wat betekent dat het aanvragen kan verwerken. @page moet de eerste Razor instructie op een pagina zijn. @page en @model zijn voorbeelden van overgang naar Razor-specifieke markeringen. Zie Razor de syntaxis voor meer informatie.

De richtlijn @model

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

De @model richtlijn geeft het type model aan dat aan de Razor pagina wordt doorgegeven. In het voorgaande voorbeeld maakt de @model regel de afgeleide PageModel-klasse beschikbaar voor de Razor pagina. Het model wordt gebruikt in de @Html.DisplayNameFor@Html.DisplayForHTML-Helpers op de pagina.

Bekijk de lambda-expressie die wordt gebruikt in de volgende HTML-helper:

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

De DisplayNameFor HTML Helper inspecteert de Title eigenschap waarnaar wordt verwezen in de lambda-expressie om de weergavenaam te bepalen. De lambda-expressie wordt geïnspecteerd in plaats van geëvalueerd. Dit betekent dat er geen toegangsschending is wanneer model, model.Movie, of model.Movie[0]null of leeg is. Wanneer de lambda-expressie wordt geëvalueerd, bijvoorbeeld met @Html.DisplayFor(modelItem => item.Title), worden de eigenschapswaarden van het model geëvalueerd.

De indelingspagina

Selecteer de menukoppelingen RazorPagesMovie, Home, en Privacy. Elke pagina bevat dezelfde menu-indeling. De menu-indeling wordt geïmplementeerd in het Pages/Shared/_Layout.cshtml bestand.

Open het Pages/Shared/_Layout.cshtml bestand en bekijk het.

Met indelingssjablonen kan de HTML-containerindeling het volgende zijn:

  • Gespecificeerd op één plaats.
  • Toegepast op meerdere pagina's op de site.

Zoek de @RenderBody() lijn. RenderBody is een tijdelijke aanduiding waarin alle paginaspecifieke weergaven worden weergegeven, verpakt op de indelingspagina. Selecteer bijvoorbeeld de Privacy koppeling en de Pages/Privacy.cshtml weergave wordt weergegeven in de RenderBody methode.

Weergavegegevens en layout

Houd rekening met de volgende markeringen uit het Pages/Movies/Index.cshtml bestand:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

De vooraf gemarkeerde markeringen zijn een voorbeeld van Razor dat overgaat naar C#. De { tekens en } bevatten een blok C#-code.

De PageModel basisklasse bevat een ViewData woordenlijsteigenschap die kan worden gebruikt om gegevens door te geven aan een weergave. Objecten worden aan de ViewData woordenlijst toegevoegd met behulp van een sleutelwaardepatroon . In het voorgaande voorbeeld wordt de Title eigenschap toegevoegd aan de ViewData woordenlijst.

De Title eigenschap wordt gebruikt in het Pages/Shared/_Layout.cshtml bestand. In de volgende markeringen worden de eerste regels van het _Layout.cshtml bestand weergegeven.

<!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.*@

De regel @*Markup removed for brevity.*@ is een Razor opmerking. In tegenstelling tot HTML-opmerkingen <!-- -->worden Razor opmerkingen niet naar de client verzonden. Zie MDN-webdocumenten: Aan de slag met HTML voor meer informatie.

De indeling bijwerken

  1. Wijzig het <title> element in het Pages/Shared/_Layout.cshtml bestand om Film weer te geven in plaats van RazorPagesMovie.

    <!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>
    
  2. Zoek het volgende ankerelement in het Pages/Shared/_Layout.cshtml bestand.

    <a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
    
  3. Vervang het voorgaande element door de volgende markeringen:

    <a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
    

    Het voorgaande ankerelement is een Tag Helper. In dit geval is het de Anchor Tag Helper. Het asp-page="/Movies/Index" Tag Helper-kenmerk en -waarde maken een koppeling naar de /Movies/IndexRazor pagina. De asp-area kenmerkwaarde is leeg, dus het gebied wordt niet gebruikt in de koppeling. Zie Gebieden voor meer informatie.

  4. Sla de wijzigingen op en test de app door de RpMovie-koppeling te selecteren. Zie het bestand _Layout.cshtml in GitHub als u problemen ondervindt.

  5. Test de koppelingen Home, RpMovie, Maken, Bewerken en Verwijderen. Op elke pagina wordt de titel ingesteld die je in het tabblad van de browser kunt zien. Wanneer je een pagina als bladwijzer opslaat, wordt de titel gebruikt voor de bladwijzer.

Opmerking

Mogelijk kunt u geen decimale komma's invoeren in het veld Price. Als u jQuery-validatie wilt ondersteunen voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en niet-US-English datumnotaties, moet u stappen ondernemen om de app te globaliseren. Zie dit GitHub-probleem 4076 voor instructies over het toevoegen van decimale komma's.

De Layout eigenschap is ingesteld in het Pages/_ViewStart.cshtml bestand:

@{
    Layout = "_Layout";
}

Met de voorgaande opmaak wordt het indelingsbestand ingesteld Pages/Shared/_Layout.cshtml op alle Razor bestanden onder de map Pagina's . Zie Indeling voor meer informatie.

Het paginamodel maken

Bekijk het Pages/Movies/Create.cshtml.cs paginamodel:

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");
        }
    }
}

De OnGet methode initialiseert alle statussen die nodig zijn voor de pagina. De Maakpagina heeft geen status die hoeft te worden geïnitialiseerd, dus Page wordt geretourneerd. Verderop in de zelfstudie wordt een voorbeeld van OnGet de initialisatiestatus weergegeven. Met de Page methode wordt een PageResult object gemaakt waarmee de Create.cshtml pagina wordt weergegeven.

De Movie eigenschap maakt gebruik van het kenmerk [BindProperty] om deel te nemen aan modelbinding. Wanneer het formulier maken de formulierwaarden plaatst, verbindt de ASP.NET Core-runtime de geplaatste waarden aan het Movie model.

De OnPostAsync methode wordt uitgevoerd wanneer de formuliergegevens van de pagina worden geplaatst:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Movie.Add(Movie);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Als er modelfouten zijn, wordt het formulier opnieuw weergegeven, samen met eventuele formuliergegevens die zijn gepost. De meeste modelfouten kunnen aan de clientzijde worden opgevangen voordat het formulier wordt geplaatst. Een voorbeeld van een modelfout is het posten van een waarde voor het datumveld dat niet kan worden geconverteerd naar een datum. Validatie aan de clientzijde en modelvalidatie worden verderop in de zelfstudie besproken.

Als er geen modelfouten zijn:

  • De gegevens worden opgeslagen.
  • De browser wordt omgeleid naar de pagina Index.

De pagina Maken Razor

Bekijk het Pages/Movies/Create.cshtmlRazor paginabestand:

@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 geeft de volgende tags weer in een opvallend vet lettertype dat wordt gebruikt voor Tag Helpers:

  • <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>

VS17-weergave van de pagina Create.cshtml

Het <form method="post"> element is een Helper voor formuliertags. De Helper voor formuliertags bevat automatisch een antiforgery-token.

De scaffolding-engine creëert Razor markup voor elk veld in het model, behalve de ID, zoals de volgende:

<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>

In de Helpers voor validatietags (<div asp-validation-summary en <span asp-validation-for) worden validatiefouten weergegeven. De validatie wordt verderop in deze reeks uitgebreider besproken.

De Label Tag Helper (<label asp-for="Movie.Title" class="control-label"></label>) genereert het labelbijschrift en [for] kenmerk voor de Title eigenschap.

De Helper voor invoertags (<input asp-for="Movie.Title" class="form-control">) maakt gebruik van de kenmerken DataAnnotations en produceert HTML-kenmerken die nodig zijn voor jQuery-validatie aan de clientzijde.

Zie <form method="post"> voor meer informatie over Tag Helpers zoals.

Volgende stappen