Część 3, strony szkieletowe Razor w ASP.NET Core
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Autor: Rick Anderson
Ten samouczek analizuje Razor strony utworzone przez tworzenie szkieletów w poprzednim samouczku.
Strony Tworzenie, Usuwanie, Szczegóły i Edytowanie
Pages/Movies/Index.cshtml.cs
Sprawdź model strony:
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 Strony pochodzą z elementu PageModel. Zgodnie z konwencją klasa pochodna PageModel
nosi nazwę PageNameModel
. Na przykład strona Indeks ma nazwę IndexModel
.
Konstruktor używa iniekcji zależności, aby dodać element RazorPagesMovieContext
do strony:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Zobacz Kod asynchroniczny, aby uzyskać więcej informacji na temat programowania asynchronicznego w programie Entity Framework.
GET
Po wysłaniu żądania dla strony OnGetAsync
metoda zwraca listę filmów do stronyRazor. Razor Na stronie lub OnGet
jest wywoływana w OnGetAsync
celu zainicjowania stanu strony. W tym przypadku OnGetAsync
pobiera listę filmów i wyświetla je.
Gdy OnGet
zwraca void
lub OnGetAsync
zwraca Task
wartość , nie jest używana żadna instrukcja return. Na przykład sprawdź Privacy stronę:
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()
{
}
}
}
Gdy zwracany typ to IActionResult lub Task<IActionResult>
, należy podać instrukcję return. Na przykład Pages/Movies/Create.cshtml.cs OnPostAsync
metoda:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Sprawdź stronę Pages/Movies/Index.cshtml
Razor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor może przejść z kodu HTML do języka C# lub do Razorznaczników specyficznych. Gdy po Razor symbolu @
następuje zastrzeżone słowo kluczowe, przechodzi do znaczników specyficznych dla języka C#. W przeciwnym razie przechodzi do Razorjęzyka C#.
Dyrektywa @page
Dyrektywa @page
Razor sprawia, że plik jest akcją MVC, co oznacza, że może obsługiwać żądania. Dyrektywa @page
musi być pierwszą dyrektywą Razor na stronie. @page
i @model
to przykłady przejścia na Razorznaczniki specyficzne dla języka . Zobacz Razor składnię , aby uzyskać więcej informacji.
Dyrektywa @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Dyrektywa @model
określa typ modelu przekazanego Razor do strony. W poprzednim przykładzie wiersz sprawia, @model
że klasa pochodna PageModel
jest dostępna dla strony Razor . Model jest używany w pomocnikach @Html.DisplayNameFor
HTML i @Html.DisplayFor
na stronie.
Sprawdź wyrażenie lambda używane w następującym pomocniku HTML:
@Html.DisplayNameFor(model => model.Movie[0].Title)
Pomocnik DisplayNameFor HTML sprawdza Title
właściwość przywoływane w wyrażeniu lambda, aby określić nazwę wyświetlaną. Wyrażenie lambda jest sprawdzane, a nie oceniane. Oznacza to, że nie ma naruszenia dostępu, gdy model
wartość , model.Movie
lub model.Movie[0]
jest pusta null
. Gdy wyrażenie lambda jest obliczane, na przykład przy @Html.DisplayFor(modelItem => item.Title)
użyciu metody , wartości właściwości modelu są oceniane.
Strona układu
Wybierz łącza menu RazorPagesFilm, Homei Privacy. Każda strona zawiera ten sam układ menu. Układ menu jest implementowany w Pages/Shared/_Layout.cshtml
pliku.
Otwórz plik i sprawdź go Pages/Shared/_Layout.cshtml
.
Szablony układów umożliwiają układ kontenera HTML:
- Określone w jednym miejscu.
- Zastosowane na wielu stronach w witrynie.
@RenderBody()
Znajdź wiersz. RenderBody
to symbol zastępczy, w którym są wyświetlane wszystkie widoki specyficzne dla strony, opakowane na stronie układu. Na przykład wybierz Privacy link, a Pages/Privacy.cshtml
widok jest renderowany wewnątrz RenderBody
metody .
ViewData i układ
Rozważ następujące znaczniki z Pages/Movies/Index.cshtml
pliku:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Powyższy wyróżniony znacznik jest przykładem Razor przejścia do języka C#. Znaki {
i }
otaczają blok kodu języka C#.
Klasa PageModel
bazowa zawiera właściwość słownika ViewData
, która może służyć do przekazywania danych do widoku. Obiekty są dodawane do słownika ViewData
przy użyciu wzorca wartości klucza. W poprzednim przykładzie Title
właściwość jest dodawana do słownika ViewData
.
Właściwość Title
jest używana w Pages/Shared/_Layout.cshtml
pliku . Poniższy znacznik przedstawia kilka pierwszych wierszy _Layout.cshtml
pliku.
<!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" />
Aktualizowanie układu
<title>
Zmień element w pliku,Pages/Shared/_Layout.cshtml
aby wyświetlić film, a nie RazorPagesPanel.<!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>
Znajdź następujący element zakotwiczenia w
Pages/Shared/_Layout.cshtml
pliku.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Zastąp poprzedni element następującym znacznikiem:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
Poprzedni element kotwicy jest pomocnikem tagów. W tym przypadku jest to pomocnik tagu kotwicy. Atrybut
asp-page="/Movies/Index"
i wartość Pomocnika tagów/Movies/Index
Razor tworzą link do strony. Wartość atrybutuasp-area
jest pusta, więc obszar nie jest używany w linku. Aby uzyskać więcej informacji, zobacz Obszary .Zapisz zmiany i przetestuj aplikację, wybierając link RpFilm . Jeśli masz jakiekolwiek problemy, zobacz plik _Layout.cshtml w usłudze GitHub.
Przetestuj Homełącza , RpFilm, Create, Edit i Delete. Każda strona ustawia tytuł, który można wyświetlić na karcie przeglądarki. Podczas tworzenia zakładek tytuł jest używany dla zakładki.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i formatów dat innych niż angielskie stany USA, należy wykonać kroki w celu globalizacji aplikacji. Zobacz ten problem z usługą GitHub 4076 , aby uzyskać instrukcje dotyczące dodawania przecinka dziesiętnego.
Właściwość Layout
jest ustawiana w Pages/_ViewStart.cshtml
pliku:
@{
Layout = "_Layout";
}
Powyższy znacznik ustawia plik układu na Pages/Shared/_Layout.cshtml
dla wszystkich Razor plików w folderze Pages . Aby uzyskać więcej informacji, zobacz Układ .
Model tworzenia strony
Pages/Movies/Create.cshtml.cs
Sprawdź model strony:
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");
}
}
}
Metoda OnGet
inicjuje dowolny stan wymagany dla strony. Strona Tworzenie nie ma żadnego stanu do zainicjowania, dlatego Page
jest zwracana. W dalszej części samouczka zostanie wyświetlony przykład inicjowania OnGet
stanu. Metoda Page
tworzy PageResult
obiekt renderujący Create.cshtml
stronę.
Właściwość Movie
używa atrybutu [BindProperty], aby wyrazić zgodę na powiązanie modelu. Gdy formularz Tworzenie publikuje wartości formularza, środowisko uruchomieniowe ASP.NET Core wiąże opublikowane wartości z modelem Movie
.
Metoda OnPostAsync
jest uruchamiana, gdy strona publikuje dane formularza:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Jeśli występują jakiekolwiek błędy modelu, formularz jest odtwarzany ponownie wraz z dowolnymi opublikowanymi danymi formularza. Większość błędów modelu można przechwycić po stronie klienta przed opublikowaniem formularza. Przykładem błędu modelu jest opublikowanie wartości pola daty, którego nie można przekonwertować na datę. Walidacja po stronie klienta i walidacja modelu zostały omówione w dalszej części tego samouczka.
Jeśli nie ma żadnych błędów modelu:
- Dane są zapisywane.
- Przeglądarka jest przekierowywana do strony Indeks.
Strona tworzenia Razor
Pages/Movies/Create.cshtml
Razor Sprawdź plik strony:
@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");}
}
Program Visual Studio wyświetla następujące tagi w charakterystycznej czcionki pogrubionej używanej dla pomocników tagów:
<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>
Element <form method="post">
jest pomocnikiem tagu formularza. Pomocnik tagu formularza automatycznie zawiera token antyforgery.
Aparat tworzenia szkieletów tworzy Razor znaczniki dla każdego pola w modelu, z wyjątkiem identyfikatora, podobnego do następującego:
<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>
Pomocnicy tagów walidacji (<div asp-validation-summary
i <span asp-validation-for
) wyświetlają błędy walidacji. Walidacja zostanie szczegółowo omówiona w dalszej części tej serii.
Pomocnik tagów etykiet (<label asp-for="Movie.Title" class="control-label"></label>
) generuje podpis [for]
i atrybut etykiety dla Title
właściwości.
Pomocnik tagów wejściowych (<input asp-for="Movie.Title" class="form-control">
) używa atrybutów DataAnnotations i tworzy atrybuty HTML wymagane do weryfikacji jQuery po stronie klienta.
Aby uzyskać więcej informacji na temat pomocników tagów, takich jak <form method="post">
, zobacz Pomocnicy tagów w ASP.NET Core.
Następne kroki
Strony Tworzenie, Usuwanie, Szczegóły i Edytowanie
Pages/Movies/Index.cshtml.cs
Sprawdź model strony:
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 Strony pochodzą z elementu PageModel. Zgodnie z konwencją klasa pochodna PageModel
nosi nazwę PageNameModel
. Na przykład strona Indeks ma nazwę IndexModel
.
Konstruktor używa iniekcji zależności, aby dodać element RazorPagesMovieContext
do strony:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Zobacz Kod asynchroniczny, aby uzyskać więcej informacji na temat programowania asynchronicznego w programie Entity Framework.
GET
Po wysłaniu żądania dla strony OnGetAsync
metoda zwraca listę filmów do stronyRazor. Razor Na stronie lub OnGet
jest wywoływana w OnGetAsync
celu zainicjowania stanu strony. W tym przypadku OnGetAsync
pobiera listę filmów i wyświetla je.
Gdy OnGet
zwraca void
lub OnGetAsync
zwraca Task
wartość , nie jest używana żadna instrukcja return. Na przykład sprawdź Privacy stronę:
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()
{
}
}
}
Gdy zwracany typ to IActionResult lub Task<IActionResult>
, należy podać instrukcję return. Na przykład Pages/Movies/Create.cshtml.cs OnPostAsync
metoda:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Sprawdź stronę Pages/Movies/Index.cshtml
Razor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor może przejść z kodu HTML do języka C# lub do Razorznaczników specyficznych. Gdy po Razor symbolu @
następuje zastrzeżone słowo kluczowe, przechodzi do znaczników specyficznych dla języka C#. W przeciwnym razie przechodzi do Razorjęzyka C#.
Dyrektywa @page
Dyrektywa @page
Razor sprawia, że plik jest akcją MVC, co oznacza, że może obsługiwać żądania. Dyrektywa @page
musi być pierwszą dyrektywą Razor na stronie. @page
i @model
to przykłady przejścia na Razorznaczniki specyficzne dla języka . Zobacz Razor składnię , aby uzyskać więcej informacji.
Dyrektywa @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Dyrektywa @model
określa typ modelu przekazanego Razor do strony. W poprzednim przykładzie wiersz sprawia, @model
że klasa pochodna PageModel
jest dostępna dla strony Razor . Model jest używany w pomocnikach @Html.DisplayNameFor
HTML i @Html.DisplayFor
na stronie.
Sprawdź wyrażenie lambda używane w następującym pomocniku HTML:
@Html.DisplayNameFor(model => model.Movie[0].Title)
Pomocnik DisplayNameFor HTML sprawdza Title
właściwość przywoływane w wyrażeniu lambda, aby określić nazwę wyświetlaną. Wyrażenie lambda jest sprawdzane, a nie oceniane. Oznacza to, że nie ma naruszenia dostępu, gdy model
wartość , model.Movie
lub model.Movie[0]
jest pusta null
. Gdy wyrażenie lambda jest obliczane, na przykład przy @Html.DisplayFor(modelItem => item.Title)
użyciu metody , wartości właściwości modelu są oceniane.
Strona układu
Wybierz łącza menu RazorPagesFilm, Homei Privacy. Każda strona zawiera ten sam układ menu. Układ menu jest implementowany w Pages/Shared/_Layout.cshtml
pliku.
Otwórz plik i sprawdź go Pages/Shared/_Layout.cshtml
.
Szablony układów umożliwiają układ kontenera HTML:
- Określone w jednym miejscu.
- Zastosowane na wielu stronach w witrynie.
@RenderBody()
Znajdź wiersz. RenderBody
to symbol zastępczy, w którym są wyświetlane wszystkie widoki specyficzne dla strony, opakowane na stronie układu. Na przykład wybierz Privacy link, a Pages/Privacy.cshtml
widok jest renderowany wewnątrz RenderBody
metody .
ViewData i układ
Rozważ następujące znaczniki z Pages/Movies/Index.cshtml
pliku:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Powyższy wyróżniony znacznik jest przykładem Razor przejścia do języka C#. Znaki {
i }
otaczają blok kodu języka C#.
Klasa PageModel
bazowa zawiera właściwość słownika ViewData
, która może służyć do przekazywania danych do widoku. Obiekty są dodawane do słownika ViewData
przy użyciu wzorca wartości klucza. W poprzednim przykładzie Title
właściwość jest dodawana do słownika ViewData
.
Właściwość Title
jest używana w Pages/Shared/_Layout.cshtml
pliku . Poniższy znacznik przedstawia kilka pierwszych wierszy _Layout.cshtml
pliku.
<!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" />
Aktualizowanie układu
<title>
Zmień element w pliku,Pages/Shared/_Layout.cshtml
aby wyświetlić film, a nie RazorPagesPanel.<!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>
Znajdź następujący element zakotwiczenia w
Pages/Shared/_Layout.cshtml
pliku.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Zastąp poprzedni element następującym znacznikiem:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
Poprzedni element kotwicy jest pomocnikem tagów. W tym przypadku jest to pomocnik tagu kotwicy. Atrybut
asp-page="/Movies/Index"
i wartość Pomocnika tagów/Movies/Index
Razor tworzą link do strony. Wartość atrybutuasp-area
jest pusta, więc obszar nie jest używany w linku. Aby uzyskać więcej informacji, zobacz Obszary .Zapisz zmiany i przetestuj aplikację, wybierając link RpFilm . Jeśli masz jakiekolwiek problemy, zobacz plik _Layout.cshtml w usłudze GitHub.
Przetestuj Homełącza , RpFilm, Create, Edit i Delete. Każda strona ustawia tytuł, który można wyświetlić na karcie przeglądarki. Podczas tworzenia zakładek tytuł jest używany dla zakładki.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i formatów dat innych niż angielskie stany USA, należy wykonać kroki w celu globalizacji aplikacji. Zobacz ten problem z usługą GitHub 4076 , aby uzyskać instrukcje dotyczące dodawania przecinka dziesiętnego.
Właściwość Layout
jest ustawiana w Pages/_ViewStart.cshtml
pliku:
@{
Layout = "_Layout";
}
Powyższy znacznik ustawia plik układu na Pages/Shared/_Layout.cshtml
dla wszystkich Razor plików w folderze Pages . Aby uzyskać więcej informacji, zobacz Układ .
Model tworzenia strony
Pages/Movies/Create.cshtml.cs
Sprawdź model strony:
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");
}
}
}
Metoda OnGet
inicjuje dowolny stan wymagany dla strony. Strona Tworzenie nie ma żadnego stanu do zainicjowania, dlatego Page
jest zwracana. W dalszej części samouczka zostanie wyświetlony przykład inicjowania OnGet
stanu. Metoda Page
tworzy PageResult
obiekt renderujący Create.cshtml
stronę.
Właściwość Movie
używa atrybutu [BindProperty], aby wyrazić zgodę na powiązanie modelu. Gdy formularz Tworzenie publikuje wartości formularza, środowisko uruchomieniowe ASP.NET Core wiąże opublikowane wartości z modelem Movie
.
Metoda OnPostAsync
jest uruchamiana, gdy strona publikuje dane formularza:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Jeśli występują jakiekolwiek błędy modelu, formularz jest odtwarzany ponownie wraz z dowolnymi opublikowanymi danymi formularza. Większość błędów modelu można przechwycić po stronie klienta przed opublikowaniem formularza. Przykładem błędu modelu jest opublikowanie wartości pola daty, którego nie można przekonwertować na datę. Walidacja po stronie klienta i walidacja modelu zostały omówione w dalszej części tego samouczka.
Jeśli nie ma żadnych błędów modelu:
- Dane są zapisywane.
- Przeglądarka jest przekierowywana do strony Indeks.
Strona tworzenia Razor
Pages/Movies/Create.cshtml
Razor Sprawdź plik strony:
@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");}
}
Program Visual Studio wyświetla następujące tagi w charakterystycznej czcionki pogrubionej używanej dla pomocników tagów:
<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>
Element <form method="post">
jest pomocnikiem tagu formularza. Pomocnik tagu formularza automatycznie zawiera token antyforgery.
Aparat tworzenia szkieletów tworzy Razor znaczniki dla każdego pola w modelu, z wyjątkiem identyfikatora, podobnego do następującego:
<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>
Pomocnicy tagów walidacji (<div asp-validation-summary
i <span asp-validation-for
) wyświetlają błędy walidacji. Walidacja zostanie szczegółowo omówiona w dalszej części tej serii.
Pomocnik tagów etykiet (<label asp-for="Movie.Title" class="control-label"></label>
) generuje podpis [for]
i atrybut etykiety dla Title
właściwości.
Pomocnik tagów wejściowych (<input asp-for="Movie.Title" class="form-control">
) używa atrybutów DataAnnotations i tworzy atrybuty HTML wymagane do weryfikacji jQuery po stronie klienta.
Aby uzyskać więcej informacji na temat pomocników tagów, takich jak <form method="post">
, zobacz Pomocnicy tagów w ASP.NET Core.
Następne kroki
Strony Tworzenie, Usuwanie, Szczegóły i Edytowanie
Pages/Movies/Index.cshtml.cs
Sprawdź model strony:
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 Strony pochodzą z elementu PageModel. Zgodnie z konwencją klasa pochodna PageModel
nosi nazwę PageNameModel
. Na przykład strona Indeks ma nazwę IndexModel
.
Konstruktor używa iniekcji zależności, aby dodać element RazorPagesMovieContext
do strony:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Zobacz Kod asynchroniczny, aby uzyskać więcej informacji na temat programowania asynchronicznego w programie Entity Framework.
GET
Po wysłaniu żądania dla strony OnGetAsync
metoda zwraca listę filmów do stronyRazor. Razor Na stronie lub OnGet
jest wywoływana w OnGetAsync
celu zainicjowania stanu strony. W tym przypadku OnGetAsync
pobiera listę filmów i wyświetla je.
Gdy OnGet
zwraca void
lub OnGetAsync
zwraca Task
wartość , nie jest używana żadna instrukcja return. Na przykład sprawdź Privacy stronę:
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()
{
}
}
}
Gdy zwracany typ to IActionResult lub Task<IActionResult>
, należy podać instrukcję return. Na przykład Pages/Movies/Create.cshtml.cs OnPostAsync
metoda:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Sprawdź stronę Pages/Movies/Index.cshtml
Razor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor może przejść z kodu HTML do języka C# lub do Razorznaczników specyficznych. Gdy po Razor symbolu @
następuje zastrzeżone słowo kluczowe, przechodzi do znaczników specyficznych dla języka C#. W przeciwnym razie przechodzi do Razorjęzyka C#.
Dyrektywa @page
Dyrektywa @page
Razor sprawia, że plik jest akcją MVC, co oznacza, że może obsługiwać żądania. Dyrektywa @page
musi być pierwszą dyrektywą Razor na stronie. @page
i @model
to przykłady przejścia na Razorznaczniki specyficzne dla języka . Zobacz Razor składnię , aby uzyskać więcej informacji.
Dyrektywa @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Dyrektywa @model
określa typ modelu przekazanego Razor do strony. W poprzednim przykładzie wiersz sprawia, @model
że klasa pochodna PageModel
jest dostępna dla strony Razor . Model jest używany w pomocnikach @Html.DisplayNameFor
HTML i @Html.DisplayFor
na stronie.
Sprawdź wyrażenie lambda używane w następującym pomocniku HTML:
@Html.DisplayNameFor(model => model.Movie[0].Title)
Pomocnik DisplayNameFor HTML sprawdza Title
właściwość przywoływane w wyrażeniu lambda, aby określić nazwę wyświetlaną. Wyrażenie lambda jest sprawdzane, a nie oceniane. Oznacza to, że nie ma naruszenia dostępu, gdy model
wartość , model.Movie
lub model.Movie[0]
jest pusta null
. Gdy wyrażenie lambda jest obliczane, na przykład przy @Html.DisplayFor(modelItem => item.Title)
użyciu metody , wartości właściwości modelu są oceniane.
Strona układu
Wybierz łącza menu RazorPagesFilm, Homei Privacy. Każda strona zawiera ten sam układ menu. Układ menu jest implementowany w Pages/Shared/_Layout.cshtml
pliku.
Otwórz plik i sprawdź go Pages/Shared/_Layout.cshtml
.
Szablony układów umożliwiają układ kontenera HTML:
- Określone w jednym miejscu.
- Zastosowane na wielu stronach w witrynie.
@RenderBody()
Znajdź wiersz. RenderBody
to symbol zastępczy, w którym są wyświetlane wszystkie widoki specyficzne dla strony, opakowane na stronie układu. Na przykład wybierz Privacy link, a Pages/Privacy.cshtml
widok jest renderowany wewnątrz RenderBody
metody .
ViewData i układ
Rozważ następujące znaczniki z Pages/Movies/Index.cshtml
pliku:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Powyższy wyróżniony znacznik jest przykładem Razor przejścia do języka C#. Znaki {
i }
otaczają blok kodu języka C#.
Klasa PageModel
bazowa zawiera właściwość słownika ViewData
, która może służyć do przekazywania danych do widoku. Obiekty są dodawane do słownika ViewData
przy użyciu wzorca wartości klucza. W poprzednim przykładzie Title
właściwość jest dodawana do słownika ViewData
.
Właściwość Title
jest używana w Pages/Shared/_Layout.cshtml
pliku . Poniższy znacznik przedstawia kilka pierwszych wierszy _Layout.cshtml
pliku.
<!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" />
Wiersz @*Markup removed for brevity.*@
jest komentarzem Razor . W przeciwieństwie do komentarzy <!-- -->
Razor HTML komentarze nie są wysyłane do klienta. Aby uzyskać więcej informacji, zobacz Dokumentację internetową usługi MDN: Wprowadzenie do języka HTML .
Aktualizowanie układu
<title>
Zmień element w pliku,Pages/Shared/_Layout.cshtml
aby wyświetlić film, a nie RazorPagesPanel.<!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>
Znajdź następujący element zakotwiczenia w
Pages/Shared/_Layout.cshtml
pliku.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Zastąp poprzedni element następującym znacznikiem:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
Poprzedni element kotwicy jest pomocnikem tagów. W tym przypadku jest to pomocnik tagu kotwicy. Atrybut
asp-page="/Movies/Index"
i wartość Pomocnika tagów/Movies/Index
Razor tworzą link do strony. Wartość atrybutuasp-area
jest pusta, więc obszar nie jest używany w linku. Aby uzyskać więcej informacji, zobacz Obszary .Zapisz zmiany i przetestuj aplikację, wybierając link RpFilm . Jeśli masz jakiekolwiek problemy, zobacz plik _Layout.cshtml w usłudze GitHub.
Przetestuj Homełącza , RpFilm, Create, Edit i Delete. Każda strona ustawia tytuł, który można wyświetlić na karcie przeglądarki. Podczas tworzenia zakładek tytuł jest używany dla zakładki.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i formatów dat innych niż angielskie stany USA, należy wykonać kroki w celu globalizacji aplikacji. Zobacz ten problem z usługą GitHub 4076 , aby uzyskać instrukcje dotyczące dodawania przecinka dziesiętnego.
Właściwość Layout
jest ustawiana w Pages/_ViewStart.cshtml
pliku:
@{
Layout = "_Layout";
}
Powyższy znacznik ustawia plik układu na Pages/Shared/_Layout.cshtml
dla wszystkich Razor plików w folderze Pages . Aby uzyskać więcej informacji, zobacz Układ .
Model tworzenia strony
Pages/Movies/Create.cshtml.cs
Sprawdź model strony:
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");
}
}
}
Metoda OnGet
inicjuje dowolny stan wymagany dla strony. Strona Tworzenie nie ma żadnego stanu do zainicjowania, dlatego Page
jest zwracana. W dalszej części samouczka zostanie wyświetlony przykład inicjowania OnGet
stanu. Metoda Page
tworzy PageResult
obiekt renderujący Create.cshtml
stronę.
Właściwość Movie
używa atrybutu [BindProperty], aby wyrazić zgodę na powiązanie modelu. Gdy formularz Tworzenie publikuje wartości formularza, środowisko uruchomieniowe ASP.NET Core wiąże opublikowane wartości z modelem Movie
.
Metoda OnPostAsync
jest uruchamiana, gdy strona publikuje dane formularza:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Jeśli występują jakiekolwiek błędy modelu, formularz jest odtwarzany ponownie wraz z dowolnymi opublikowanymi danymi formularza. Większość błędów modelu można przechwycić po stronie klienta przed opublikowaniem formularza. Przykładem błędu modelu jest opublikowanie wartości pola daty, którego nie można przekonwertować na datę. Walidacja po stronie klienta i walidacja modelu zostały omówione w dalszej części tego samouczka.
Jeśli nie ma żadnych błędów modelu:
- Dane są zapisywane.
- Przeglądarka jest przekierowywana do strony Indeks.
Strona tworzenia Razor
Pages/Movies/Create.cshtml
Razor Sprawdź plik strony:
@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");}
}
Program Visual Studio wyświetla następujące tagi w charakterystycznej czcionki pogrubionej używanej dla pomocników tagów:
<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>
Element <form method="post">
jest pomocnikiem tagu formularza. Pomocnik tagu formularza automatycznie zawiera token antyforgery.
Aparat tworzenia szkieletów tworzy Razor znaczniki dla każdego pola w modelu, z wyjątkiem identyfikatora, podobnego do następującego:
<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>
Pomocnicy tagów walidacji (<div asp-validation-summary
i <span asp-validation-for
) wyświetlają błędy walidacji. Walidacja zostanie szczegółowo omówiona w dalszej części tej serii.
Pomocnik tagów etykiet (<label asp-for="Movie.Title" class="control-label"></label>
) generuje podpis [for]
i atrybut etykiety dla Title
właściwości.
Pomocnik tagów wejściowych (<input asp-for="Movie.Title" class="form-control">
) używa atrybutów DataAnnotations i tworzy atrybuty HTML wymagane do weryfikacji jQuery po stronie klienta.
Aby uzyskać więcej informacji na temat pomocników tagów, takich jak <form method="post">
, zobacz Pomocnicy tagów w ASP.NET Core.
Następne kroki
Strony Tworzenie, Usuwanie, Szczegóły i Edytowanie
Pages/Movies/Index.cshtml.cs
Sprawdź model strony:
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 Strony pochodzą z elementu PageModel. Zgodnie z konwencją klasa pochodna PageModel
nosi nazwę PageNameModel
. Na przykład strona Indeks ma nazwę IndexModel
.
Konstruktor używa iniekcji zależności, aby dodać element RazorPagesMovieContext
do strony:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Zobacz Kod asynchroniczny, aby uzyskać więcej informacji na temat programowania asynchronicznego w programie Entity Framework.
Po wysłaniu żądania dla strony OnGetAsync
metoda zwraca listę filmów do strony Razor . Razor Na stronie lub OnGet
jest wywoływana w OnGetAsync
celu zainicjowania stanu strony. W tym przypadku OnGetAsync
pobiera listę filmów i wyświetla je.
Gdy OnGet
zwraca void
lub OnGetAsync
zwraca Task
wartość , nie jest używana żadna instrukcja return. Na przykład sprawdź Privacy stronę:
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()
{
}
}
}
Gdy zwracany typ to IActionResult lub Task<IActionResult>
, należy podać instrukcję return. Na przykład Pages/Movies/Create.cshtml.cs
OnPostAsync
metoda:
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");
}
Sprawdź stronę Pages/Movies/Index.cshtml
Razor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor może przejść z kodu HTML do języka C# lub do Razorznaczników specyficznych. Gdy po Razor symbolu @
następuje zastrzeżone słowo kluczowe, przechodzi do znaczników specyficznych dla języka C#. W przeciwnym razie przechodzi do Razorjęzyka C#.
Dyrektywa @page
Dyrektywa @page
Razor sprawia, że plik jest akcją MVC, co oznacza, że może obsługiwać żądania. Dyrektywa @page
musi być pierwszą dyrektywą Razor na stronie. @page
i @model
to przykłady przejścia na Razorznaczniki specyficzne dla języka . Zobacz Razor składnię , aby uzyskać więcej informacji.
Dyrektywa @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Dyrektywa @model
określa typ modelu przekazanego Razor do strony. W poprzednim przykładzie wiersz sprawia, @model
że klasa pochodna PageModel
jest dostępna dla strony Razor . Model jest używany w pomocnikach @Html.DisplayNameFor
HTML i @Html.DisplayFor
na stronie.
Sprawdź wyrażenie lambda używane w następującym pomocniku HTML:
@Html.DisplayNameFor(model => model.Movie[0].Title)
Pomocnik DisplayNameFor HTML sprawdza Title
właściwość przywoływane w wyrażeniu lambda, aby określić nazwę wyświetlaną. Wyrażenie lambda jest sprawdzane, a nie oceniane. Oznacza to, że nie ma naruszenia dostępu, gdy model
wartość , model.Movie
lub model.Movie[0]
jest pusta null
. Gdy wyrażenie lambda jest obliczane, na przykład przy @Html.DisplayFor(modelItem => item.Title)
użyciu metody , wartości właściwości modelu są oceniane.
Strona układu
Wybierz łącza menu RazorPagesFilm, Homei Privacy. Każda strona zawiera ten sam układ menu. Układ menu jest implementowany w Pages/Shared/_Layout.cshtml
pliku.
Otwórz plik i sprawdź go Pages/Shared/_Layout.cshtml
.
Szablony układów umożliwiają układ kontenera HTML:
- Określone w jednym miejscu.
- Zastosowane na wielu stronach w witrynie.
@RenderBody()
Znajdź wiersz. RenderBody
to symbol zastępczy, w którym są wyświetlane wszystkie widoki specyficzne dla strony, opakowane na stronie układu. Na przykład wybierz Privacy link, a Pages/Privacy.cshtml
widok jest renderowany wewnątrz RenderBody
metody .
ViewData i układ
Rozważ następujące znaczniki z Pages/Movies/Index.cshtml
pliku:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Powyższy wyróżniony znacznik jest przykładem Razor przejścia do języka C#. Znaki {
i }
otaczają blok kodu języka C#.
Klasa PageModel
bazowa zawiera właściwość słownika ViewData
, która może służyć do przekazywania danych do widoku. Obiekty są dodawane do słownika ViewData
przy użyciu wzorca wartości klucza. W poprzednim przykładzie Title
właściwość jest dodawana do słownika ViewData
.
Właściwość Title
jest używana w Pages/Shared/_Layout.cshtml
pliku . Poniższy znacznik przedstawia kilka pierwszych wierszy _Layout.cshtml
pliku.
<!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" />
Wiersz @*Markup removed for brevity.*@
jest komentarzem Razor . W przeciwieństwie do komentarzy <!-- -->
Razor HTML komentarze nie są wysyłane do klienta. Aby uzyskać więcej informacji, zobacz Dokumentację internetową usługi MDN: Wprowadzenie do języka HTML .
Aktualizowanie układu
<title>
Zmień element w pliku,Pages/Shared/_Layout.cshtml
aby wyświetlić film, a nie RazorPagesPanel.<!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>
Znajdź następujący element zakotwiczenia w
Pages/Shared/_Layout.cshtml
pliku.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Zastąp poprzedni element następującym znacznikiem:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
Poprzedni element kotwicy jest pomocnikem tagów. W tym przypadku jest to pomocnik tagu kotwicy. Atrybut
asp-page="/Movies/Index"
i wartość Pomocnika tagów/Movies/Index
Razor tworzą link do strony. Wartość atrybutuasp-area
jest pusta, więc obszar nie jest używany w linku. Aby uzyskać więcej informacji, zobacz Obszary .Zapisz zmiany i przetestuj aplikację, wybierając link RpFilm . Jeśli masz jakiekolwiek problemy, zobacz plik _Layout.cshtml w usłudze GitHub.
Przetestuj Homełącza , RpFilm, Create, Edit i Delete. Każda strona ustawia tytuł, który można wyświetlić na karcie przeglądarki. Podczas tworzenia zakładek tytuł jest używany dla zakładki.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i formatów dat innych niż angielskie stany USA, należy wykonać kroki w celu globalizacji aplikacji. Zobacz ten problem z usługą GitHub 4076 , aby uzyskać instrukcje dotyczące dodawania przecinka dziesiętnego.
Właściwość Layout
jest ustawiana w Pages/_ViewStart.cshtml
pliku:
@{
Layout = "_Layout";
}
Powyższy znacznik ustawia plik układu na Pages/Shared/_Layout.cshtml
dla wszystkich Razor plików w folderze Pages . Aby uzyskać więcej informacji, zobacz Układ .
Model tworzenia strony
Pages/Movies/Create.cshtml.cs
Sprawdź model strony:
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");
}
}
}
Metoda OnGet
inicjuje dowolny stan wymagany dla strony. Strona Tworzenie nie ma żadnego stanu do zainicjowania, dlatego Page
jest zwracana. W dalszej części samouczka zostanie wyświetlony przykład inicjowania OnGet
stanu. Metoda Page
tworzy PageResult
obiekt renderujący Create.cshtml
stronę.
Właściwość Movie
używa atrybutu [BindProperty], aby wyrazić zgodę na powiązanie modelu. Gdy formularz Tworzenie publikuje wartości formularza, środowisko uruchomieniowe ASP.NET Core wiąże opublikowane wartości z modelem Movie
.
Metoda OnPostAsync
jest uruchamiana, gdy strona publikuje dane formularza:
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");
}
Jeśli występują jakiekolwiek błędy modelu, formularz jest odtwarzany ponownie wraz z dowolnymi opublikowanymi danymi formularza. Większość błędów modelu można przechwycić po stronie klienta przed opublikowaniem formularza. Przykładem błędu modelu jest opublikowanie wartości pola daty, którego nie można przekonwertować na datę. Walidacja po stronie klienta i walidacja modelu zostały omówione w dalszej części tego samouczka.
Jeśli nie ma żadnych błędów modelu:
- Dane są zapisywane.
- Przeglądarka jest przekierowywana do strony Indeks.
Strona tworzenia Razor
Pages/Movies/Create.cshtml
Razor Sprawdź plik strony:
@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");}
}
Program Visual Studio wyświetla następujące tagi w charakterystycznej czcionki pogrubionej używanej dla pomocników tagów:
<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>
Element <form method="post">
jest pomocnikiem tagu formularza. Pomocnik tagu formularza automatycznie zawiera token antyforgery.
Aparat tworzenia szkieletów tworzy Razor znaczniki dla każdego pola w modelu, z wyjątkiem identyfikatora, podobnego do następującego:
<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>
Pomocnicy tagów walidacji (<div asp-validation-summary
i <span asp-validation-for
) wyświetlają błędy walidacji. Walidacja zostanie szczegółowo omówiona w dalszej części tej serii.
Pomocnik tagów etykiet (<label asp-for="Movie.Title" class="control-label"></label>
) generuje podpis [for]
i atrybut etykiety dla Title
właściwości.
Pomocnik tagów wejściowych (<input asp-for="Movie.Title" class="form-control">
) używa atrybutów DataAnnotations i tworzy atrybuty HTML wymagane do weryfikacji jQuery po stronie klienta.
Aby uzyskać więcej informacji na temat pomocników tagów, takich jak <form method="post">
, zobacz Pomocnicy tagów w ASP.NET Core.
Następne kroki
Strony Tworzenie, Usuwanie, Szczegóły i Edytowanie
Pages/Movies/Index.cshtml.cs
Sprawdź model strony:
// 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 Strony pochodzą z elementu PageModel
. Zgodnie z konwencją klasa pochodna PageModel
nosi nazwę <PageName>Model
. Konstruktor używa iniekcji zależności, aby dodać element RazorPagesMovieContext
do strony:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Zobacz Kod asynchroniczny, aby uzyskać więcej informacji na temat programowania asynchronicznego w programie Entity Framework.
Po wysłaniu żądania dla strony OnGetAsync
metoda zwraca listę filmów do strony Razor . Razor Na stronie lub OnGet
jest wywoływana w OnGetAsync
celu zainicjowania stanu strony. W tym przypadku OnGetAsync
pobiera listę filmów i wyświetla je.
Gdy OnGet
zwraca void
lub OnGetAsync
zwraca Task
wartość , nie jest używana żadna instrukcja return. Na przykład Privacy strona:
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
Gdy zwracany typ to IActionResult
lub Task<IActionResult>
, należy podać instrukcję return. Na przykład Pages/Movies/Create.cshtml.cs
OnPostAsync
metoda:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Sprawdź stronę Pages/Movies/Index.cshtml
Razor :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movie[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Razor może przejść z kodu HTML do języka C# lub do Razorznaczników specyficznych. Gdy po Razor symbolu @
następuje zastrzeżone słowo kluczowe, przechodzi do znaczników specyficznych dla języka C#. W przeciwnym razie przechodzi do Razorjęzyka C#.
Dyrektywa @page
Dyrektywa @page
Razor sprawia, że plik jest akcją MVC, co oznacza, że może obsługiwać żądania. Dyrektywa @page
musi być pierwszą dyrektywą Razor na stronie. @page
i @model
to przykłady przejścia na Razorznaczniki specyficzne dla języka . Zobacz Razor składnię , aby uzyskać więcej informacji.
Dyrektywa @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
Dyrektywa @model
określa typ modelu przekazanego Razor do strony. W poprzednim przykładzie wiersz sprawia, że @model
klasa pochodna PageModel
jest dostępna dla Razor strony. Model jest używany w pomocnikach @Html.DisplayNameFor
HTML i @Html.DisplayFor
na stronie.
Sprawdź wyrażenie lambda używane w następującym pomocniku HTML:
@Html.DisplayNameFor(model => model.Movie[0].Title)
Pomocnik DisplayNameFor HTML sprawdza Title
właściwość przywoływane w wyrażeniu lambda, aby określić nazwę wyświetlaną. Wyrażenie lambda jest sprawdzane, a nie oceniane. Oznacza to, że nie ma naruszenia dostępu, gdy model
wartość , model.Movie
lub model.Movie[0]
jest pusta null
. Gdy wyrażenie lambda jest obliczane, na przykład przy @Html.DisplayFor(modelItem => item.Title)
użyciu metody , wartości właściwości modelu są oceniane.
Strona układu
Wybierz łącza menu RazorPagesFilm, Homei Privacy. Każda strona zawiera ten sam układ menu. Układ menu jest implementowany w Pages/Shared/_Layout.cshtml
pliku.
Otwórz plik i sprawdź go Pages/Shared/_Layout.cshtml
.
Szablony układów umożliwiają układ kontenera HTML:
- Określone w jednym miejscu.
- Zastosowane na wielu stronach w witrynie.
@RenderBody()
Znajdź wiersz. RenderBody
to symbol zastępczy, w którym są wyświetlane wszystkie widoki specyficzne dla strony, opakowane na stronie układu. Na przykład wybierz Privacy link, a Pages/Privacy.cshtml
widok jest renderowany wewnątrz RenderBody
metody .
ViewData i układ
Rozważ następujące znaczniki z Pages/Movies/Index.cshtml
pliku:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Powyższy wyróżniony znacznik jest przykładem Razor przejścia do języka C#. Znaki {
i }
otaczają blok kodu języka C#.
Klasa PageModel
bazowa zawiera właściwość słownika ViewData
, która może służyć do przekazywania danych do widoku. Obiekty są dodawane do słownika ViewData
przy użyciu wzorca wartości klucza. W poprzednim przykładzie Title
właściwość jest dodawana do słownika ViewData
.
Właściwość Title
jest używana w Pages/Shared/_Layout.cshtml
pliku . Poniższy znacznik przedstawia kilka pierwszych wierszy _Layout.cshtml
pliku.
<!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.*@
Wiersz @*Markup removed for brevity.*@
jest komentarzem Razor . W przeciwieństwie do komentarzy <!-- -->
Razor HTML komentarze nie są wysyłane do klienta. Aby uzyskać więcej informacji, zobacz Dokumentację internetową usługi MDN: Wprowadzenie do języka HTML .
Aktualizowanie układu
<title>
Zmień element w pliku,Pages/Shared/_Layout.cshtml
aby wyświetlić film, a nie RazorPagesPanel.<!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>
Znajdź następujący element zakotwiczenia w
Pages/Shared/_Layout.cshtml
pliku.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Zastąp poprzedni element następującym znacznikiem:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
Poprzedni element kotwicy jest pomocnikem tagów. W tym przypadku jest to pomocnik tagu kotwicy. Atrybut
asp-page="/Movies/Index"
i wartość Pomocnika tagów/Movies/Index
Razor tworzą link do strony. Wartość atrybutuasp-area
jest pusta, więc obszar nie jest używany w linku. Aby uzyskać więcej informacji, zobacz Obszary .Zapisz zmiany i przetestuj aplikację, wybierając link RpFilm . Jeśli masz jakiekolwiek problemy, zobacz plik _Layout.cshtml w usłudze GitHub.
Przetestuj Homełącza , RpFilm, Create, Edit i Delete. Każda strona ustawia tytuł, który można wyświetlić na karcie przeglądarki. Podczas tworzenia zakładek tytuł jest używany dla zakładki.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i formatów dat innych niż angielskie stany USA, należy wykonać kroki w celu globalizacji aplikacji. Zobacz ten problem z usługą GitHub 4076 , aby uzyskać instrukcje dotyczące dodawania przecinka dziesiętnego.
Właściwość Layout
jest ustawiana w Pages/_ViewStart.cshtml
pliku:
@{
Layout = "_Layout";
}
Powyższy znacznik ustawia plik układu na Pages/Shared/_Layout.cshtml
dla wszystkich Razor plików w folderze Pages . Aby uzyskać więcej informacji, zobacz Układ .
Model tworzenia strony
Pages/Movies/Create.cshtml.cs
Sprawdź model strony:
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");
}
}
}
Metoda OnGet
inicjuje dowolny stan wymagany dla strony. Strona Tworzenie nie ma żadnego stanu do zainicjowania, dlatego Page
jest zwracana. W dalszej części samouczka zostanie wyświetlony przykład inicjowania OnGet
stanu. Metoda Page
tworzy PageResult
obiekt renderujący Create.cshtml
stronę.
Właściwość Movie
używa atrybutu [BindProperty], aby wyrazić zgodę na powiązanie modelu. Gdy formularz Tworzenie publikuje wartości formularza, środowisko uruchomieniowe ASP.NET Core wiąże opublikowane wartości z modelem Movie
.
Metoda OnPostAsync
jest uruchamiana, gdy strona publikuje dane formularza:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Jeśli występują jakiekolwiek błędy modelu, formularz jest odtwarzany ponownie wraz z dowolnymi opublikowanymi danymi formularza. Większość błędów modelu można przechwycić po stronie klienta przed opublikowaniem formularza. Przykładem błędu modelu jest opublikowanie wartości pola daty, którego nie można przekonwertować na datę. Walidacja po stronie klienta i walidacja modelu zostały omówione w dalszej części tego samouczka.
Jeśli nie ma żadnych błędów modelu:
- Dane są zapisywane.
- Przeglądarka jest przekierowywana do strony Indeks.
Strona tworzenia Razor
Pages/Movies/Create.cshtml
Razor Sprawdź plik strony:
@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");}
}
Program Visual Studio wyświetla następujące tagi w charakterystycznej czcionki pogrubionej używanej dla pomocników tagów:
<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>
Element <form method="post">
jest pomocnikiem tagu formularza. Pomocnik tagu formularza automatycznie zawiera token antyforgery.
Aparat tworzenia szkieletów tworzy Razor znaczniki dla każdego pola w modelu, z wyjątkiem identyfikatora, podobnego do następującego:
<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>
Pomocnicy tagów walidacji (<div asp-validation-summary
i <span asp-validation-for
) wyświetlają błędy walidacji. Walidacja zostanie szczegółowo omówiona w dalszej części tej serii.
Pomocnik tagów etykiet (<label asp-for="Movie.Title" class="control-label"></label>
) generuje podpis [for]
i atrybut etykiety dla Title
właściwości.
Pomocnik tagów wejściowych (<input asp-for="Movie.Title" class="form-control">
) używa atrybutów DataAnnotations i tworzy atrybuty HTML wymagane do weryfikacji jQuery po stronie klienta.
Aby uzyskać więcej informacji na temat pomocników tagów, takich jak <form method="post">
, zobacz Pomocnicy tagów w ASP.NET Core.