Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
Por Rick Anderson
Este tutorial examina as Razor Páginas criadas por andaimes no tutorial anterior.
As páginas Criar, Apagar, Detalhes e Editar
Examine o Modelo da Página Pages/Movies/Index.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor As páginas são derivadas de PageModel. Por convenção, a classe derivada PageModel é denominada PageNameModel. Por exemplo, a página Índice tem o nome IndexModel.
O construtor usa a injeção de dependência para adicionar o RazorPagesMovieContext à página:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Consulte Código assíncrono para obter mais informações sobre programação assíncrona com o Entity Framework.
Quando uma GET solicitação é feita para a página, o OnGetAsync método retorna uma lista de filmes para a Razor página. Em uma Página Razor, é chamado OnGetAsync ou OnGet para inicializar o estado da página. Neste caso, OnGetAsync obtém uma lista de filmes e exibe-os.
Quando OnGet retorna void ou OnGetAsync retorna Task, nenhuma instrução de retorno é usada. Por exemplo, verifique a Privacy Página:
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 o tipo de retorno é IActionResult ou Task<IActionResult>, uma declaração de retorno deve ser fornecida. Por exemplo, o Pages/Movies/Create.cshtml.cs OnPostAsync método:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Examine a Pages/Movies/Index.cshtmlRazor página:
@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 pode fazer a transição de HTML para C# ou para Razormarcação específica. Quando um @ símbolo é seguido por uma Razor palavra-chave reservada, transita para a marcação específica de Razor, caso contrário, para C#.
A @page diretiva
A @pageRazor diretiva torna o arquivo uma ação MVC, o que significa que ele pode lidar com solicitações.
@page deve ser a primeira Razor diretiva numa página.
@page e @model são exemplos de transição para Razor marcações específicas. Consulte Razor sintaxe para obter mais informações.
A @model diretiva
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A @model diretiva especifica o tipo do modelo passado para a Razor Página. No exemplo anterior, a @model linha disponibiliza a classe derivada PageModel para a Razor Page. O modelo é usado no @Html.DisplayNameFor e @Html.DisplayForHTML Helpers na página.
Examine a expressão lambda usada no seguinte HTML Helper:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O DisplayNameFor HTML Helper inspeciona a Title propriedade referenciada na expressão lambda para determinar o nome para exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há violação de acesso quando model, model.Movie, ou model.Movie[0] é null ou está vazio. Quando a expressão lambda é avaliada, por exemplo, com @Html.DisplayFor(modelItem => item.Title), os valores de propriedade do modelo são avaliados.
A página de layout
Selecione os links de menu RazorPagesMovie, Homee Privacy. Cada página mostra o mesmo layout de menu. O layout do menu Pages/Shared/_Layout.cshtml é implementado no ficheiro.
Abra e examine o Pages/Shared/_Layout.cshtml arquivo.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado num só lugar.
- Aplicado em várias páginas do site.
Encontre a @RenderBody() linha.
RenderBody é um espaço reservado onde todas as visualizações específicas da página aparecem, encapsuladas na página de layout. Por exemplo, selecione o Privacy link e a Pages/Privacy.cshtml exibição é renderizada dentro do RenderBody método.
ViewData e layout
Considere a seguinte marcação do Pages/Movies/Index.cshtml arquivo:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação destacada anteriormente é um exemplo de Razor a transitar para C#. Os { caracteres e } incluem um bloco de código C#.
A PageModel classe base contém uma ViewData propriedade de dicionário que pode ser usada para passar dados para um View. Os objetos são adicionados ao ViewData dicionário usando um padrão de valor de chave . No exemplo anterior, a propriedade Title é adicionada ao dicionário ViewData.
A Title propriedade é usada no Pages/Shared/_Layout.cshtml arquivo. A marcação a seguir mostra as primeiras linhas do _Layout.cshtml arquivo.
<!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" />
Atualizar o layout
Altere o
<title>elemento doPages/Shared/_Layout.cshtmlficheiro para exibir Movie em vez de 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>Encontre o seguinte elemento âncora no
Pages/Shared/_Layout.cshtmlarquivo.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Substitua o elemento anterior pela seguinte marcação:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>O elemento âncora anterior é um Tag Helper. Neste caso, é o Anchor Tag Helper. O atributo Tag Helper e o seu valor criam um link para a Página
asp-page="/Movies/Index"/Movies/Index. Oasp-areavalor do atributo está vazio, portanto, a área não é usada no link. Consulte Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie . Consulte o arquivo _Layout.cshtml no GitHub se tiver algum problema.
Teste os Homelinks , RpMovie, Criar, Editar e Apagar. Cada página define o título, que você pode ver na guia do navegador. Quando você marca uma página, o título é usado para o marcador.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price. Para dar suporte à validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e formatos de data não US-English, você deve tomar medidas para globalizar o aplicativo. Consulte esta edição 4076 do GitHub para obter instruções sobre como adicionar vírgula decimal.
A Layout propriedade é definida no Pages/_ViewStart.cshtml arquivo:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout para Pages/Shared/_Layout.cshtml todos os Razor arquivos na pasta Páginas . Consulte Layout para obter mais informações.
O modelo Criar página
Examine o modelo da página Pages/Movies/Create.cshtml.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
O OnGet método inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, portanto, Page é retornada. Mais adiante no tutorial, um exemplo de estado de OnGet inicialização é mostrado. O Page método cria um PageResult objeto que renderiza a Create.cshtml página.
A Movie propriedade usa o atributo [BindProperty] para aceitar a vinculação de modelo. Quando o formulário Create envia os valores do formulário, o tempo de execução do ASP.NET Core vincula os valores enviados ao modelo Movie.
O OnPostAsync método é executado quando a página posta dados de formulário:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se houver algum erro de modelo, o formulário será reexibido, juntamente com todos os dados do formulário postados. A maioria dos erros de modelo pode ser detetada no lado do cliente antes que o formulário seja lançado. Um exemplo de erro de modelo é lançar um valor para o campo de data que não pode ser convertido em uma data. A validação do lado do cliente e a validação do modelo são discutidas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são guardados.
- O navegador é redirecionado para a página Índice.
A página de Criação Razor
Verifique o ficheiro de página Pages/Movies/Create.cshtmlRazor.
@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 exibe as seguintes tags em uma fonte distinta em negrito usada nos Auxiliares de 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>
O <form method="post"> elemento é um Form Tag Helper. O Form Tag Helper inclui automaticamente um token antifalsificação.
O motor de andaimes cria Razor marcação para cada campo no modelo, exceto o ID, semelhante ao seguinte:
<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>
Os Auxiliares de Tag de Validação (<div asp-validation-summary e <span asp-validation-for) exibem erros de validação. A validação será abordada mais detalhadamente mais adiante nesta série.
O Auxiliar de Etiquetas para Rótulos (<label asp-for="Movie.Title" class="control-label"></label>) gera a legenda do rótulo e o atributo para a [for] propriedade.
O Input Tag Helper (<input asp-for="Movie.Title" class="form-control">) usa os atributos DataAnnotations e produz atributos HTML necessários para a Validação do jQuery no lado do cliente.
Para obter mais informações sobre Ajudantes de tag, como <form method="post">, consulte Auxiliares de tag no ASP.NET Core.
Próximos passos
As páginas Criar, Apagar, Detalhes e Editar
Examine o Modelo da Página Pages/Movies/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor As páginas são derivadas de PageModel. Por convenção, a classe derivada PageModel é denominada PageNameModel. Por exemplo, a página Índice tem o nome IndexModel.
O construtor usa a injeção de dependência para adicionar o RazorPagesMovieContext à página:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Consulte Código assíncrono para obter mais informações sobre programação assíncrona com o Entity Framework.
Quando uma GET solicitação é feita para a página, o OnGetAsync método retorna uma lista de filmes para a Razor página. Em uma Página Razor, é chamado OnGetAsync ou OnGet para inicializar o estado da página. Neste caso, OnGetAsync obtém uma lista de filmes e exibe-os.
Quando OnGet retorna void ou OnGetAsync retorna Task, nenhuma instrução de retorno é usada. Por exemplo, verifique a Privacy Página:
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 o tipo de retorno é IActionResult ou Task<IActionResult>, uma declaração de retorno deve ser fornecida. Por exemplo, o Pages/Movies/Create.cshtml.cs OnPostAsync método:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Examine a Pages/Movies/Index.cshtmlRazor página:
@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 pode fazer a transição de HTML para C# ou para Razormarcação específica. Quando um @ símbolo é seguido por uma Razor palavra-chave reservada, transita para a marcação específica de Razor, caso contrário, para C#.
A @page diretiva
A @pageRazor diretiva torna o arquivo uma ação MVC, o que significa que ele pode lidar com solicitações.
@page deve ser a primeira Razor diretiva numa página.
@page e @model são exemplos de transição para Razor marcações específicas. Consulte Razor sintaxe para obter mais informações.
A @model diretiva
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A @model diretiva especifica o tipo do modelo passado para a Razor Página. No exemplo anterior, a @model linha disponibiliza a classe derivada PageModel para a Razor Page. O modelo é usado no @Html.DisplayNameFor e @Html.DisplayForHTML Helpers na página.
Examine a expressão lambda usada no seguinte HTML Helper:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O DisplayNameFor HTML Helper inspeciona a Title propriedade referenciada na expressão lambda para determinar o nome para exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há violação de acesso quando model, model.Movie, ou model.Movie[0] é null ou está vazio. Quando a expressão lambda é avaliada, por exemplo, com @Html.DisplayFor(modelItem => item.Title), os valores de propriedade do modelo são avaliados.
A página de layout
Selecione os links de menu RazorPagesMovie, Homee Privacy. Cada página mostra o mesmo layout de menu. O layout do menu Pages/Shared/_Layout.cshtml é implementado no ficheiro.
Abra e examine o Pages/Shared/_Layout.cshtml arquivo.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado num só lugar.
- Aplicado em várias páginas do site.
Encontre a @RenderBody() linha.
RenderBody é um espaço reservado onde todas as visualizações específicas da página aparecem, encapsuladas na página de layout. Por exemplo, selecione o Privacy link e a Pages/Privacy.cshtml exibição é renderizada dentro do RenderBody método.
ViewData e layout
Considere a seguinte marcação do Pages/Movies/Index.cshtml arquivo:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação destacada anteriormente é um exemplo de Razor a transitar para C#. Os { caracteres e } incluem um bloco de código C#.
A PageModel classe base contém uma ViewData propriedade de dicionário que pode ser usada para passar dados para um View. Os objetos são adicionados ao ViewData dicionário usando um padrão de valor de chave . No exemplo anterior, a propriedade Title é adicionada ao dicionário ViewData.
A Title propriedade é usada no Pages/Shared/_Layout.cshtml arquivo. A marcação a seguir mostra as primeiras linhas do _Layout.cshtml arquivo.
<!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" />
Atualizar o layout
Altere o
<title>elemento doPages/Shared/_Layout.cshtmlficheiro para exibir Movie em vez de 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>Encontre o seguinte elemento âncora no
Pages/Shared/_Layout.cshtmlarquivo.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Substitua o elemento anterior pela seguinte marcação:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>O elemento âncora anterior é um Tag Helper. Neste caso, é o Anchor Tag Helper. O atributo Tag Helper e o seu valor criam um link para a Página
asp-page="/Movies/Index"/Movies/Index. Oasp-areavalor do atributo está vazio, portanto, a área não é usada no link. Consulte Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie . Consulte o arquivo _Layout.cshtml no GitHub se tiver algum problema.
Teste os Homelinks , RpMovie, Criar, Editar e Apagar. Cada página define o título, que você pode ver na guia do navegador. Quando você marca uma página, o título é usado para o marcador.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price. Para dar suporte à validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e formatos de data não US-English, você deve tomar medidas para globalizar o aplicativo. Consulte esta edição 4076 do GitHub para obter instruções sobre como adicionar vírgula decimal.
A Layout propriedade é definida no Pages/_ViewStart.cshtml arquivo:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout para Pages/Shared/_Layout.cshtml todos os Razor arquivos na pasta Páginas . Consulte Layout para obter mais informações.
O modelo Criar página
Examine o modelo da página Pages/Movies/Create.cshtml.cs.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
O OnGet método inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, portanto, Page é retornada. Mais adiante no tutorial, um exemplo de estado de OnGet inicialização é mostrado. O Page método cria um PageResult objeto que renderiza a Create.cshtml página.
A Movie propriedade usa o atributo [BindProperty] para aceitar a vinculação de modelo. Quando o formulário Create envia os valores do formulário, o tempo de execução do ASP.NET Core vincula os valores enviados ao modelo Movie.
O OnPostAsync método é executado quando a página posta dados de formulário:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se houver algum erro de modelo, o formulário será reexibido, juntamente com todos os dados do formulário postados. A maioria dos erros de modelo pode ser detetada no lado do cliente antes que o formulário seja lançado. Um exemplo de erro de modelo é lançar um valor para o campo de data que não pode ser convertido em uma data. A validação do lado do cliente e a validação do modelo são discutidas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são guardados.
- O navegador é redirecionado para a página Índice.
A página de Criação Razor
Verifique o ficheiro de página Pages/Movies/Create.cshtmlRazor.
@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 exibe as seguintes tags em uma fonte distinta em negrito usada nos Auxiliares de 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>
O <form method="post"> elemento é um Form Tag Helper. O Form Tag Helper inclui automaticamente um token antifalsificação.
O motor de andaimes cria Razor marcação para cada campo no modelo, exceto o ID, semelhante ao seguinte:
<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>
Os Auxiliares de Tag de Validação (<div asp-validation-summary e <span asp-validation-for) exibem erros de validação. A validação será abordada mais detalhadamente mais adiante nesta série.
O Auxiliar de Etiquetas para Rótulos (<label asp-for="Movie.Title" class="control-label"></label>) gera a legenda do rótulo e o atributo para a [for] propriedade.
O Input Tag Helper (<input asp-for="Movie.Title" class="form-control">) usa os atributos DataAnnotations e produz atributos HTML necessários para a Validação do jQuery no lado do cliente.
Para obter mais informações sobre Ajudantes de tag, como <form method="post">, consulte Auxiliares de tag no ASP.NET Core.
Próximos passos
As páginas Criar, Apagar, Detalhes e Editar
Examine o Modelo da Página Pages/Movies/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies;
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor As páginas são derivadas de PageModel. Por convenção, a classe derivada PageModel é denominada PageNameModel. Por exemplo, a página Índice tem o nome IndexModel.
O construtor usa a injeção de dependência para adicionar o RazorPagesMovieContext à página:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Consulte Código assíncrono para obter mais informações sobre programação assíncrona com o Entity Framework.
Quando uma GET solicitação é feita para a página, o OnGetAsync método retorna uma lista de filmes para a Razor página. Em uma Página Razor, é chamado OnGetAsync ou OnGet para inicializar o estado da página. Neste caso, OnGetAsync obtém uma lista de filmes e exibe-os.
Quando OnGet retorna void ou OnGetAsync retorna Task, nenhuma instrução de retorno é usada. Por exemplo, verifique a Privacy Página:
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 o tipo de retorno é IActionResult ou Task<IActionResult>, uma declaração de retorno deve ser fornecida. Por exemplo, o Pages/Movies/Create.cshtml.cs OnPostAsync método:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Examine a Pages/Movies/Index.cshtmlRazor página:
@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 pode fazer a transição de HTML para C# ou para Razormarcação específica. Quando um @ símbolo é seguido por uma Razor palavra-chave reservada, transita para a marcação específica de Razor, caso contrário, para C#.
A @page diretiva
A @pageRazor diretiva torna o arquivo uma ação MVC, o que significa que ele pode lidar com solicitações.
@page deve ser a primeira Razor diretiva numa página.
@page e @model são exemplos de transição para Razor marcações específicas. Consulte Razor sintaxe para obter mais informações.
A @model diretiva
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A @model diretiva especifica o tipo do modelo passado para a Razor Página. No exemplo anterior, a @model linha disponibiliza a classe derivada PageModel para a Razor Page. O modelo é usado no @Html.DisplayNameFor e @Html.DisplayForHTML Helpers na página.
Examine a expressão lambda usada no seguinte HTML Helper:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O DisplayNameFor HTML Helper inspeciona a Title propriedade referenciada na expressão lambda para determinar o nome para exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há violação de acesso quando model, model.Movie, ou model.Movie[0] é null ou está vazio. Quando a expressão lambda é avaliada, por exemplo, com @Html.DisplayFor(modelItem => item.Title), os valores de propriedade do modelo são avaliados.
A página de layout
Selecione os links de menu RazorPagesMovie, Homee Privacy. Cada página mostra o mesmo layout de menu. O layout do menu Pages/Shared/_Layout.cshtml é implementado no ficheiro.
Abra e examine o Pages/Shared/_Layout.cshtml arquivo.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado num só lugar.
- Aplicado em várias páginas do site.
Encontre a @RenderBody() linha.
RenderBody é um espaço reservado onde todas as visualizações específicas da página aparecem, encapsuladas na página de layout. Por exemplo, selecione o Privacy link e a Pages/Privacy.cshtml exibição é renderizada dentro do RenderBody método.
ViewData e layout
Considere a seguinte marcação do Pages/Movies/Index.cshtml arquivo:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação destacada anteriormente é um exemplo de Razor a transitar para C#. Os { caracteres e } incluem um bloco de código C#.
A PageModel classe base contém uma ViewData propriedade de dicionário que pode ser usada para passar dados para um View. Os objetos são adicionados ao ViewData dicionário usando um padrão de valor de chave . No exemplo anterior, a propriedade Title é adicionada ao dicionário ViewData.
A Title propriedade é usada no Pages/Shared/_Layout.cshtml arquivo. A marcação a seguir mostra as primeiras linhas do _Layout.cshtml arquivo.
<!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" />
A linha @*Markup removed for brevity.*@ é um Razor comentário. Ao contrário dos comentários <!-- -->HTML, Razor os comentários não são enviados para o cliente. Consulte MDN web docs: Introdução ao HTML para obter mais informações.
Atualizar o layout
Altere o
<title>elemento doPages/Shared/_Layout.cshtmlficheiro para exibir Movie em vez de 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>Encontre o seguinte elemento âncora no
Pages/Shared/_Layout.cshtmlarquivo.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Substitua o elemento anterior pela seguinte marcação:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>O elemento âncora anterior é um Tag Helper. Neste caso, é o Anchor Tag Helper. O atributo Tag Helper e o seu valor criam um link para a Página
asp-page="/Movies/Index"/Movies/Index. Oasp-areavalor do atributo está vazio, portanto, a área não é usada no link. Consulte Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie . Consulte o arquivo _Layout.cshtml no GitHub se tiver algum problema.
Teste os Homelinks , RpMovie, Criar, Editar e Apagar. Cada página define o título, que você pode ver na guia do navegador. Quando você marca uma página, o título é usado para o marcador.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price. Para dar suporte à validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e formatos de data não US-English, você deve tomar medidas para globalizar o aplicativo. Consulte esta edição 4076 do GitHub para obter instruções sobre como adicionar vírgula decimal.
A Layout propriedade é definida no Pages/_ViewStart.cshtml arquivo:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout para Pages/Shared/_Layout.cshtml todos os Razor arquivos na pasta Páginas . Consulte Layout para obter mais informações.
O modelo Criar página
Examine o modelo da página Pages/Movies/Create.cshtml.cs.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
O OnGet método inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, portanto, Page é retornada. Mais adiante no tutorial, um exemplo de estado de OnGet inicialização é mostrado. O Page método cria um PageResult objeto que renderiza a Create.cshtml página.
A Movie propriedade usa o atributo [BindProperty] para aceitar a vinculação de modelo. Quando o formulário Create envia os valores do formulário, o tempo de execução do ASP.NET Core vincula os valores enviados ao modelo Movie.
O OnPostAsync método é executado quando a página posta dados de formulário:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se houver algum erro de modelo, o formulário será reexibido, juntamente com todos os dados do formulário postados. A maioria dos erros de modelo pode ser detetada no lado do cliente antes que o formulário seja lançado. Um exemplo de erro de modelo é lançar um valor para o campo de data que não pode ser convertido em uma data. A validação do lado do cliente e a validação do modelo são discutidas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são guardados.
- O navegador é redirecionado para a página Índice.
A página de Criação Razor
Verifique o ficheiro de página Pages/Movies/Create.cshtmlRazor.
@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 exibe as seguintes tags em uma fonte distinta em negrito usada nos Auxiliares de 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>
O <form method="post"> elemento é um Form Tag Helper. O Form Tag Helper inclui automaticamente um token antifalsificação.
O motor de andaimes cria Razor marcação para cada campo no modelo, exceto o ID, semelhante ao seguinte:
<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>
Os Auxiliares de Tag de Validação (<div asp-validation-summary e <span asp-validation-for) exibem erros de validação. A validação será abordada mais detalhadamente mais adiante nesta série.
O Auxiliar de Etiquetas para Rótulos (<label asp-for="Movie.Title" class="control-label"></label>) gera a legenda do rótulo e o atributo para a [for] propriedade.
O Input Tag Helper (<input asp-for="Movie.Title" class="form-control">) usa os atributos DataAnnotations e produz atributos HTML necessários para a Validação do jQuery no lado do cliente.
Para obter mais informações sobre Ajudantes de tag, como <form method="post">, consulte Auxiliares de tag no ASP.NET Core.
Próximos passos
As páginas Criar, Apagar, Detalhes e Editar
Examine o Modelo da Página Pages/Movies/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.Movie != null)
{
Movie = await _context.Movie.ToListAsync();
}
}
}
}
Razor As páginas são derivadas de PageModel. Por convenção, a classe derivada PageModel é denominada PageNameModel. Por exemplo, a página Índice tem o nome IndexModel.
O construtor usa a injeção de dependência para adicionar o RazorPagesMovieContext à página:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Consulte Código assíncrono para obter mais informações sobre programação assíncrona com o Entity Framework.
Quando uma solicitação é feita para a página, o OnGetAsync método retorna uma lista de filmes para a Razor página. Em uma Página Razor, é chamado OnGetAsync ou OnGet para inicializar o estado da página. Neste caso, OnGetAsync obtém uma lista de filmes e exibe-os.
Quando OnGet retorna void ou OnGetAsync retorna Task, nenhuma instrução de retorno é usada. Por exemplo, verifique a Privacy Página:
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 o tipo de retorno é IActionResult ou Task<IActionResult>, uma declaração de retorno deve ser fornecida. Por exemplo, o Pages/Movies/Create.cshtml.csOnPostAsync método:
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");
}
Examine a Pages/Movies/Index.cshtmlRazor página:
@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 pode fazer a transição de HTML para C# ou para Razormarcação específica. Quando um @ símbolo é seguido por uma Razor palavra-chave reservada, transita para a marcação específica de Razor, caso contrário, para C#.
A @page diretiva
A @pageRazor diretiva torna o arquivo uma ação MVC, o que significa que ele pode lidar com solicitações.
@page deve ser a primeira Razor diretiva numa página.
@page e @model são exemplos de transição para Razor marcações específicas. Consulte Razor sintaxe para obter mais informações.
A @model diretiva
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A @model diretiva especifica o tipo do modelo passado para a Razor Página. No exemplo anterior, a @model linha disponibiliza a classe derivada PageModel para a Razor Page. O modelo é usado no @Html.DisplayNameFor e @Html.DisplayForHTML Helpers na página.
Examine a expressão lambda usada no seguinte HTML Helper:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O DisplayNameFor HTML Helper inspeciona a Title propriedade referenciada na expressão lambda para determinar o nome para exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há violação de acesso quando model, model.Movie, ou model.Movie[0] é null ou está vazio. Quando a expressão lambda é avaliada, por exemplo, com @Html.DisplayFor(modelItem => item.Title), os valores de propriedade do modelo são avaliados.
A página de layout
Selecione os links de menu RazorPagesMovie, Homee Privacy. Cada página mostra o mesmo layout de menu. O layout do menu Pages/Shared/_Layout.cshtml é implementado no ficheiro.
Abra e examine o Pages/Shared/_Layout.cshtml arquivo.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado num só lugar.
- Aplicado em várias páginas do site.
Encontre a @RenderBody() linha.
RenderBody é um espaço reservado onde todas as visualizações específicas da página aparecem, encapsuladas na página de layout. Por exemplo, selecione o Privacy link e a Pages/Privacy.cshtml exibição é renderizada dentro do RenderBody método.
ViewData e layout
Considere a seguinte marcação do Pages/Movies/Index.cshtml arquivo:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação destacada anteriormente é um exemplo de Razor a transitar para C#. Os { caracteres e } incluem um bloco de código C#.
A PageModel classe base contém uma ViewData propriedade de dicionário que pode ser usada para passar dados para um View. Os objetos são adicionados ao ViewData dicionário usando um padrão de valor de chave . No exemplo anterior, a propriedade Title é adicionada ao dicionário ViewData.
A Title propriedade é usada no Pages/Shared/_Layout.cshtml arquivo. A marcação a seguir mostra as primeiras linhas do _Layout.cshtml arquivo.
<!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" />
A linha @*Markup removed for brevity.*@ é um Razor comentário. Ao contrário dos comentários <!-- -->HTML, Razor os comentários não são enviados para o cliente. Consulte MDN web docs: Introdução ao HTML para obter mais informações.
Atualizar o layout
Altere o
<title>elemento doPages/Shared/_Layout.cshtmlficheiro para exibir Movie em vez de 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>Encontre o seguinte elemento âncora no
Pages/Shared/_Layout.cshtmlarquivo.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Substitua o elemento anterior pela seguinte marcação:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>O elemento âncora anterior é um Tag Helper. Neste caso, é o Anchor Tag Helper. O atributo Tag Helper e o seu valor criam um link para a Página
asp-page="/Movies/Index"/Movies/Index. Oasp-areavalor do atributo está vazio, portanto, a área não é usada no link. Consulte Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie . Consulte o arquivo _Layout.cshtml no GitHub se tiver algum problema.
Teste os Homelinks , RpMovie, Criar, Editar e Apagar. Cada página define o título, que você pode ver na guia do navegador. Quando você marca uma página, o título é usado para o marcador.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price. Para dar suporte à validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e formatos de data não US-English, você deve tomar medidas para globalizar o aplicativo. Consulte esta edição 4076 do GitHub para obter instruções sobre como adicionar vírgula decimal.
A Layout propriedade é definida no Pages/_ViewStart.cshtml arquivo:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout para Pages/Shared/_Layout.cshtml todos os Razor arquivos na pasta Páginas . Consulte Layout para obter mais informações.
O modelo Criar página
Examine o modelo da página Pages/Movies/Create.cshtml.cs.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
O OnGet método inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, portanto, Page é retornada. Mais adiante no tutorial, um exemplo de estado de OnGet inicialização é mostrado. O Page método cria um PageResult objeto que renderiza a Create.cshtml página.
A Movie propriedade usa o atributo [BindProperty] para aceitar a vinculação de modelo. Quando o formulário Create envia os valores do formulário, o tempo de execução do ASP.NET Core vincula os valores enviados ao modelo Movie.
O OnPostAsync método é executado quando a página posta dados de formulário:
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 houver algum erro de modelo, o formulário será reexibido, juntamente com todos os dados do formulário postados. A maioria dos erros de modelo pode ser detetada no lado do cliente antes que o formulário seja lançado. Um exemplo de erro de modelo é lançar um valor para o campo de data que não pode ser convertido em uma data. A validação do lado do cliente e a validação do modelo são discutidas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são guardados.
- O navegador é redirecionado para a página Índice.
A página de Criação Razor
Verifique o ficheiro de página Pages/Movies/Create.cshtmlRazor.
@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 exibe as seguintes tags em uma fonte distinta em negrito usada nos Auxiliares de 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>
O <form method="post"> elemento é um Form Tag Helper. O Form Tag Helper inclui automaticamente um token antifalsificação.
O motor de andaimes cria Razor marcação para cada campo no modelo, exceto o ID, semelhante ao seguinte:
<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>
Os Auxiliares de Tag de Validação (<div asp-validation-summary e <span asp-validation-for) exibem erros de validação. A validação será abordada mais detalhadamente mais adiante nesta série.
O Auxiliar de Etiquetas para Rótulos (<label asp-for="Movie.Title" class="control-label"></label>) gera a legenda do rótulo e o atributo para a [for] propriedade.
O Input Tag Helper (<input asp-for="Movie.Title" class="form-control">) usa os atributos DataAnnotations e produz atributos HTML necessários para a Validação do jQuery no lado do cliente.
Para obter mais informações sobre Ajudantes de tag, como <form method="post">, consulte Auxiliares de tag no ASP.NET Core.
Próximos passos
As páginas Criar, Apagar, Detalhes e Editar
Examine o Modelo da Página Pages/Movies/Index.cshtml.cs
// Unused usings removed.
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; }
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor As páginas são derivadas de PageModel. Por convenção, a classe derivada PageModelé denominada <PageName>Model. O construtor usa a injeção de dependência para adicionar o RazorPagesMovieContext à página:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
Consulte Código assíncrono para obter mais informações sobre programação assíncrona com o Entity Framework.
Quando uma solicitação é feita para a página, o OnGetAsync método retorna uma lista de filmes para a Razor página. Em uma Página Razor, é chamado OnGetAsync ou OnGet para inicializar o estado da página. Neste caso, OnGetAsync obtém uma lista de filmes e exibe-os.
Quando OnGet retorna void ou OnGetAsync retorna Task, nenhuma instrução de retorno é usada. Por exemplo, a Privacy página:
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
Quando o tipo de retorno é IActionResult ou Task<IActionResult>, uma declaração de retorno deve ser fornecida. Por exemplo, o Pages/Movies/Create.cshtml.csOnPostAsync método:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Examine a Pages/Movies/Index.cshtmlRazor página:
@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 pode fazer a transição de HTML para C# ou para Razormarcação específica. Quando um @ símbolo é seguido por uma Razor palavra-chave reservada, transita para a marcação específica de Razor, caso contrário, para C#.
A @page diretiva
A @pageRazor diretiva torna o arquivo uma ação MVC, o que significa que ele pode lidar com solicitações.
@page deve ser a primeira Razor diretiva numa página.
@page e @model são exemplos de transição para Razor marcações específicas. Consulte Razor sintaxe para obter mais informações.
A @model diretiva
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A @model diretiva especifica o tipo do modelo passado para a Razor Página. No exemplo anterior, a linha @model torna a classe derivada PageModel disponível na página Razor. O modelo é usado no @Html.DisplayNameFor e @Html.DisplayForHTML Helpers na página.
Examine a expressão lambda usada no seguinte HTML Helper:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O DisplayNameFor HTML Helper inspeciona a Title propriedade referenciada na expressão lambda para determinar o nome para exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há violação de acesso quando model, model.Movie, ou model.Movie[0] é null ou está vazio. Quando a expressão lambda é avaliada, por exemplo, com @Html.DisplayFor(modelItem => item.Title), os valores de propriedade do modelo são avaliados.
A página de layout
Selecione os links de menu RazorPagesMovie, Homee Privacy. Cada página mostra o mesmo layout de menu. O layout do menu Pages/Shared/_Layout.cshtml é implementado no ficheiro.
Abra e examine o Pages/Shared/_Layout.cshtml arquivo.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado num só lugar.
- Aplicado em várias páginas do site.
Encontre a @RenderBody() linha.
RenderBody é um espaço reservado onde todas as visualizações específicas da página aparecem, encapsuladas na página de layout. Por exemplo, selecione o Privacy link e a Pages/Privacy.cshtml exibição é renderizada dentro do RenderBody método.
ViewData e layout
Considere a seguinte marcação do Pages/Movies/Index.cshtml arquivo:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação destacada anteriormente é um exemplo de Razor a transitar para C#. Os { caracteres e } incluem um bloco de código C#.
A PageModel classe base contém uma ViewData propriedade de dicionário que pode ser usada para passar dados para um View. Os objetos são adicionados ao ViewData dicionário usando um padrão de valor de chave . No exemplo anterior, a propriedade Title é adicionada ao dicionário ViewData.
A Title propriedade é usada no Pages/Shared/_Layout.cshtml arquivo. A marcação a seguir mostra as primeiras linhas do _Layout.cshtml arquivo.
<!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.*@
A linha @*Markup removed for brevity.*@ é um Razor comentário. Ao contrário dos comentários <!-- -->HTML, Razor os comentários não são enviados para o cliente. Consulte MDN web docs: Introdução ao HTML para obter mais informações.
Atualizar o layout
Altere o
<title>elemento doPages/Shared/_Layout.cshtmlficheiro para exibir Movie em vez de 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>Encontre o seguinte elemento âncora no
Pages/Shared/_Layout.cshtmlarquivo.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>Substitua o elemento anterior pela seguinte marcação:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>O elemento âncora anterior é um Tag Helper. Neste caso, é o Anchor Tag Helper. O atributo Tag Helper e o seu valor criam um link para a Página
asp-page="/Movies/Index"/Movies/Index. Oasp-areavalor do atributo está vazio, portanto, a área não é usada no link. Consulte Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie . Consulte o arquivo _Layout.cshtml no GitHub se tiver algum problema.
Teste os Homelinks , RpMovie, Criar, Editar e Apagar. Cada página define o título, que você pode ver na guia do navegador. Quando você marca uma página, o título é usado para o marcador.
Observação
Talvez não seja possível inserir vírgulas decimais no campo Price. Para dar suporte à validação do jQuery para localidades diferentes do inglês que usam uma vírgula (",") para um ponto decimal e formatos de data não US-English, você deve tomar medidas para globalizar o aplicativo. Consulte esta edição 4076 do GitHub para obter instruções sobre como adicionar vírgula decimal.
A Layout propriedade é definida no Pages/_ViewStart.cshtml arquivo:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout para Pages/Shared/_Layout.cshtml todos os Razor arquivos na pasta Páginas . Consulte Layout para obter mais informações.
O modelo Criar página
Examine o modelo da página Pages/Movies/Create.cshtml.cs.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
O OnGet método inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, portanto, Page é retornada. Mais adiante no tutorial, um exemplo de estado de OnGet inicialização é mostrado. O Page método cria um PageResult objeto que renderiza a Create.cshtml página.
A Movie propriedade usa o atributo [BindProperty] para aceitar a vinculação de modelo. Quando o formulário Create envia os valores do formulário, o tempo de execução do ASP.NET Core vincula os valores enviados ao modelo Movie.
O OnPostAsync método é executado quando a página posta dados de formulário:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Se houver algum erro de modelo, o formulário será reexibido, juntamente com todos os dados do formulário postados. A maioria dos erros de modelo pode ser detetada no lado do cliente antes que o formulário seja lançado. Um exemplo de erro de modelo é lançar um valor para o campo de data que não pode ser convertido em uma data. A validação do lado do cliente e a validação do modelo são discutidas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são guardados.
- O navegador é redirecionado para a página Índice.
A página de Criação Razor
Verifique o ficheiro de página Pages/Movies/Create.cshtmlRazor.
@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 exibe as seguintes tags em uma fonte distinta em negrito usada nos Auxiliares de 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>
O <form method="post"> elemento é um Form Tag Helper. O Form Tag Helper inclui automaticamente um token antifalsificação.
O motor de andaimes cria Razor marcação para cada campo no modelo, exceto o ID, semelhante ao seguinte:
<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>
Os Auxiliares de Tag de Validação (<div asp-validation-summary e <span asp-validation-for) exibem erros de validação. A validação será abordada mais detalhadamente mais adiante nesta série.
O Auxiliar de Etiquetas para Rótulos (<label asp-for="Movie.Title" class="control-label"></label>) gera a legenda do rótulo e o atributo para a [for] propriedade.
O Input Tag Helper (<input asp-for="Movie.Title" class="form-control">) usa os atributos DataAnnotations e produz atributos HTML necessários para a Validação do jQuery no lado do cliente.
Para obter mais informações sobre Ajudantes de tag, como <form method="post">, consulte Auxiliares de tag no ASP.NET Core.