Parte 3, pagine con scaffolding Razor in ASP.NET Core
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere Criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Questa esercitazione esamina le Razor pagine create dallo scaffolding nell'esercitazione precedente.
Pagine di creazione, eliminazione, dettagli e modifica
Esaminare il Pages/Movies/Index.cshtml.cs
modello di pagina:
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 Le pagine sono derivate da PageModel. Per convenzione, la PageModel
classe derivata è denominata PageNameModel
. Ad esempio, la pagina Index è denominata IndexModel
.
Il costruttore usa l'inserimento delle dipendenze per aggiungere alla RazorPagesMovieContext
pagina:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Vedere Codice asincrono per altre informazioni sulla programmazione asincrona con Entity Framework.
Quando viene effettuata una GET
richiesta per la pagina, il OnGetAsync
metodo restituisce un elenco di film nella Razor pagina. In una Razor pagina OnGetAsync
o OnGet
viene chiamato per inizializzare lo stato della pagina. In questo caso, OnGetAsync
ottiene un elenco di filmati e li visualizza.
Quando OnGet
restituisce o OnGetAsync
restituisce void
Task
, non viene utilizzata alcuna istruzione return. Ad esempio, esaminare la 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()
{
}
}
}
Quando il tipo restituito è IActionResult o Task<IActionResult>
, è necessario specificare un'istruzione return. Ad esempio, il Pages/Movies/Create.cshtml.cs OnPostAsync
metodo :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Esaminare la Pages/Movies/Index.cshtml
Razor 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 può passare da HTML a C# o in Razormarkup specifico. Quando un @
simbolo è seguito da una Razor parola chiave riservata, passa a Razormarkup specifico, altrimenti passa a C#.
La direttiva @page
La @page
Razor direttiva rende il file un'azione MVC, il che significa che può gestire le richieste. @page
deve essere la prima direttiva Razor in una pagina. @page
e @model
sono esempi di transizione in Razormarkup specifico. Per altre informazioni, vedere Razor sintassi .
La direttiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
La @model
direttiva specifica il tipo del modello passato alla Razor pagina. Nell'esempio precedente la @model
riga rende la PageModel
classe derivata disponibile per page Razor . Il modello viene usato negli @Html.DisplayNameFor
helper HTML e @Html.DisplayFor
nella pagina.
Esaminare l'espressione lambda usata nell'helper HTML seguente:
@Html.DisplayNameFor(model => model.Movie[0].Title)
L'helper HTML DisplayNameFor controlla la proprietà Title
a cui fa riferimento nell'espressione lambda per determinare il nome visualizzato. L'espressione lambda viene controllata anziché valutata. Ciò significa che non esiste alcuna violazione di accesso quando model
, model.Movie
o model.Movie[0]
è null
o vuoto. Quando l'espressione lambda viene valutata, ad esempio con @Html.DisplayFor(modelItem => item.Title)
, i valori delle proprietà del modello vengono valutati.
Pagina di layout
Selezionare i collegamenti di menu RazorPagesMovie, Homee Privacy. Ogni pagina mostra lo stesso layout di menu. Il layout del Pages/Shared/_Layout.cshtml
menu viene implementato nel file.
Aprire ed esaminare il Pages/Shared/_Layout.cshtml
file.
I modelli Layout consentono di:
- Specificare il layout del contenitore HTML in un'unica posizione.
- Applicare il layout in più pagine del sito.
Trovare la riga @RenderBody()
. RenderBody
è un segnaposto dove tutte le visualizzazioni specifiche della pagina vengono presentate, incapsulate nella pagina di layout. Ad esempio, selezionare il Privacy collegamento e il rendering della Pages/Privacy.cshtml
vista all'interno del RenderBody
metodo .
ViewData e layout
Prendere in considerazione il markup seguente dal Pages/Movies/Index.cshtml
file :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Il markup evidenziato precedente è un esempio di Razor transizione in C#. Tra i caratteri {
e }
è racchiuso un blocco di codice C#.
La PageModel
classe base contiene una ViewData
proprietà del dizionario che può essere utilizzata per passare i dati a una vista. Gli oggetti vengono aggiunti al ViewData
dizionario usando un modello chiave value . Nell'esempio precedente la proprietà Title
viene aggiunta al dizionario ViewData
.
La Title
proprietà viene utilizzata nel Pages/Shared/_Layout.cshtml
file . Il markup seguente mostra le prime righe del _Layout.cshtml
file.
<!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" />
Aggiornare il layout
Modificare l'elemento
<title>
nelPages/Shared/_Layout.cshtml
file in modo da visualizzare Movie anziché 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>
Trovare l'elemento di ancoraggio seguente nel
Pages/Shared/_Layout.cshtml
file .<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Sostituire l'elemento precedente con il markup seguente:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
L'elemento di ancoraggio precedente è un helper tag. In questo caso, si tratta dell'helper tag di ancoraggio. L'attributo
asp-page="/Movies/Index"
helper tag e il valore creano un collegamento alla/Movies/Index
Razor pagina. Poiché il valore dell'attributoasp-area
è vuoto, l'area non viene usata nel collegamento. Per altre informazioni, vedere Aree.Salvare le modifiche e testare l'app selezionando il collegamento RpMovie . In caso di problemi, vedere il file _Layout.cshtml in GitHub.
Testare i Homecollegamenti , RpMovie, Create, Edit e Delete . Ogni pagina imposta il titolo, che è possibile visualizzare nella scheda del browser. Quando si segnalibra una pagina, il titolo viene usato per il segnalibro.
Nota
Potrebbe non essere possibile immettere virgole decimali nel campo Price
. Per supportare la convalida di jQuery per le impostazioni locali non in lingua inglese che usano una virgola (",") per un separatore decimale e per i formati di data non inglese negli Stati Uniti, è necessario eseguire i passaggi per globalizzare l'app. Vedere questo problema 4076 su GitHub per istruzioni sull'aggiunta della virgola decimale.
La Layout
proprietà è impostata nel Pages/_ViewStart.cshtml
file :
@{
Layout = "_Layout";
}
Il markup precedente imposta il file di layout su Pages/Shared/_Layout.cshtml
per tutti i Razor file nella cartella Pages . Vedere Layout per altre informazioni.
Modello di pagina di creazione
Esaminare il modello di Pages/Movies/Create.cshtml.cs
pagina:
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");
}
}
}
Il metodo OnGet
inizializza lo stato necessario per la pagina. La pagina di creazione non possiede uno stato da inizializzare. Viene restituito Page
. Più avanti nell'esercitazione viene visualizzato un esempio di inizializzazione dello stato con OnGet
. Il Page
metodo crea un PageResult
oggetto che esegue il rendering della Create.cshtml
pagina.
La Movie
proprietà usa l'attributo [BindProperty] per acconsentire esplicitamente all'associazione di modelli. Dopo che il modulo di creazione registra i valori, il runtime di ASP.NET Core associa i valori registrati al modello Movie
.
Il metodo OnPostAsync
viene eseguito quando la pagina inserisce i dati del modulo:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se il modello contiene errori, il modulo viene nuovamente visualizzato insieme ai dati del modulo inviati. La maggior parte degli errori del modello sono riscontrabili sul lato client prima che il modulo sia inviato. La registrazione di un valore per il campo data non convertibile in una data è un esempio di errore del modello. Durante l'esercitazione saranno poi trattate nel dettaglio la convalida lato client e la convalida del modello.
Se non sono presenti errori del modello:
- I dati vengono salvati.
- Il browser viene reindirizzato alla pagina Indice.
Pagina Crea Razor
Esaminare il Pages/Movies/Create.cshtml
Razor file di pagina:
@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 visualizza i tag seguenti con un tipo di carattere in grassetto distintivo specifico per gli helper tag:
<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>
L'elemento <form method="post">
è un helper tag del modulo. L'helper tag del modulo include automaticamente un token antifalsificazione.
Il motore di scaffolding crea Razor markup per ogni campo nel modello, ad eccezione dell'ID, simile al seguente:
<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>
Gli helper tag di convalida (<div asp-validation-summary
e <span asp-validation-for
) visualizzano gli errori di convalida. Il tema della convalida viene trattato in modo più dettagliato successivamente in questa serie.
L'helper tag di etichetta (<label asp-for="Movie.Title" class="control-label"></label>
) genera la didascalia dell'etichetta e l'attributo [for]
per la proprietà Title
.
L'helper tag di input (<input asp-for="Movie.Title" class="form-control">
) usa gli attributi DataAnnotations e produce gli attributi HTML necessari per la convalida jQuery sul lato client.
Per altre informazioni sugli helper tag, ad esempio <form method="post">
, vedere Helper tag in ASP.NET Core.
Passaggi successivi
Pagine di creazione, eliminazione, dettagli e modifica
Esaminare il Pages/Movies/Index.cshtml.cs
modello di pagina:
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 Le pagine sono derivate da PageModel. Per convenzione, la PageModel
classe derivata è denominata PageNameModel
. Ad esempio, la pagina Index è denominata IndexModel
.
Il costruttore usa l'inserimento delle dipendenze per aggiungere alla RazorPagesMovieContext
pagina:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Vedere Codice asincrono per altre informazioni sulla programmazione asincrona con Entity Framework.
Quando viene effettuata una GET
richiesta per la pagina, il OnGetAsync
metodo restituisce un elenco di film nella Razor pagina. In una Razor pagina OnGetAsync
o OnGet
viene chiamato per inizializzare lo stato della pagina. In questo caso, OnGetAsync
ottiene un elenco di filmati e li visualizza.
Quando OnGet
restituisce o OnGetAsync
restituisce void
Task
, non viene utilizzata alcuna istruzione return. Ad esempio, esaminare la 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()
{
}
}
}
Quando il tipo restituito è IActionResult o Task<IActionResult>
, è necessario specificare un'istruzione return. Ad esempio, il Pages/Movies/Create.cshtml.cs OnPostAsync
metodo :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Esaminare la Pages/Movies/Index.cshtml
Razor 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 può passare da HTML a C# o in Razormarkup specifico. Quando un @
simbolo è seguito da una Razor parola chiave riservata, passa a Razormarkup specifico, altrimenti passa a C#.
La direttiva @page
La @page
Razor direttiva rende il file un'azione MVC, il che significa che può gestire le richieste. @page
deve essere la prima direttiva Razor in una pagina. @page
e @model
sono esempi di transizione in Razormarkup specifico. Per altre informazioni, vedere Razor sintassi .
La direttiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
La @model
direttiva specifica il tipo del modello passato alla Razor pagina. Nell'esempio precedente la @model
riga rende la PageModel
classe derivata disponibile per page Razor . Il modello viene usato negli @Html.DisplayNameFor
helper HTML e @Html.DisplayFor
nella pagina.
Esaminare l'espressione lambda usata nell'helper HTML seguente:
@Html.DisplayNameFor(model => model.Movie[0].Title)
L'helper HTML DisplayNameFor controlla la proprietà Title
a cui fa riferimento nell'espressione lambda per determinare il nome visualizzato. L'espressione lambda viene controllata anziché valutata. Ciò significa che non esiste alcuna violazione di accesso quando model
, model.Movie
o model.Movie[0]
è null
o vuoto. Quando l'espressione lambda viene valutata, ad esempio con @Html.DisplayFor(modelItem => item.Title)
, i valori delle proprietà del modello vengono valutati.
Pagina di layout
Selezionare i collegamenti di menu RazorPagesMovie, Homee Privacy. Ogni pagina mostra lo stesso layout di menu. Il layout del Pages/Shared/_Layout.cshtml
menu viene implementato nel file.
Aprire ed esaminare il Pages/Shared/_Layout.cshtml
file.
I modelli Layout consentono di:
- Specificare il layout del contenitore HTML in un'unica posizione.
- Applicare il layout in più pagine del sito.
Trovare la riga @RenderBody()
. RenderBody
è un segnaposto dove tutte le visualizzazioni specifiche della pagina vengono presentate, incapsulate nella pagina di layout. Ad esempio, selezionare il Privacy collegamento e il rendering della Pages/Privacy.cshtml
vista all'interno del RenderBody
metodo .
ViewData e layout
Prendere in considerazione il markup seguente dal Pages/Movies/Index.cshtml
file :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Il markup evidenziato precedente è un esempio di Razor transizione in C#. Tra i caratteri {
e }
è racchiuso un blocco di codice C#.
La PageModel
classe base contiene una ViewData
proprietà del dizionario che può essere utilizzata per passare i dati a una vista. Gli oggetti vengono aggiunti al ViewData
dizionario usando un modello chiave value . Nell'esempio precedente la proprietà Title
viene aggiunta al dizionario ViewData
.
La Title
proprietà viene utilizzata nel Pages/Shared/_Layout.cshtml
file . Il markup seguente mostra le prime righe del _Layout.cshtml
file.
<!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" />
Aggiornare il layout
Modificare l'elemento
<title>
nelPages/Shared/_Layout.cshtml
file in modo da visualizzare Movie anziché 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>
Trovare l'elemento di ancoraggio seguente nel
Pages/Shared/_Layout.cshtml
file .<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Sostituire l'elemento precedente con il markup seguente:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
L'elemento di ancoraggio precedente è un helper tag. In questo caso, si tratta dell'helper tag di ancoraggio. L'attributo
asp-page="/Movies/Index"
helper tag e il valore creano un collegamento alla/Movies/Index
Razor pagina. Poiché il valore dell'attributoasp-area
è vuoto, l'area non viene usata nel collegamento. Per altre informazioni, vedere Aree.Salvare le modifiche e testare l'app selezionando il collegamento RpMovie . In caso di problemi, vedere il file _Layout.cshtml in GitHub.
Testare i Homecollegamenti , RpMovie, Create, Edit e Delete . Ogni pagina imposta il titolo, che è possibile visualizzare nella scheda del browser. Quando si segnalibra una pagina, il titolo viene usato per il segnalibro.
Nota
Potrebbe non essere possibile immettere virgole decimali nel campo Price
. Per supportare la convalida di jQuery per le impostazioni locali non in lingua inglese che usano una virgola (",") per un separatore decimale e per i formati di data non inglese negli Stati Uniti, è necessario eseguire i passaggi per globalizzare l'app. Vedere questo problema 4076 su GitHub per istruzioni sull'aggiunta della virgola decimale.
La Layout
proprietà è impostata nel Pages/_ViewStart.cshtml
file :
@{
Layout = "_Layout";
}
Il markup precedente imposta il file di layout su Pages/Shared/_Layout.cshtml
per tutti i Razor file nella cartella Pages . Vedere Layout per altre informazioni.
Modello di pagina di creazione
Esaminare il modello di Pages/Movies/Create.cshtml.cs
pagina:
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");
}
}
}
Il metodo OnGet
inizializza lo stato necessario per la pagina. La pagina di creazione non possiede uno stato da inizializzare. Viene restituito Page
. Più avanti nell'esercitazione viene visualizzato un esempio di inizializzazione dello stato con OnGet
. Il Page
metodo crea un PageResult
oggetto che esegue il rendering della Create.cshtml
pagina.
La Movie
proprietà usa l'attributo [BindProperty] per acconsentire esplicitamente all'associazione di modelli. Dopo che il modulo di creazione registra i valori, il runtime di ASP.NET Core associa i valori registrati al modello Movie
.
Il metodo OnPostAsync
viene eseguito quando la pagina inserisce i dati del modulo:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se il modello contiene errori, il modulo viene nuovamente visualizzato insieme ai dati del modulo inviati. La maggior parte degli errori del modello sono riscontrabili sul lato client prima che il modulo sia inviato. La registrazione di un valore per il campo data non convertibile in una data è un esempio di errore del modello. Durante l'esercitazione saranno poi trattate nel dettaglio la convalida lato client e la convalida del modello.
Se non sono presenti errori del modello:
- I dati vengono salvati.
- Il browser viene reindirizzato alla pagina Indice.
Pagina Crea Razor
Esaminare il Pages/Movies/Create.cshtml
Razor file di pagina:
@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 visualizza i tag seguenti con un tipo di carattere in grassetto distintivo specifico per gli helper tag:
<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>
L'elemento <form method="post">
è un helper tag del modulo. L'helper tag del modulo include automaticamente un token antifalsificazione.
Il motore di scaffolding crea Razor markup per ogni campo nel modello, ad eccezione dell'ID, simile al seguente:
<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>
Gli helper tag di convalida (<div asp-validation-summary
e <span asp-validation-for
) visualizzano gli errori di convalida. Il tema della convalida viene trattato in modo più dettagliato successivamente in questa serie.
L'helper tag di etichetta (<label asp-for="Movie.Title" class="control-label"></label>
) genera la didascalia dell'etichetta e l'attributo [for]
per la proprietà Title
.
L'helper tag di input (<input asp-for="Movie.Title" class="form-control">
) usa gli attributi DataAnnotations e produce gli attributi HTML necessari per la convalida jQuery sul lato client.
Per altre informazioni sugli helper tag, ad esempio <form method="post">
, vedere Helper tag in ASP.NET Core.
Passaggi successivi
Pagine di creazione, eliminazione, dettagli e modifica
Esaminare il Pages/Movies/Index.cshtml.cs
modello di pagina:
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 Le pagine sono derivate da PageModel. Per convenzione, la PageModel
classe derivata è denominata PageNameModel
. Ad esempio, la pagina Index è denominata IndexModel
.
Il costruttore usa l'inserimento delle dipendenze per aggiungere alla RazorPagesMovieContext
pagina:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Vedere Codice asincrono per altre informazioni sulla programmazione asincrona con Entity Framework.
Quando viene effettuata una GET
richiesta per la pagina, il OnGetAsync
metodo restituisce un elenco di film nella Razor pagina. In una Razor pagina OnGetAsync
o OnGet
viene chiamato per inizializzare lo stato della pagina. In questo caso, OnGetAsync
ottiene un elenco di filmati e li visualizza.
Quando OnGet
restituisce o OnGetAsync
restituisce void
Task
, non viene utilizzata alcuna istruzione return. Ad esempio, esaminare la 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()
{
}
}
}
Quando il tipo restituito è IActionResult o Task<IActionResult>
, è necessario specificare un'istruzione return. Ad esempio, il Pages/Movies/Create.cshtml.cs OnPostAsync
metodo :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Esaminare la Pages/Movies/Index.cshtml
Razor 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 può passare da HTML a C# o in Razormarkup specifico. Quando un @
simbolo è seguito da una Razor parola chiave riservata, passa a Razormarkup specifico, altrimenti passa a C#.
La direttiva @page
La @page
Razor direttiva rende il file un'azione MVC, il che significa che può gestire le richieste. @page
deve essere la prima direttiva Razor in una pagina. @page
e @model
sono esempi di transizione in Razormarkup specifico. Per altre informazioni, vedere Razor sintassi .
La direttiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
La @model
direttiva specifica il tipo del modello passato alla Razor pagina. Nell'esempio precedente la @model
riga rende la PageModel
classe derivata disponibile per page Razor . Il modello viene usato negli @Html.DisplayNameFor
helper HTML e @Html.DisplayFor
nella pagina.
Esaminare l'espressione lambda usata nell'helper HTML seguente:
@Html.DisplayNameFor(model => model.Movie[0].Title)
L'helper HTML DisplayNameFor controlla la proprietà Title
a cui fa riferimento nell'espressione lambda per determinare il nome visualizzato. L'espressione lambda viene controllata anziché valutata. Ciò significa che non esiste alcuna violazione di accesso quando model
, model.Movie
o model.Movie[0]
è null
o vuoto. Quando l'espressione lambda viene valutata, ad esempio con @Html.DisplayFor(modelItem => item.Title)
, i valori delle proprietà del modello vengono valutati.
Pagina di layout
Selezionare i collegamenti di menu RazorPagesMovie, Homee Privacy. Ogni pagina mostra lo stesso layout di menu. Il layout del Pages/Shared/_Layout.cshtml
menu viene implementato nel file.
Aprire ed esaminare il Pages/Shared/_Layout.cshtml
file.
I modelli Layout consentono di:
- Specificare il layout del contenitore HTML in un'unica posizione.
- Applicare il layout in più pagine del sito.
Trovare la riga @RenderBody()
. RenderBody
è un segnaposto dove tutte le visualizzazioni specifiche della pagina vengono presentate, incapsulate nella pagina di layout. Ad esempio, selezionare il Privacy collegamento e il rendering della Pages/Privacy.cshtml
vista all'interno del RenderBody
metodo .
ViewData e layout
Prendere in considerazione il markup seguente dal Pages/Movies/Index.cshtml
file :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Il markup evidenziato precedente è un esempio di Razor transizione in C#. Tra i caratteri {
e }
è racchiuso un blocco di codice C#.
La PageModel
classe base contiene una ViewData
proprietà del dizionario che può essere utilizzata per passare i dati a una vista. Gli oggetti vengono aggiunti al ViewData
dizionario usando un modello chiave value . Nell'esempio precedente la proprietà Title
viene aggiunta al dizionario ViewData
.
La Title
proprietà viene utilizzata nel Pages/Shared/_Layout.cshtml
file . Il markup seguente mostra le prime righe del _Layout.cshtml
file.
<!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" />
La riga @*Markup removed for brevity.*@
è un Razor commento. A differenza dei commenti <!-- -->
HTML, Razor i commenti non vengono inviati al client. Per altre informazioni, vedere la documentazione Web MDN: Introduzione al codice HTML .
Aggiornare il layout
Modificare l'elemento
<title>
nelPages/Shared/_Layout.cshtml
file in modo da visualizzare Movie anziché 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>
Trovare l'elemento di ancoraggio seguente nel
Pages/Shared/_Layout.cshtml
file .<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Sostituire l'elemento precedente con il markup seguente:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
L'elemento di ancoraggio precedente è un helper tag. In questo caso, si tratta dell'helper tag di ancoraggio. L'attributo
asp-page="/Movies/Index"
helper tag e il valore creano un collegamento alla/Movies/Index
Razor pagina. Poiché il valore dell'attributoasp-area
è vuoto, l'area non viene usata nel collegamento. Per altre informazioni, vedere Aree.Salvare le modifiche e testare l'app selezionando il collegamento RpMovie . In caso di problemi, vedere il file _Layout.cshtml in GitHub.
Testare i Homecollegamenti , RpMovie, Create, Edit e Delete . Ogni pagina imposta il titolo, che è possibile visualizzare nella scheda del browser. Quando si segnalibra una pagina, il titolo viene usato per il segnalibro.
Nota
Potrebbe non essere possibile immettere virgole decimali nel campo Price
. Per supportare la convalida di jQuery per le impostazioni locali non in lingua inglese che usano una virgola (",") per un separatore decimale e per i formati di data non inglese negli Stati Uniti, è necessario eseguire i passaggi per globalizzare l'app. Vedere questo problema 4076 su GitHub per istruzioni sull'aggiunta della virgola decimale.
La Layout
proprietà è impostata nel Pages/_ViewStart.cshtml
file :
@{
Layout = "_Layout";
}
Il markup precedente imposta il file di layout su Pages/Shared/_Layout.cshtml
per tutti i Razor file nella cartella Pages . Vedere Layout per altre informazioni.
Modello di pagina di creazione
Esaminare il modello di Pages/Movies/Create.cshtml.cs
pagina:
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");
}
}
}
Il metodo OnGet
inizializza lo stato necessario per la pagina. La pagina di creazione non possiede uno stato da inizializzare. Viene restituito Page
. Più avanti nell'esercitazione viene visualizzato un esempio di inizializzazione dello stato con OnGet
. Il Page
metodo crea un PageResult
oggetto che esegue il rendering della Create.cshtml
pagina.
La Movie
proprietà usa l'attributo [BindProperty] per acconsentire esplicitamente all'associazione di modelli. Dopo che il modulo di creazione registra i valori, il runtime di ASP.NET Core associa i valori registrati al modello Movie
.
Il metodo OnPostAsync
viene eseguito quando la pagina inserisce i dati del modulo:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se il modello contiene errori, il modulo viene nuovamente visualizzato insieme ai dati del modulo inviati. La maggior parte degli errori del modello sono riscontrabili sul lato client prima che il modulo sia inviato. La registrazione di un valore per il campo data non convertibile in una data è un esempio di errore del modello. Durante l'esercitazione saranno poi trattate nel dettaglio la convalida lato client e la convalida del modello.
Se non sono presenti errori del modello:
- I dati vengono salvati.
- Il browser viene reindirizzato alla pagina Indice.
Pagina Crea Razor
Esaminare il Pages/Movies/Create.cshtml
Razor file di pagina:
@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 visualizza i tag seguenti con un tipo di carattere in grassetto distintivo specifico per gli helper tag:
<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>
L'elemento <form method="post">
è un helper tag del modulo. L'helper tag del modulo include automaticamente un token antifalsificazione.
Il motore di scaffolding crea Razor markup per ogni campo nel modello, ad eccezione dell'ID, simile al seguente:
<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>
Gli helper tag di convalida (<div asp-validation-summary
e <span asp-validation-for
) visualizzano gli errori di convalida. Il tema della convalida viene trattato in modo più dettagliato successivamente in questa serie.
L'helper tag di etichetta (<label asp-for="Movie.Title" class="control-label"></label>
) genera la didascalia dell'etichetta e l'attributo [for]
per la proprietà Title
.
L'helper tag di input (<input asp-for="Movie.Title" class="form-control">
) usa gli attributi DataAnnotations e produce gli attributi HTML necessari per la convalida jQuery sul lato client.
Per altre informazioni sugli helper tag, ad esempio <form method="post">
, vedere Helper tag in ASP.NET Core.
Passaggi successivi
Pagine di creazione, eliminazione, dettagli e modifica
Esaminare il Pages/Movies/Index.cshtml.cs
modello di pagina:
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 Le pagine sono derivate da PageModel. Per convenzione, la PageModel
classe derivata è denominata PageNameModel
. Ad esempio, la pagina Index è denominata IndexModel
.
Il costruttore usa l'inserimento delle dipendenze per aggiungere alla RazorPagesMovieContext
pagina:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Vedere Codice asincrono per altre informazioni sulla programmazione asincrona con Entity Framework.
Quando viene effettuata una richiesta per la pagina, il OnGetAsync
metodo restituisce un elenco di film nella Razor pagina. In una Razor pagina OnGetAsync
o OnGet
viene chiamato per inizializzare lo stato della pagina. In questo caso, OnGetAsync
ottiene un elenco di filmati e li visualizza.
Quando OnGet
restituisce o OnGetAsync
restituisce void
Task
, non viene utilizzata alcuna istruzione return. Ad esempio, esaminare la 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()
{
}
}
}
Quando il tipo restituito è IActionResult o Task<IActionResult>
, è necessario specificare un'istruzione return. Ad esempio, il Pages/Movies/Create.cshtml.cs
OnPostAsync
metodo :
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");
}
Esaminare la Pages/Movies/Index.cshtml
Razor 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 può passare da HTML a C# o in Razormarkup specifico. Quando un @
simbolo è seguito da una Razor parola chiave riservata, passa a Razormarkup specifico, altrimenti passa a C#.
La direttiva @page
La @page
Razor direttiva rende il file un'azione MVC, il che significa che può gestire le richieste. @page
deve essere la prima direttiva Razor in una pagina. @page
e @model
sono esempi di transizione in Razormarkup specifico. Per altre informazioni, vedere Razor sintassi .
La direttiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
La @model
direttiva specifica il tipo del modello passato alla Razor pagina. Nell'esempio precedente la @model
riga rende la PageModel
classe derivata disponibile per page Razor . Il modello viene usato negli @Html.DisplayNameFor
helper HTML e @Html.DisplayFor
nella pagina.
Esaminare l'espressione lambda usata nell'helper HTML seguente:
@Html.DisplayNameFor(model => model.Movie[0].Title)
L'helper HTML DisplayNameFor controlla la proprietà Title
a cui fa riferimento nell'espressione lambda per determinare il nome visualizzato. L'espressione lambda viene controllata anziché valutata. Ciò significa che non esiste alcuna violazione di accesso quando model
, model.Movie
o model.Movie[0]
è null
o vuoto. Quando l'espressione lambda viene valutata, ad esempio con @Html.DisplayFor(modelItem => item.Title)
, i valori delle proprietà del modello vengono valutati.
Pagina di layout
Selezionare i collegamenti di menu RazorPagesMovie, Homee Privacy. Ogni pagina mostra lo stesso layout di menu. Il layout del Pages/Shared/_Layout.cshtml
menu viene implementato nel file.
Aprire ed esaminare il Pages/Shared/_Layout.cshtml
file.
I modelli Layout consentono di:
- Specificare il layout del contenitore HTML in un'unica posizione.
- Applicare il layout in più pagine del sito.
Trovare la riga @RenderBody()
. RenderBody
è un segnaposto dove tutte le visualizzazioni specifiche della pagina vengono presentate, incapsulate nella pagina di layout. Ad esempio, selezionare il Privacy collegamento e il rendering della Pages/Privacy.cshtml
vista all'interno del RenderBody
metodo .
ViewData e layout
Prendere in considerazione il markup seguente dal Pages/Movies/Index.cshtml
file :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Il markup evidenziato precedente è un esempio di Razor transizione in C#. Tra i caratteri {
e }
è racchiuso un blocco di codice C#.
La PageModel
classe base contiene una ViewData
proprietà del dizionario che può essere utilizzata per passare i dati a una vista. Gli oggetti vengono aggiunti al ViewData
dizionario usando un modello chiave value . Nell'esempio precedente la proprietà Title
viene aggiunta al dizionario ViewData
.
La Title
proprietà viene utilizzata nel Pages/Shared/_Layout.cshtml
file . Il markup seguente mostra le prime righe del _Layout.cshtml
file.
<!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" />
La riga @*Markup removed for brevity.*@
è un Razor commento. A differenza dei commenti <!-- -->
HTML, Razor i commenti non vengono inviati al client. Per altre informazioni, vedere la documentazione Web MDN: Introduzione al codice HTML .
Aggiornare il layout
Modificare l'elemento
<title>
nelPages/Shared/_Layout.cshtml
file in modo da visualizzare Movie anziché 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>
Trovare l'elemento di ancoraggio seguente nel
Pages/Shared/_Layout.cshtml
file .<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Sostituire l'elemento precedente con il markup seguente:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
L'elemento di ancoraggio precedente è un helper tag. In questo caso, si tratta dell'helper tag di ancoraggio. L'attributo
asp-page="/Movies/Index"
helper tag e il valore creano un collegamento alla/Movies/Index
Razor pagina. Poiché il valore dell'attributoasp-area
è vuoto, l'area non viene usata nel collegamento. Per altre informazioni, vedere Aree.Salvare le modifiche e testare l'app selezionando il collegamento RpMovie . In caso di problemi, vedere il file _Layout.cshtml in GitHub.
Testare i Homecollegamenti , RpMovie, Create, Edit e Delete . Ogni pagina imposta il titolo, che è possibile visualizzare nella scheda del browser. Quando si segnalibra una pagina, il titolo viene usato per il segnalibro.
Nota
Potrebbe non essere possibile immettere virgole decimali nel campo Price
. Per supportare la convalida di jQuery per le impostazioni locali non in lingua inglese che usano una virgola (",") per un separatore decimale e per i formati di data non inglese negli Stati Uniti, è necessario eseguire i passaggi per globalizzare l'app. Vedere questo problema 4076 su GitHub per istruzioni sull'aggiunta della virgola decimale.
La Layout
proprietà è impostata nel Pages/_ViewStart.cshtml
file :
@{
Layout = "_Layout";
}
Il markup precedente imposta il file di layout su Pages/Shared/_Layout.cshtml
per tutti i Razor file nella cartella Pages . Vedere Layout per altre informazioni.
Modello di pagina di creazione
Esaminare il modello di Pages/Movies/Create.cshtml.cs
pagina:
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");
}
}
}
Il metodo OnGet
inizializza lo stato necessario per la pagina. La pagina di creazione non possiede uno stato da inizializzare. Viene restituito Page
. Più avanti nell'esercitazione viene visualizzato un esempio di inizializzazione dello stato con OnGet
. Il Page
metodo crea un PageResult
oggetto che esegue il rendering della Create.cshtml
pagina.
La Movie
proprietà usa l'attributo [BindProperty] per acconsentire esplicitamente all'associazione di modelli. Dopo che il modulo di creazione registra i valori, il runtime di ASP.NET Core associa i valori registrati al modello Movie
.
Il metodo OnPostAsync
viene eseguito quando la pagina inserisce i dati del modulo:
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");
}
Se il modello contiene errori, il modulo viene nuovamente visualizzato insieme ai dati del modulo inviati. La maggior parte degli errori del modello sono riscontrabili sul lato client prima che il modulo sia inviato. La registrazione di un valore per il campo data non convertibile in una data è un esempio di errore del modello. Durante l'esercitazione saranno poi trattate nel dettaglio la convalida lato client e la convalida del modello.
Se non sono presenti errori del modello:
- I dati vengono salvati.
- Il browser viene reindirizzato alla pagina Indice.
Pagina Crea Razor
Esaminare il Pages/Movies/Create.cshtml
Razor file di pagina:
@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 visualizza i tag seguenti con un tipo di carattere in grassetto distintivo specifico per gli helper tag:
<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>
L'elemento <form method="post">
è un helper tag del modulo. L'helper tag del modulo include automaticamente un token antifalsificazione.
Il motore di scaffolding crea Razor markup per ogni campo nel modello, ad eccezione dell'ID, simile al seguente:
<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>
Gli helper tag di convalida (<div asp-validation-summary
e <span asp-validation-for
) visualizzano gli errori di convalida. Il tema della convalida viene trattato in modo più dettagliato successivamente in questa serie.
L'helper tag di etichetta (<label asp-for="Movie.Title" class="control-label"></label>
) genera la didascalia dell'etichetta e l'attributo [for]
per la proprietà Title
.
L'helper tag di input (<input asp-for="Movie.Title" class="form-control">
) usa gli attributi DataAnnotations e produce gli attributi HTML necessari per la convalida jQuery sul lato client.
Per altre informazioni sugli helper tag, ad esempio <form method="post">
, vedere Helper tag in ASP.NET Core.
Passaggi successivi
Pagine di creazione, eliminazione, dettagli e modifica
Esaminare il Pages/Movies/Index.cshtml.cs
modello di pagina:
// 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 Le pagine sono derivate da PageModel
. Per convenzione, la PageModel
classe derivata da è denominata <PageName>Model
. Il costruttore usa l'inserimento delle dipendenze per aggiungere alla RazorPagesMovieContext
pagina:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Vedere Codice asincrono per altre informazioni sulla programmazione asincrona con Entity Framework.
Quando viene effettuata una richiesta per la pagina, il OnGetAsync
metodo restituisce un elenco di film nella Razor pagina. In una Razor pagina OnGetAsync
o OnGet
viene chiamato per inizializzare lo stato della pagina. In questo caso, OnGetAsync
ottiene un elenco di filmati e li visualizza.
Quando OnGet
restituisce o OnGetAsync
restituisce void
Task
, non viene utilizzata alcuna istruzione return. Ad esempio, pagina Privacy :
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
Quando il tipo restituito è IActionResult
o Task<IActionResult>
, è necessario specificare un'istruzione return. Ad esempio, il Pages/Movies/Create.cshtml.cs
OnPostAsync
metodo :
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Esaminare la Pages/Movies/Index.cshtml
Razor 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 può passare da HTML a C# o in Razormarkup specifico. Quando un @
simbolo è seguito da una Razor parola chiave riservata, passa a Razormarkup specifico, altrimenti passa a C#.
La direttiva @page
La @page
Razor direttiva rende il file un'azione MVC, il che significa che può gestire le richieste. @page
deve essere la prima direttiva Razor in una pagina. @page
e @model
sono esempi di transizione in Razormarkup specifico. Per altre informazioni, vedere Razor sintassi .
La direttiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
La @model
direttiva specifica il tipo del modello passato alla Razor pagina. Nell'esempio precedente, la @model
riga rende la PageModel
classe derivata da disponibile per page Razor . Il modello viene usato negli @Html.DisplayNameFor
helper HTML e @Html.DisplayFor
nella pagina.
Esaminare l'espressione lambda usata nell'helper HTML seguente:
@Html.DisplayNameFor(model => model.Movie[0].Title)
L'helper HTML DisplayNameFor controlla la proprietà Title
a cui fa riferimento nell'espressione lambda per determinare il nome visualizzato. L'espressione lambda viene controllata anziché valutata. Ciò significa che non esiste alcuna violazione di accesso quando model
, model.Movie
o model.Movie[0]
è null
o vuoto. Quando l'espressione lambda viene valutata, ad esempio con @Html.DisplayFor(modelItem => item.Title)
, i valori delle proprietà del modello vengono valutati.
Pagina di layout
Selezionare i collegamenti di menu RazorPagesMovie, Homee Privacy. Ogni pagina mostra lo stesso layout di menu. Il layout del Pages/Shared/_Layout.cshtml
menu viene implementato nel file.
Aprire ed esaminare il Pages/Shared/_Layout.cshtml
file.
I modelli Layout consentono di:
- Specificare il layout del contenitore HTML in un'unica posizione.
- Applicare il layout in più pagine del sito.
Trovare la riga @RenderBody()
. RenderBody
è un segnaposto dove tutte le visualizzazioni specifiche della pagina vengono presentate, incapsulate nella pagina di layout. Ad esempio, selezionare il Privacy collegamento e il rendering della Pages/Privacy.cshtml
vista all'interno del RenderBody
metodo .
ViewData e layout
Prendere in considerazione il markup seguente dal Pages/Movies/Index.cshtml
file :
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
Il markup evidenziato precedente è un esempio di Razor transizione in C#. Tra i caratteri {
e }
è racchiuso un blocco di codice C#.
La PageModel
classe base contiene una ViewData
proprietà del dizionario che può essere utilizzata per passare i dati a una vista. Gli oggetti vengono aggiunti al ViewData
dizionario usando un modello chiave value . Nell'esempio precedente la proprietà Title
viene aggiunta al dizionario ViewData
.
La Title
proprietà viene utilizzata nel Pages/Shared/_Layout.cshtml
file . Il markup seguente mostra le prime righe del _Layout.cshtml
file.
<!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.*@
La riga @*Markup removed for brevity.*@
è un Razor commento. A differenza dei commenti <!-- -->
HTML, Razor i commenti non vengono inviati al client. Per altre informazioni, vedere la documentazione Web MDN: Introduzione al codice HTML .
Aggiornare il layout
Modificare l'elemento
<title>
nelPages/Shared/_Layout.cshtml
file in modo da visualizzare Movie anziché 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>
Trovare l'elemento di ancoraggio seguente nel
Pages/Shared/_Layout.cshtml
file .<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Sostituire l'elemento precedente con il markup seguente:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
L'elemento di ancoraggio precedente è un helper tag. In questo caso, si tratta dell'helper tag di ancoraggio. L'attributo
asp-page="/Movies/Index"
helper tag e il valore creano un collegamento alla/Movies/Index
Razor pagina. Poiché il valore dell'attributoasp-area
è vuoto, l'area non viene usata nel collegamento. Per altre informazioni, vedere Aree.Salvare le modifiche e testare l'app selezionando il collegamento RpMovie . In caso di problemi, vedere il file _Layout.cshtml in GitHub.
Testare i Homecollegamenti , RpMovie, Create, Edit e Delete . Ogni pagina imposta il titolo, che è possibile visualizzare nella scheda del browser. Quando si segnalibra una pagina, il titolo viene usato per il segnalibro.
Nota
Potrebbe non essere possibile immettere virgole decimali nel campo Price
. Per supportare la convalida di jQuery per le impostazioni locali non in lingua inglese che usano una virgola (",") per un separatore decimale e per i formati di data non inglese negli Stati Uniti, è necessario eseguire i passaggi per globalizzare l'app. Vedere questo problema 4076 su GitHub per istruzioni sull'aggiunta della virgola decimale.
La Layout
proprietà è impostata nel Pages/_ViewStart.cshtml
file :
@{
Layout = "_Layout";
}
Il markup precedente imposta il file di layout su Pages/Shared/_Layout.cshtml
per tutti i Razor file nella cartella Pages . Vedere Layout per altre informazioni.
Modello di pagina di creazione
Esaminare il modello di Pages/Movies/Create.cshtml.cs
pagina:
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");
}
}
}
Il metodo OnGet
inizializza lo stato necessario per la pagina. La pagina di creazione non possiede uno stato da inizializzare. Viene restituito Page
. Più avanti nell'esercitazione viene visualizzato un esempio di inizializzazione dello stato con OnGet
. Il Page
metodo crea un PageResult
oggetto che esegue il rendering della Create.cshtml
pagina.
La Movie
proprietà usa l'attributo [BindProperty] per acconsentire esplicitamente all'associazione di modelli. Dopo che il modulo di creazione registra i valori, il runtime di ASP.NET Core associa i valori registrati al modello Movie
.
Il metodo OnPostAsync
viene eseguito quando la pagina inserisce i dati del modulo:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se il modello contiene errori, il modulo viene nuovamente visualizzato insieme ai dati del modulo inviati. La maggior parte degli errori del modello sono riscontrabili sul lato client prima che il modulo sia inviato. La registrazione di un valore per il campo data non convertibile in una data è un esempio di errore del modello. Durante l'esercitazione saranno poi trattate nel dettaglio la convalida lato client e la convalida del modello.
Se non sono presenti errori del modello:
- I dati vengono salvati.
- Il browser viene reindirizzato alla pagina Indice.
Pagina Crea Razor
Esaminare il Pages/Movies/Create.cshtml
Razor file di pagina:
@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 visualizza i tag seguenti con un tipo di carattere in grassetto distintivo specifico per gli helper tag:
<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>
L'elemento <form method="post">
è un helper tag del modulo. L'helper tag del modulo include automaticamente un token antifalsificazione.
Il motore di scaffolding crea Razor markup per ogni campo nel modello, ad eccezione dell'ID, simile al seguente:
<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>
Gli helper tag di convalida (<div asp-validation-summary
e <span asp-validation-for
) visualizzano gli errori di convalida. Il tema della convalida viene trattato in modo più dettagliato successivamente in questa serie.
L'helper tag di etichetta (<label asp-for="Movie.Title" class="control-label"></label>
) genera la didascalia dell'etichetta e l'attributo [for]
per la proprietà Title
.
L'helper tag di input (<input asp-for="Movie.Title" class="form-control">
) usa gli attributi DataAnnotations e produce gli attributi HTML necessari per la convalida jQuery sul lato client.
Per altre informazioni sugli helper tag, ad esempio <form method="post">
, vedere Helper tag in ASP.NET Core.