Parte 3, Razor Pages gerado por scaffolding no ASP.NET Core
Observação
Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Importante
Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.
Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Este tutorial examina o Razor Pages criadi por scaffolding no tutorial anterior.
As páginas Create, Delete, Details e Edit
Examine o modelo do Pages/Movies/Index.cshtml.cs
Page:
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 Pages são derivados de PageModel. Por convenção, a classe derivada de PageModel
é chamada de PageNameModel
. Por exemplo, a página Índice é chamada de IndexModel
.
O construtor usa 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;
}
Confira Código assíncrono para obter mais informações sobre a programação assíncrona com o Entity Framework.
Quando uma solicitação GET
é feita à página, o método OnGetAsync
retorna uma lista de filmes para o Razor Page. Em um Razor Page, OnGetAsync
ou OnGet
é chamado para inicializar o estado da página. Nesse caso, OnGetAsync
obtém uma lista de filmes e os exibe.
Quando OnGet
retorna void
ou OnGetAsync
retorna Task
, então nenhuma instrução return é usada. Por exemplo, examine o Privacy Page:
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 for IActionResult ou Task<IActionResult>
, é necessário fornecer uma instrução de retorno. Por exemplo, o método Pages/Movies/Create.cshtml.cs OnPostAsync
:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Examine o Pages/Movies/Index.cshtml
Razor Page:
@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>
O Razor pode fazer a transição do HTML em C# ou em marcação específica do Razor. Quando um símbolo @
é seguido por uma palavra-chave reservada do Razor, ele faz a transição para marcação específica do Razor, caso contrário, ele faz a transição para C#.
A diretiva @page
A diretiva do @page
Razor transforma o arquivo em uma ação do MVC, o que significa que ele pode manipular solicitações. @page
deve ser a primeira diretiva do Razor em uma página. @page
e @model
são exemplos de transição para a marcação específica do Razor. Confira RazorSintaxe para obter mais informações.
A diretiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A diretiva @model
especifica o tipo do modelo passado para o Razor Page. No exemplo anterior, a linha @model
torna a classe derivada de PageModel
disponível para o Razor Page. O modelo é usado nos auxiliares HTML @Html.DisplayNameFor
e @Html.DisplayFor
na página.
Examine a expressão lambda usada no auxiliar HTML a seguir:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O auxiliar HTML DisplayNameFor inspeciona a propriedade Title
referenciada na expressão lambda para determinar o nome de exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há nenhuma violação de acesso quando model
, model.Movie
ou model.Movie[0]
é null
ou 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, Home e Privacy. Cada página mostra o mesmo layout de menu. O layout do menu é implementado no arquivo Pages/Shared/_Layout.cshtml
.
Abra e examine o arquivo Pages/Shared/_Layout.cshtml
.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado em um único lugar.
- Aplicado a várias páginas no site.
Localize a linha @RenderBody()
. RenderBody
é um espaço reservado em que todas as exibições específicas da página são mostradas, encapsuladas na página de layout. Por exemplo, selecione o link Privacy e a exibição Pages/Privacy.cshtml
será renderizada dentro do método RenderBody
.
ViewData e layout
Considere a seguinte marcação do arquivo Pages/Movies/Index.cshtml
:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação realçada anteriormente é um exemplo de transição do Razor para C#. Os caracteres {
e }
circunscrevem um bloco de código C#.
A classe base PageModel
tem uma propriedade de dicionário ViewData
que pode ser usada para passar dados para uma Exibição. Adicione objetos ao dicionário ViewData
usando um padrão de valor de chave. No exemplo anterior, a propriedade Title
é adicionada ao dicionário ViewData
.
A propriedade Title
é usada no arquivo Pages/Shared/_Layout.cshtml
. A marcação a seguir mostra as primeiras linhas do arquivo _Layout.cshtml
.
<!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 elemento
<title>
no arquivoPages/Shared/_Layout.cshtml
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>
Localizar o elemento de âncora a seguir no arquivo
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Substitua o elemento anterior pela marcação a seguir:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
O elemento de âncora anterior é um Auxiliar de Marcas. Nesse caso, ele é o Auxiliar de Marcas de Âncora. O atributo e valor do auxiliar de marcas
asp-page="/Movies/Index"
cria um link para o/Movies/Index
Razor Page. O valor do atributoasp-area
está vazio e, portanto, a área não é usada no link. Confira Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie. Confira o arquivo _Layout.cshtml no GitHub caso tenha problemas.
Teste os links Home, RpMovie, Criar, Editar e Excluir. Cada página define o título, que pode ser visto na guia do navegador. Quando você coloca um indicador em uma página, o título é usado para o indicador.
Observação
Talvez você não consiga inserir casas decimais ou vírgulas no campo Price
. Para dar suporte à validação do jQuery para localidades de idiomas diferentes do inglês que usam uma vírgula (“,”) para um ponto decimal e formatos de data diferentes do inglês dos EUA, você deve tomar medidas para globalizar o aplicativo. Confira Problema 4076 do GitHub para obter instruções sobre como adicionar casas decimais.
A propriedade Layout
é definida no arquivo Pages/_ViewStart.cshtml
:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout Pages/Shared/_Layout.cshtml
para todos os arquivos do Razor na pasta Pages. Veja 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 método OnGet
inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, assim, Page
é retornado. Apresentamos um exemplo de inicialização de estado OnGet
posteriormente no tutorial. O método Page
cria um objeto PageResult
que renderiza a página Create.cshtml
.
A propriedade Movie
usa o atributo [BindProperty] para aceitar o model binding. Quando o formulário Criar posta os valores de formulário, o runtime do ASP.NET Core associa os valores postados ao modelo Movie
.
O método OnPostAsync
é 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 há algum erro de modelo, o formulário é reexibido juntamente com quaisquer dados de formulário postados. A maioria dos erros de modelo podem ser capturados no lado do cliente antes do formulário ser enviado. Um exemplo de um erro de modelo é postar, para o campo de data, um valor que não pode ser convertido em uma data. A validação do lado do cliente e a validação de modelo são abordadas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são salvos.
- O navegador é redirecionado para a página de índice.
Criar Razor Page
Examine o arquivo Pages/Movies/Create.cshtml
Razor Page:
@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");}
}
O Visual Studio exibe as marcas a seguir em uma fonte em negrito diferente usada em auxiliares de marcações:
<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 elemento <form method="post">
é um auxiliar de marcas de formulário. O auxiliar de marcas de formulário inclui automaticamente um token antifalsificação.
O mecanismo de scaffolding cria marcação do Razor para cada campo no modelo, exceto a 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 marcas de validação (<div asp-validation-summary
e <span asp-validation-for
) exibem erros de validação. A validação será abordada em mais detalhes posteriormente nesta série.
O auxiliar de marcas de rótulo (<label asp-for="Movie.Title" class="control-label"></label>
) gera a legenda do rótulo e o atributo [for]
para a propriedade Title
.
O auxiliar de marcas de entrada (<input asp-for="Movie.Title" class="form-control">
) usa os atributos DataAnnotations e produz os atributos HTML necessários para validação jQuery no lado do cliente.
Para obter mais informações sobre Auxiliares de Marcas, como <form method="post">
, confira Auxiliares de Marcas no ASP.NET Core.
Próximas etapas
As páginas Create, Delete, Details e Edit
Examine o modelo do Pages/Movies/Index.cshtml.cs
Page:
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 Pages são derivados de PageModel. Por convenção, a classe derivada de PageModel
é chamada de PageNameModel
. Por exemplo, a página Índice é chamada de IndexModel
.
O construtor usa 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;
}
Confira Código assíncrono para obter mais informações sobre a programação assíncrona com o Entity Framework.
Quando uma solicitação GET
é feita à página, o método OnGetAsync
retorna uma lista de filmes para o Razor Page. Em um Razor Page, OnGetAsync
ou OnGet
é chamado para inicializar o estado da página. Nesse caso, OnGetAsync
obtém uma lista de filmes e os exibe.
Quando OnGet
retorna void
ou OnGetAsync
retorna Task
, então nenhuma instrução return é usada. Por exemplo, examine o Privacy Page:
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 for IActionResult ou Task<IActionResult>
, é necessário fornecer uma instrução de retorno. Por exemplo, o método Pages/Movies/Create.cshtml.cs OnPostAsync
:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Examine o Pages/Movies/Index.cshtml
Razor Page:
@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>
O Razor pode fazer a transição do HTML em C# ou em marcação específica do Razor. Quando um símbolo @
é seguido por uma palavra-chave reservada do Razor, ele faz a transição para marcação específica do Razor, caso contrário, ele faz a transição para C#.
A diretiva @page
A diretiva do @page
Razor transforma o arquivo em uma ação do MVC, o que significa que ele pode manipular solicitações. @page
deve ser a primeira diretiva do Razor em uma página. @page
e @model
são exemplos de transição para a marcação específica do Razor. Confira RazorSintaxe para obter mais informações.
A diretiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A diretiva @model
especifica o tipo do modelo passado para o Razor Page. No exemplo anterior, a linha @model
torna a classe derivada de PageModel
disponível para o Razor Page. O modelo é usado nos auxiliares HTML @Html.DisplayNameFor
e @Html.DisplayFor
na página.
Examine a expressão lambda usada no auxiliar HTML a seguir:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O auxiliar HTML DisplayNameFor inspeciona a propriedade Title
referenciada na expressão lambda para determinar o nome de exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há nenhuma violação de acesso quando model
, model.Movie
ou model.Movie[0]
é null
ou 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, Home e Privacy. Cada página mostra o mesmo layout de menu. O layout do menu é implementado no arquivo Pages/Shared/_Layout.cshtml
.
Abra e examine o arquivo Pages/Shared/_Layout.cshtml
.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado em um único lugar.
- Aplicado a várias páginas no site.
Localize a linha @RenderBody()
. RenderBody
é um espaço reservado em que todas as exibições específicas da página são mostradas, encapsuladas na página de layout. Por exemplo, selecione o link Privacy e a exibição Pages/Privacy.cshtml
será renderizada dentro do método RenderBody
.
ViewData e layout
Considere a seguinte marcação do arquivo Pages/Movies/Index.cshtml
:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação realçada anteriormente é um exemplo de transição do Razor para C#. Os caracteres {
e }
circunscrevem um bloco de código C#.
A classe base PageModel
tem uma propriedade de dicionário ViewData
que pode ser usada para passar dados para uma Exibição. Adicione objetos ao dicionário ViewData
usando um padrão de valor de chave. No exemplo anterior, a propriedade Title
é adicionada ao dicionário ViewData
.
A propriedade Title
é usada no arquivo Pages/Shared/_Layout.cshtml
. A marcação a seguir mostra as primeiras linhas do arquivo _Layout.cshtml
.
<!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 elemento
<title>
no arquivoPages/Shared/_Layout.cshtml
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>
Localizar o elemento de âncora a seguir no arquivo
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Substitua o elemento anterior pela marcação a seguir:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
O elemento de âncora anterior é um Auxiliar de Marcas. Nesse caso, ele é o Auxiliar de Marcas de Âncora. O atributo e valor do auxiliar de marcas
asp-page="/Movies/Index"
cria um link para o/Movies/Index
Razor Page. O valor do atributoasp-area
está vazio e, portanto, a área não é usada no link. Confira Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie. Confira o arquivo _Layout.cshtml no GitHub caso tenha problemas.
Teste os links Home, RpMovie, Criar, Editar e Excluir. Cada página define o título, que pode ser visto na guia do navegador. Quando você coloca um indicador em uma página, o título é usado para o indicador.
Observação
Talvez você não consiga inserir casas decimais ou vírgulas no campo Price
. Para dar suporte à validação do jQuery para localidades de idiomas diferentes do inglês que usam uma vírgula (“,”) para um ponto decimal e formatos de data diferentes do inglês dos EUA, você deve tomar medidas para globalizar o aplicativo. Confira Problema 4076 do GitHub para obter instruções sobre como adicionar casas decimais.
A propriedade Layout
é definida no arquivo Pages/_ViewStart.cshtml
:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout Pages/Shared/_Layout.cshtml
para todos os arquivos do Razor na pasta Pages. Veja 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 método OnGet
inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, assim, Page
é retornado. Apresentamos um exemplo de inicialização de estado OnGet
posteriormente no tutorial. O método Page
cria um objeto PageResult
que renderiza a página Create.cshtml
.
A propriedade Movie
usa o atributo [BindProperty] para aceitar o model binding. Quando o formulário Criar posta os valores de formulário, o runtime do ASP.NET Core associa os valores postados ao modelo Movie
.
O método OnPostAsync
é 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 há algum erro de modelo, o formulário é reexibido juntamente com quaisquer dados de formulário postados. A maioria dos erros de modelo podem ser capturados no lado do cliente antes do formulário ser enviado. Um exemplo de um erro de modelo é postar, para o campo de data, um valor que não pode ser convertido em uma data. A validação do lado do cliente e a validação de modelo são abordadas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são salvos.
- O navegador é redirecionado para a página de índice.
Criar Razor Page
Examine o arquivo Pages/Movies/Create.cshtml
Razor Page:
@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");}
}
O Visual Studio exibe as marcas a seguir em uma fonte em negrito diferente usada em auxiliares de marcações:
<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 elemento <form method="post">
é um auxiliar de marcas de formulário. O auxiliar de marcas de formulário inclui automaticamente um token antifalsificação.
O mecanismo de scaffolding cria marcação do Razor para cada campo no modelo, exceto a 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 marcas de validação (<div asp-validation-summary
e <span asp-validation-for
) exibem erros de validação. A validação será abordada em mais detalhes posteriormente nesta série.
O auxiliar de marcas de rótulo (<label asp-for="Movie.Title" class="control-label"></label>
) gera a legenda do rótulo e o atributo [for]
para a propriedade Title
.
O auxiliar de marcas de entrada (<input asp-for="Movie.Title" class="form-control">
) usa os atributos DataAnnotations e produz os atributos HTML necessários para validação jQuery no lado do cliente.
Para obter mais informações sobre Auxiliares de Marcas, como <form method="post">
, confira Auxiliares de Marcas no ASP.NET Core.
Próximas etapas
As páginas Create, Delete, Details e Edit
Examine o modelo do Pages/Movies/Index.cshtml.cs
Page:
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 Pages são derivados de PageModel. Por convenção, a classe derivada de PageModel
é chamada de PageNameModel
. Por exemplo, a página Índice é chamada de IndexModel
.
O construtor usa 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;
}
Confira Código assíncrono para obter mais informações sobre a programação assíncrona com o Entity Framework.
Quando uma solicitação GET
é feita à página, o método OnGetAsync
retorna uma lista de filmes para o Razor Page. Em um Razor Page, OnGetAsync
ou OnGet
é chamado para inicializar o estado da página. Nesse caso, OnGetAsync
obtém uma lista de filmes e os exibe.
Quando OnGet
retorna void
ou OnGetAsync
retorna Task
, então nenhuma instrução return é usada. Por exemplo, examine o Privacy Page:
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 for IActionResult ou Task<IActionResult>
, é necessário fornecer uma instrução de retorno. Por exemplo, o método Pages/Movies/Create.cshtml.cs OnPostAsync
:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Examine o Pages/Movies/Index.cshtml
Razor Page:
@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>
O Razor pode fazer a transição do HTML em C# ou em marcação específica do Razor. Quando um símbolo @
é seguido por uma palavra-chave reservada do Razor, ele faz a transição para marcação específica do Razor, caso contrário, ele faz a transição para C#.
A diretiva @page
A diretiva do @page
Razor transforma o arquivo em uma ação do MVC, o que significa que ele pode manipular solicitações. @page
deve ser a primeira diretiva do Razor em uma página. @page
e @model
são exemplos de transição para a marcação específica do Razor. Confira RazorSintaxe para obter mais informações.
A diretiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A diretiva @model
especifica o tipo do modelo passado para o Razor Page. No exemplo anterior, a linha @model
torna a classe derivada de PageModel
disponível para o Razor Page. O modelo é usado nos auxiliares HTML @Html.DisplayNameFor
e @Html.DisplayFor
na página.
Examine a expressão lambda usada no auxiliar HTML a seguir:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O auxiliar HTML DisplayNameFor inspeciona a propriedade Title
referenciada na expressão lambda para determinar o nome de exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há nenhuma violação de acesso quando model
, model.Movie
ou model.Movie[0]
é null
ou 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, Home e Privacy. Cada página mostra o mesmo layout de menu. O layout do menu é implementado no arquivo Pages/Shared/_Layout.cshtml
.
Abra e examine o arquivo Pages/Shared/_Layout.cshtml
.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado em um único lugar.
- Aplicado a várias páginas no site.
Localize a linha @RenderBody()
. RenderBody
é um espaço reservado em que todas as exibições específicas da página são mostradas, encapsuladas na página de layout. Por exemplo, selecione o link Privacy e a exibição Pages/Privacy.cshtml
será renderizada dentro do método RenderBody
.
ViewData e layout
Considere a seguinte marcação do arquivo Pages/Movies/Index.cshtml
:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação realçada anteriormente é um exemplo de transição do Razor para C#. Os caracteres {
e }
circunscrevem um bloco de código C#.
A classe base PageModel
tem uma propriedade de dicionário ViewData
que pode ser usada para passar dados para uma Exibição. Adicione objetos ao dicionário ViewData
usando um padrão de valor de chave. No exemplo anterior, a propriedade Title
é adicionada ao dicionário ViewData
.
A propriedade Title
é usada no arquivo Pages/Shared/_Layout.cshtml
. A marcação a seguir mostra as primeiras linhas do arquivo _Layout.cshtml
.
<!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 comentário Razor. Ao contrário de comentários HTML <!-- -->
, comentários do Razor não são enviados ao cliente. Confira Documentos da Web do MDN: Introdução ao HTML para obter mais informações.
Atualizar o layout
Altere o elemento
<title>
no arquivoPages/Shared/_Layout.cshtml
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>
Localizar o elemento de âncora a seguir no arquivo
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Substitua o elemento anterior pela marcação a seguir:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
O elemento de âncora anterior é um Auxiliar de Marcas. Nesse caso, ele é o Auxiliar de Marcas de Âncora. O atributo e valor do auxiliar de marcas
asp-page="/Movies/Index"
cria um link para o/Movies/Index
Razor Page. O valor do atributoasp-area
está vazio e, portanto, a área não é usada no link. Confira Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie. Confira o arquivo _Layout.cshtml no GitHub caso tenha problemas.
Teste os links Home, RpMovie, Criar, Editar e Excluir. Cada página define o título, que pode ser visto na guia do navegador. Quando você coloca um indicador em uma página, o título é usado para o indicador.
Observação
Talvez você não consiga inserir casas decimais ou vírgulas no campo Price
. Para dar suporte à validação do jQuery para localidades de idiomas diferentes do inglês que usam uma vírgula (“,”) para um ponto decimal e formatos de data diferentes do inglês dos EUA, você deve tomar medidas para globalizar o aplicativo. Confira Problema 4076 do GitHub para obter instruções sobre como adicionar casas decimais.
A propriedade Layout
é definida no arquivo Pages/_ViewStart.cshtml
:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout Pages/Shared/_Layout.cshtml
para todos os arquivos do Razor na pasta Pages. Veja 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 método OnGet
inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, assim, Page
é retornado. Apresentamos um exemplo de inicialização de estado OnGet
posteriormente no tutorial. O método Page
cria um objeto PageResult
que renderiza a página Create.cshtml
.
A propriedade Movie
usa o atributo [BindProperty] para aceitar o model binding. Quando o formulário Criar posta os valores de formulário, o runtime do ASP.NET Core associa os valores postados ao modelo Movie
.
O método OnPostAsync
é 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 há algum erro de modelo, o formulário é reexibido juntamente com quaisquer dados de formulário postados. A maioria dos erros de modelo podem ser capturados no lado do cliente antes do formulário ser enviado. Um exemplo de um erro de modelo é postar, para o campo de data, um valor que não pode ser convertido em uma data. A validação do lado do cliente e a validação de modelo são abordadas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são salvos.
- O navegador é redirecionado para a página de índice.
Criar Razor Page
Examine o arquivo Pages/Movies/Create.cshtml
Razor Page:
@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");}
}
O Visual Studio exibe as marcas a seguir em uma fonte em negrito diferente usada em auxiliares de marcações:
<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 elemento <form method="post">
é um auxiliar de marcas de formulário. O auxiliar de marcas de formulário inclui automaticamente um token antifalsificação.
O mecanismo de scaffolding cria marcação do Razor para cada campo no modelo, exceto a 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 marcas de validação (<div asp-validation-summary
e <span asp-validation-for
) exibem erros de validação. A validação será abordada em mais detalhes posteriormente nesta série.
O auxiliar de marcas de rótulo (<label asp-for="Movie.Title" class="control-label"></label>
) gera a legenda do rótulo e o atributo [for]
para a propriedade Title
.
O auxiliar de marcas de entrada (<input asp-for="Movie.Title" class="form-control">
) usa os atributos DataAnnotations e produz os atributos HTML necessários para validação jQuery no lado do cliente.
Para obter mais informações sobre Auxiliares de Marcas, como <form method="post">
, confira Auxiliares de Marcas no ASP.NET Core.
Próximas etapas
As páginas Create, Delete, Details e Edit
Examine o modelo do Pages/Movies/Index.cshtml.cs
Page:
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 Pages são derivados de PageModel. Por convenção, a classe derivada de PageModel
é chamada de PageNameModel
. Por exemplo, a página Índice é chamada de IndexModel
.
O construtor usa 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;
}
Confira Código assíncrono para obter mais informações sobre a programação assíncrona com o Entity Framework.
Quando uma solicitação é feita à página, o método OnGetAsync
retorna uma lista de filmes para o Razor Page. Em um Razor Page, OnGetAsync
ou OnGet
é chamado para inicializar o estado da página. Nesse caso, OnGetAsync
obtém uma lista de filmes e os exibe.
Quando OnGet
retorna void
ou OnGetAsync
retorna Task
, então nenhuma instrução return é usada. Por exemplo, examine o Privacy Page:
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 for IActionResult ou Task<IActionResult>
, é necessário fornecer uma instrução de retorno. Por exemplo, o método Pages/Movies/Create.cshtml.cs
OnPostAsync
:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.Movie == null || Movie == null)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Examine o Pages/Movies/Index.cshtml
Razor Page:
@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>
O Razor pode fazer a transição do HTML em C# ou em marcação específica do Razor. Quando um símbolo @
é seguido por uma palavra-chave reservada do Razor, ele faz a transição para marcação específica do Razor, caso contrário, ele faz a transição para C#.
A diretiva @page
A diretiva do @page
Razor transforma o arquivo em uma ação do MVC, o que significa que ele pode manipular solicitações. @page
deve ser a primeira diretiva do Razor em uma página. @page
e @model
são exemplos de transição para a marcação específica do Razor. Confira RazorSintaxe para obter mais informações.
A diretiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A diretiva @model
especifica o tipo do modelo passado para o Razor Page. No exemplo anterior, a linha @model
torna a classe derivada de PageModel
disponível para o Razor Page. O modelo é usado nos auxiliares HTML @Html.DisplayNameFor
e @Html.DisplayFor
na página.
Examine a expressão lambda usada no auxiliar HTML a seguir:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O auxiliar HTML DisplayNameFor inspeciona a propriedade Title
referenciada na expressão lambda para determinar o nome de exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há nenhuma violação de acesso quando model
, model.Movie
ou model.Movie[0]
é null
ou 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, Home e Privacy. Cada página mostra o mesmo layout de menu. O layout do menu é implementado no arquivo Pages/Shared/_Layout.cshtml
.
Abra e examine o arquivo Pages/Shared/_Layout.cshtml
.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado em um único lugar.
- Aplicado a várias páginas no site.
Localize a linha @RenderBody()
. RenderBody
é um espaço reservado em que todas as exibições específicas da página são mostradas, encapsuladas na página de layout. Por exemplo, selecione o link Privacy e a exibição Pages/Privacy.cshtml
será renderizada dentro do método RenderBody
.
ViewData e layout
Considere a seguinte marcação do arquivo Pages/Movies/Index.cshtml
:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação realçada anteriormente é um exemplo de transição do Razor para C#. Os caracteres {
e }
circunscrevem um bloco de código C#.
A classe base PageModel
tem uma propriedade de dicionário ViewData
que pode ser usada para passar dados para uma Exibição. Adicione objetos ao dicionário ViewData
usando um padrão de valor de chave. No exemplo anterior, a propriedade Title
é adicionada ao dicionário ViewData
.
A propriedade Title
é usada no arquivo Pages/Shared/_Layout.cshtml
. A marcação a seguir mostra as primeiras linhas do arquivo _Layout.cshtml
.
<!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 comentário Razor. Ao contrário de comentários HTML <!-- -->
, comentários do Razor não são enviados ao cliente. Confira Documentos da Web do MDN: Introdução ao HTML para obter mais informações.
Atualizar o layout
Altere o elemento
<title>
no arquivoPages/Shared/_Layout.cshtml
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>
Localizar o elemento de âncora a seguir no arquivo
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Substitua o elemento anterior pela marcação a seguir:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
O elemento de âncora anterior é um Auxiliar de Marcas. Nesse caso, ele é o Auxiliar de Marcas de Âncora. O atributo e valor do auxiliar de marcas
asp-page="/Movies/Index"
cria um link para o/Movies/Index
Razor Page. O valor do atributoasp-area
está vazio e, portanto, a área não é usada no link. Confira Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie. Confira o arquivo _Layout.cshtml no GitHub caso tenha problemas.
Teste os links Home, RpMovie, Criar, Editar e Excluir. Cada página define o título, que pode ser visto na guia do navegador. Quando você coloca um indicador em uma página, o título é usado para o indicador.
Observação
Talvez você não consiga inserir casas decimais ou vírgulas no campo Price
. Para dar suporte à validação do jQuery para localidades de idiomas diferentes do inglês que usam uma vírgula (“,”) para um ponto decimal e formatos de data diferentes do inglês dos EUA, você deve tomar medidas para globalizar o aplicativo. Confira Problema 4076 do GitHub para obter instruções sobre como adicionar casas decimais.
A propriedade Layout
é definida no arquivo Pages/_ViewStart.cshtml
:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout Pages/Shared/_Layout.cshtml
para todos os arquivos do Razor na pasta Pages. Veja 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 método OnGet
inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, assim, Page
é retornado. Apresentamos um exemplo de inicialização de estado OnGet
posteriormente no tutorial. O método Page
cria um objeto PageResult
que renderiza a página Create.cshtml
.
A propriedade Movie
usa o atributo [BindProperty] para aceitar o model binding. Quando o formulário Criar posta os valores de formulário, o runtime do ASP.NET Core associa os valores postados ao modelo Movie
.
O método OnPostAsync
é 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 há algum erro de modelo, o formulário é reexibido juntamente com quaisquer dados de formulário postados. A maioria dos erros de modelo podem ser capturados no lado do cliente antes do formulário ser enviado. Um exemplo de um erro de modelo é postar, para o campo de data, um valor que não pode ser convertido em uma data. A validação do lado do cliente e a validação de modelo são abordadas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são salvos.
- O navegador é redirecionado para a página de índice.
Criar Razor Page
Examine o arquivo Pages/Movies/Create.cshtml
Razor Page:
@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");}
}
O Visual Studio exibe as marcas a seguir em uma fonte em negrito diferente usada em auxiliares de marcações:
<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 elemento <form method="post">
é um auxiliar de marcas de formulário. O auxiliar de marcas de formulário inclui automaticamente um token antifalsificação.
O mecanismo de scaffolding cria marcação do Razor para cada campo no modelo, exceto a 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 marcas de validação (<div asp-validation-summary
e <span asp-validation-for
) exibem erros de validação. A validação será abordada em mais detalhes posteriormente nesta série.
O auxiliar de marcas de rótulo (<label asp-for="Movie.Title" class="control-label"></label>
) gera a legenda do rótulo e o atributo [for]
para a propriedade Title
.
O auxiliar de marcas de entrada (<input asp-for="Movie.Title" class="form-control">
) usa os atributos DataAnnotations e produz os atributos HTML necessários para validação jQuery no lado do cliente.
Para obter mais informações sobre Auxiliares de Marcas, como <form method="post">
, confira Auxiliares de Marcas no ASP.NET Core.
Próximas etapas
As páginas Create, Delete, Details e Edit
Examine o modelo do Pages/Movies/Index.cshtml.cs
Page:
// 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 Pages são derivados de PageModel
. Por convenção, a classe derivada de PageModel
é chamada de <PageName>Model
. O construtor usa 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;
}
Confira Código assíncrono para obter mais informações sobre a programação assíncrona com o Entity Framework.
Quando uma solicitação é feita à página, o método OnGetAsync
retorna uma lista de filmes para o Razor Page. Em um Razor Page, OnGetAsync
ou OnGet
é chamado para inicializar o estado da página. Nesse caso, OnGetAsync
obtém uma lista de filmes e os exibe.
Quando OnGet
retorna void
ou OnGetAsync
retorna Task
, então nenhuma instrução return é usada. Por exemplo, o Privacy Page:
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
Quando o tipo de retorno for IActionResult
ou Task<IActionResult>
, é necessário fornecer uma instrução de retorno. Por exemplo, o método Pages/Movies/Create.cshtml.cs
OnPostAsync
:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
Examine o Pages/Movies/Index.cshtml
Razor Page:
@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>
O Razor pode fazer a transição do HTML em C# ou em marcação específica do Razor. Quando um símbolo @
é seguido por uma palavra-chave reservada do Razor, ele faz a transição para marcação específica do Razor, caso contrário, ele faz a transição para C#.
A diretiva @page
A diretiva do @page
Razor transforma o arquivo em uma ação do MVC, o que significa que ele pode manipular solicitações. @page
deve ser a primeira diretiva do Razor em uma página. @page
e @model
são exemplos de transição para a marcação específica do Razor. Confira RazorSintaxe para obter mais informações.
A diretiva @model
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
A diretiva @model
especifica o tipo do modelo passado para o Razor Page. No exemplo anterior, a linha @model
torna a classe derivada de PageModel
disponível para o Razor Page. O modelo é usado nos auxiliares HTML @Html.DisplayNameFor
e @Html.DisplayFor
na página.
Examine a expressão lambda usada no auxiliar HTML a seguir:
@Html.DisplayNameFor(model => model.Movie[0].Title)
O auxiliar HTML DisplayNameFor inspeciona a propriedade Title
referenciada na expressão lambda para determinar o nome de exibição. A expressão lambda é inspecionada em vez de avaliada. Isso significa que não há nenhuma violação de acesso quando model
, model.Movie
ou model.Movie[0]
é null
ou 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, Home e Privacy. Cada página mostra o mesmo layout de menu. O layout do menu é implementado no arquivo Pages/Shared/_Layout.cshtml
.
Abra e examine o arquivo Pages/Shared/_Layout.cshtml
.
Os modelos de layout permitem que o layout do contêiner HTML seja:
- Especificado em um único lugar.
- Aplicado a várias páginas no site.
Localize a linha @RenderBody()
. RenderBody
é um espaço reservado em que todas as exibições específicas da página são mostradas, encapsuladas na página de layout. Por exemplo, selecione o link Privacy e a exibição Pages/Privacy.cshtml
será renderizada dentro do método RenderBody
.
ViewData e layout
Considere a seguinte marcação do arquivo Pages/Movies/Index.cshtml
:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
A marcação realçada anteriormente é um exemplo de transição do Razor para C#. Os caracteres {
e }
circunscrevem um bloco de código C#.
A classe base PageModel
tem uma propriedade de dicionário ViewData
que pode ser usada para passar dados para uma Exibição. Adicione objetos ao dicionário ViewData
usando um padrão de valor de chave. No exemplo anterior, a propriedade Title
é adicionada ao dicionário ViewData
.
A propriedade Title
é usada no arquivo Pages/Shared/_Layout.cshtml
. A marcação a seguir mostra as primeiras linhas do arquivo _Layout.cshtml
.
<!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 comentário Razor. Ao contrário de comentários HTML <!-- -->
, comentários do Razor não são enviados ao cliente. Confira Documentos da Web do MDN: Introdução ao HTML para obter mais informações.
Atualizar o layout
Altere o elemento
<title>
no arquivoPages/Shared/_Layout.cshtml
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>
Localizar o elemento de âncora a seguir no arquivo
Pages/Shared/_Layout.cshtml
.<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
Substitua o elemento anterior pela marcação a seguir:
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
O elemento de âncora anterior é um Auxiliar de Marcas. Nesse caso, ele é o Auxiliar de Marcas de Âncora. O atributo e valor do auxiliar de marcas
asp-page="/Movies/Index"
cria um link para o/Movies/Index
Razor Page. O valor do atributoasp-area
está vazio e, portanto, a área não é usada no link. Confira Áreas para obter mais informações.Salve as alterações e teste o aplicativo selecionando o link RpMovie. Confira o arquivo _Layout.cshtml no GitHub caso tenha problemas.
Teste os links Home, RpMovie, Criar, Editar e Excluir. Cada página define o título, que pode ser visto na guia do navegador. Quando você coloca um indicador em uma página, o título é usado para o indicador.
Observação
Talvez você não consiga inserir casas decimais ou vírgulas no campo Price
. Para dar suporte à validação do jQuery para localidades de idiomas diferentes do inglês que usam uma vírgula (“,”) para um ponto decimal e formatos de data diferentes do inglês dos EUA, você deve tomar medidas para globalizar o aplicativo. Confira Problema 4076 do GitHub para obter instruções sobre como adicionar casas decimais.
A propriedade Layout
é definida no arquivo Pages/_ViewStart.cshtml
:
@{
Layout = "_Layout";
}
A marcação anterior define o arquivo de layout Pages/Shared/_Layout.cshtml
para todos os arquivos do Razor na pasta Pages. Veja 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 método OnGet
inicializa qualquer estado necessário para a página. A página Criar não tem nenhum estado para inicializar, assim, Page
é retornado. Apresentamos um exemplo de inicialização de estado OnGet
posteriormente no tutorial. O método Page
cria um objeto PageResult
que renderiza a página Create.cshtml
.
A propriedade Movie
usa o atributo [BindProperty] para aceitar o model binding. Quando o formulário Criar posta os valores de formulário, o runtime do ASP.NET Core associa os valores postados ao modelo Movie
.
O método OnPostAsync
é 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 há algum erro de modelo, o formulário é reexibido juntamente com quaisquer dados de formulário postados. A maioria dos erros de modelo podem ser capturados no lado do cliente antes do formulário ser enviado. Um exemplo de um erro de modelo é postar, para o campo de data, um valor que não pode ser convertido em uma data. A validação do lado do cliente e a validação de modelo são abordadas mais adiante no tutorial.
Se não houver erros de modelo:
- Os dados são salvos.
- O navegador é redirecionado para a página de índice.
Criar Razor Page
Examine o arquivo Pages/Movies/Create.cshtml
Razor Page:
@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");}
}
O Visual Studio exibe as marcas a seguir em uma fonte em negrito diferente usada em auxiliares de marcações:
<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 elemento <form method="post">
é um auxiliar de marcas de formulário. O auxiliar de marcas de formulário inclui automaticamente um token antifalsificação.
O mecanismo de scaffolding cria marcação do Razor para cada campo no modelo, exceto a 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 marcas de validação (<div asp-validation-summary
e <span asp-validation-for
) exibem erros de validação. A validação será abordada em mais detalhes posteriormente nesta série.
O auxiliar de marcas de rótulo (<label asp-for="Movie.Title" class="control-label"></label>
) gera a legenda do rótulo e o atributo [for]
para a propriedade Title
.
O auxiliar de marcas de entrada (<input asp-for="Movie.Title" class="form-control">
) usa os atributos DataAnnotations e produz os atributos HTML necessários para validação jQuery no lado do cliente.
Para obter mais informações sobre Auxiliares de Marcas, como <form method="post">
, confira Auxiliares de Marcas no ASP.NET Core.