Parte 8 da série de tutoriais sobre o Razor Pages

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.

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.

De Rick Anderson

Nesta seção, a lógica de validação é adicionada para o modelo Movie. As regras de validação são impostas sempre que um usuário cria ou edita um filme.

Validação

Um princípio-chave do desenvolvimento de software é chamado DRY (“Don't Repeat Yourself”). O Razor Pages incentiva o desenvolvimento em que a funcionalidade é especificada uma vez e, depois, reflete-se em todo o aplicativo. O DRY pode ajudar a:

  • Reduzir a quantidade de código em um aplicativo.
  • Fazer com que o código seja menos propenso a erros e mais fácil de ser testado e mantido.

O suporte à validação fornecido pelo Razor Pages e pelo Entity Framework é um bom exemplo do princípio DRY:

  • As regras de validação são especificadas declarativamente em um só lugar, na classe de modelo.
  • As regras são impostas em todos os lugares do aplicativo.

Adicionar regras de validação ao modelo de filme

O namespace System.ComponentModel.DataAnnotations fornece:

  • Um conjunto de atributos de validação internos aplicados de forma declarativa a uma classe ou propriedade.
  • Atributos de formatação como [DataType], que ajudam com a formatação e não fornecem nenhuma validação.

Atualize a classe Movie para aproveitar os atributos de validação [Required], [StringLength], [RegularExpression] e [Range] internos.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string Title { get; set; } = string.Empty;

    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; } = string.Empty;

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string Rating { get; set; } = string.Empty;
}

Os atributos de validação especificam o comportamento a ser imposto nas propriedades de modelo às quais eles são aplicados:

  • Os atributos [Required] e [MinimumLength] indicam que uma propriedade deve ter um valor. Nada impede que um usuário insira espaço em branco para atender a essa validação.

  • O atributo [RegularExpression] é usado para limitar quais caracteres podem ser inseridos. No código anterior, Genre:

    • Deve usar apenas letras.
    • A primeira letra precisa ser maiúscula. Espaços em branco são permitidos, enquanto números e caracteres especiais não são.
  • O RegularExpressionRating:

    • Exige que o primeiro caractere seja uma letra maiúscula.
    • Permite caracteres especiais e números nos espaços subsequentes. "PG-13" é válido para uma classificação, mas é um erro em Genre.
  • O atributo [Range] restringe um valor a um intervalo especificado.

  • O atributo [StringLength] define o tamanho máximo de uma propriedade de cadeia de caracteres e, opcionalmente, seu tamanho mínimo.

  • Os tipos de valor, como decimal, int, float, DateTime são inerentemente necessários e não precisam do atributo [Required].

As regras de validação anteriores são usadas para demonstração, elas não são ideais para um sistema de produção. Por exemplo, o anterior impede a entrada de um filme com apenas dois caracteres e não permite caracteres especiais em Genre.

Ter as regras de validação automaticamente impostas pelo ASP.NET Core ajuda a:

  • Tornar o aplicativo mais robusto.
  • Reduzir as chances de salvar dados inválidos no banco de dados.

Interface do usuário de erro de validação no Razor Pages

Execute o aplicativo e navegue para Pages/Movies.

Selecione o link Criar Novo. Preencha o formulário com alguns valores inválidos. Quando a validação do lado do cliente do jQuery detecta o erro, ela exibe uma mensagem de erro.

Formulário da exibição de filmes com vários erros de validação do lado do cliente do jQuery

Observação

Talvez você não consiga inserir vírgulas decimais em campos decimais. 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 o comentário 4076 do GitHub para obter instruções sobre como adicionar casas decimais.

Observe como o formulário renderizou automaticamente uma mensagem de erro de validação em cada campo que contém um valor inválido. Os erros são impostos no lado do cliente, usando o JavaScript e o jQuery, e no lado do servidor, quando um usuário tem o JavaScript desabilitado.

Uma vantagem significativa é que nenhuma alteração de código foi necessária nas páginas Criar ou Editar. Após a aplicação das anotações de dados ao modelo, a interface do usuário de validação é habilitada. O Razor Pages criado neste tutorial selecionaram automaticamente as regras de validação, usando os atributos de validação nas propriedades da classe do modelo Movie. Validação do teste usando a página Editar: a mesma validação é aplicada.

Os dados de formulário não serão postados no servidor enquanto houver erros de validação do lado do cliente. Verifique se os dados de formulário não são postados por uma ou mais das seguintes abordagens:

  • Coloque um ponto de interrupção no método OnPostAsync. Envie o formulário selecionando Criar ou Salvar. O ponto de interrupção nunca é atingido.
  • Use a ferramenta Fiddler.
  • Use as ferramentas do desenvolvedor do navegador para monitorar o tráfego de rede.

Validação do servidor

Quando o JavaScript está desabilitado no navegador, o envio do formulário com erros será postado no servidor.

(Opcional) Teste a validação do servidor:

  1. Desabilite o JavaScript no navegador. O JavaScript pode ser desabilitado usando as ferramentas de desenvolvedor do navegador. Se o JavaScript não puder ser desabilitado no navegador, tente outro navegador.

  2. Defina um ponto de interrupção no método OnPostAsync da página Criar ou Editar.

  3. Envie um formulário com dados inválidos.

  4. Verifique se o estado do modelo é inválido:

     if (!ModelState.IsValid)
     {
        return Page();
     }
    

Como alternativa, Desabilite a validação do lado do cliente no servidor.

O código a seguir mostra uma parte da página Create.cshtml gerada anteriormente com scaffold no tutorial. Ele é usado pelas páginas Criar e Editar para:

  • Exibir o formulário inicial.
  • Exibir novamente o formulário em caso de erro.
<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>

O Auxiliar de Marcação de Entrada usa os atributos de DataAnnotations e produz os atributos HTML necessários para a Validação do jQuery no lado do cliente. O Auxiliar de Marcação de Validação exibe erros de validação. Consulte Validação para obter mais informações.

As páginas Criar e Editar não têm nenhuma regra de validação. As regras de validação e as cadeias de caracteres de erro são especificadas somente na classe Movie. Essas regras de validação são aplicadas automaticamente ao Razor Pages que edita o modelo Movie.

Quando a lógica de validação precisa ser alterada, ela é feita apenas no modelo. A validação é aplicada de forma consistente em todo o aplicativo, a lógica de validação é definida em um único lugar. A validação em um único lugar ajuda a manter o código limpo e facilita sua manutenção e atualização.

Usar atributos DataType

Examine a classe Movie. O namespace System.ComponentModel.DataAnnotations fornece atributos de formatação, além do conjunto interno de atributos de validação. O atributo [DataType] é aplicado às propriedades ReleaseDate e Price.

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

Os atributos [DataType] fornecem:

  • Dicas para o mecanismo de exibição para formatar os dados.
  • Fornece atributos como <a> para URLs e <a href="mailto:EmailAddress.com"> para email.

Use o atributo [RegularExpression] para validar o formato dos dados. O atributo [DataType] é usado para especificar um tipo de dados mais específico do que o tipo intrínseco de banco de dados. Os atributos [DataType] não são atributos de validação. No aplicativo de exemplo, apenas a data é exibida, sem a hora.

A enumeração DataType fornece muitos tipos de dados, como Date, Time, PhoneNumber, Currency, EmailAddress e muito mais.

Os atributos [DataType]:

  • Pode permitir que o aplicativo forneça automaticamente recursos específicos a um tipo. Por exemplo, um link mailto: pode ser criado para DataType.EmailAddress.
  • Pode fornecer um seletor de dados DataType.Date em navegadores que dão suporte a HTML5.
  • Emite atributos HTML 5 data-, pronunciados "data dash", que são consumidos por navegadores HTML 5.
  • Não forneça nenhuma validação.

DataType.Date não especifica o formato da data exibida. Por padrão, o campo de dados é exibido de acordo com os formatos padrão com base nas CultureInfo do servidor.

A anotação de dados [Column(TypeName = "decimal(18, 2)")] é necessária para que o Entity Framework Core possa mapear corretamente o Price para a moeda no banco de dados. Para obter mais informações, veja Tipos de Dados.

O atributo [DisplayFormat] é usado para especificar explicitamente o formato de data:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

A configuração ApplyFormatInEditMode especifica que a formatação será aplicada quando o valor for exibido para edição. Talvez esse comportamento não seja desejado para alguns campos. Por exemplo, em valores monetários, o símbolo de moeda não costuma ser desejado na interface do usuário de edição.

O atributo [DisplayFormat] pode ser usado por si só, mas geralmente é uma boa ideia usar o atributo [DataType]. O atributo [DataType] transmite a semântica dos dados em vez de como renderizá-los em uma tela. O atributo [DataType] oferece os seguintes benefícios que não estão disponíveis com [DisplayFormat]:

  • O navegador pode habilitar os recursos do HTML5, por exemplo, mostrar um controle de calendário, o símbolo de moeda apropriado à localidade, links de email etc.
  • Por padrão, o navegador renderiza os dados usando o formato correto de acordo com a localidade.
  • O atributo [DataType] pode permitir que a estrutura ASP.NET Core escolha o modelo de campo correto para renderizar os dados. O DisplayFormat, se usado por si só, usa o modelo de cadeia de caracteres.

Observação: a validação do jQuery não funciona com os atributos [Range] e DateTime. Por exemplo, o seguinte código sempre exibirá um erro de validação do lado do cliente, mesmo quando a data estiver no intervalo especificado:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

É uma boa prática compilar datas rígidas nos modelos e, portanto, o uso do atributo [Range] e de DateTime não é recomendado. Use Configuração para intervalos de datas e outros valores que estão sujeitos a alterações frequentes em vez de especificá-la no código.

O seguinte código mostra como combinar atributos em uma linha:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; } = string.Empty;

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; } = string.Empty;

    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; } = string.Empty;
}

Introdução ao Razor Pages e EF Core mostra operações de EF Core avançadas com o Razor Pages.

Aplicar migrações

As DataAnnotations aplicadas à classe alteram o esquema. Por exemplo, as DataAnnotations aplicadas ao campo Title:

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; } = string.Empty;
  • Limitam os caracteres a 60.
  • Não permitem um valor null.

Atualmente a tabela Movie tem o seguinte esquema:

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (MAX)  NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (MAX)  NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

As alterações do esquema anterior não fazem com que o EF lance uma exceção. No entanto, crie uma migração de forma que o esquema seja consistente com o modelo.

No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes. No PMC, insira os seguintes comandos:

Add-Migration New_DataAnnotations
Update-Database

Update-Database executa o método Up da classe New_DataAnnotations.

Examine o método Up:

public partial class New_DataAnnotations : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "Title",
            table: "Movie",
            type: "nvarchar(60)",
            maxLength: 60,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Rating",
            table: "Movie",
            type: "nvarchar(5)",
            maxLength: 5,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Genre",
            table: "Movie",
            type: "nvarchar(30)",
            maxLength: 30,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");
    }

A tabela Movie atualizada tem o seguinte esquema:

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (60)   NOT NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (30)   NOT NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (5)    NOT NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Publicar no Azure

Para obter informações sobre como fazer uma implantação no Azure, confira Tutorial: Criar um aplicativo ASP.NET Core no Azure com o Banco de Dados SQL.

Obrigado por concluir esta introdução ao Razor Pages. A Introdução ao Razor Pages e ao EF Core é um excelente acompanhamento para este tutorial.

Recursos adicionais

Próximas etapas

Nesta seção, a lógica de validação é adicionada para o modelo Movie. As regras de validação são impostas sempre que um usuário cria ou edita um filme.

Validação

Um princípio-chave do desenvolvimento de software é chamado DRY (“Don't Repeat Yourself”). O Razor Pages incentiva o desenvolvimento em que a funcionalidade é especificada uma vez e, depois, reflete-se em todo o aplicativo. O DRY pode ajudar a:

  • Reduzir a quantidade de código em um aplicativo.
  • Fazer com que o código seja menos propenso a erros e mais fácil de ser testado e mantido.

O suporte à validação fornecido pelo Razor Pages e pelo Entity Framework é um bom exemplo do princípio DRY:

  • As regras de validação são especificadas declarativamente em um só lugar, na classe de modelo.
  • As regras são impostas em todos os lugares do aplicativo.

Adicionar regras de validação ao modelo de filme

O namespace System.ComponentModel.DataAnnotations fornece:

  • Um conjunto de atributos de validação internos aplicados de forma declarativa a uma classe ou propriedade.
  • Atributos de formatação como [DataType], que ajudam com a formatação e não fornecem nenhuma validação.

Atualize a classe Movie para aproveitar os atributos de validação [Required], [StringLength], [RegularExpression] e [Range] internos.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string Title { get; set; } = string.Empty;

    // [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; } = string.Empty;

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string Rating { get; set; } = string.Empty;
}

Os atributos de validação especificam o comportamento a ser imposto nas propriedades de modelo às quais eles são aplicados:

  • Os atributos [Required] e [MinimumLength] indicam que uma propriedade deve ter um valor. Nada impede que um usuário insira espaço em branco para atender a essa validação.

  • O atributo [RegularExpression] é usado para limitar quais caracteres podem ser inseridos. No código anterior, Genre:

    • Deve usar apenas letras.
    • A primeira letra deve ser maiúscula. Espaços em branco são permitidos, enquanto números e caracteres especiais não são.
  • O RegularExpressionRating:

    • Exige que o primeiro caractere seja uma letra maiúscula.
    • Permite caracteres especiais e números nos espaços subsequentes. "PG-13" é válido para uma classificação, mas é um erro em Genre.
  • O atributo [Range] restringe um valor a um intervalo especificado.

  • O atributo [StringLength] define o tamanho máximo de uma propriedade de cadeia de caracteres e, opcionalmente, seu tamanho mínimo.

  • Os tipos de valor, como decimal, int, float, DateTime são inerentemente necessários e não precisam do atributo [Required].

As regras de validação anteriores são usadas para demonstração, elas não são ideais para um sistema de produção. Por exemplo, o anterior impede a entrada de um filme com apenas dois caracteres e não permite caracteres especiais em Genre.

Ter as regras de validação automaticamente impostas pelo ASP.NET Core ajuda a:

  • Tornar o aplicativo mais robusto.
  • Reduzir as chances de salvar dados inválidos no banco de dados.

Interface do usuário de erro de validação no Razor Pages

Execute o aplicativo e navegue para Pages/Movies.

Selecione o link Criar Novo. Preencha o formulário com alguns valores inválidos. Quando a validação do lado do cliente do jQuery detecta o erro, ela exibe uma mensagem de erro.

Formulário da exibição de filmes com vários erros de validação do lado do cliente do jQuery

Observação

Talvez você não consiga inserir vírgulas decimais em campos decimais. 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 o comentário 4076 do GitHub para obter instruções sobre como adicionar casas decimais.

Observe como o formulário renderizou automaticamente uma mensagem de erro de validação em cada campo que contém um valor inválido. Os erros são impostos no lado do cliente, usando o JavaScript e o jQuery, e no lado do servidor, quando um usuário tem o JavaScript desabilitado.

Uma vantagem significativa é que nenhuma alteração de código foi necessária nas páginas Criar ou Editar. Após a aplicação das anotações de dados ao modelo, a interface do usuário de validação é habilitada. O Razor Pages criado neste tutorial selecionaram automaticamente as regras de validação, usando os atributos de validação nas propriedades da classe do modelo Movie. Validação do teste usando a página Editar: a mesma validação é aplicada.

Os dados de formulário não serão postados no servidor enquanto houver erros de validação do lado do cliente. Verifique se os dados de formulário não são postados por uma ou mais das seguintes abordagens:

  • Coloque um ponto de interrupção no método OnPostAsync. Envie o formulário selecionando Criar ou Salvar. O ponto de interrupção nunca é atingido.
  • Use a ferramenta Fiddler.
  • Use as ferramentas do desenvolvedor do navegador para monitorar o tráfego de rede.

Validação do servidor

Quando o JavaScript está desabilitado no navegador, o envio do formulário com erros será postado no servidor.

(Opcional) Teste a validação do servidor:

  1. Desabilite o JavaScript no navegador. O JavaScript pode ser desabilitado usando as ferramentas de desenvolvedor do navegador. Se o JavaScript não puder ser desabilitado no navegador, tente outro navegador.

  2. Defina um ponto de interrupção no método OnPostAsync da página Criar ou Editar.

  3. Envie um formulário com dados inválidos.

  4. Verifique se o estado do modelo é inválido:

     if (!ModelState.IsValid)
     {
        return Page();
     }
    

Como alternativa, Desabilite a validação do lado do cliente no servidor.

O código a seguir mostra uma parte da página Create.cshtml gerada anteriormente com scaffold no tutorial. Ele é usado pelas páginas Criar e Editar para:

  • Exibir o formulário inicial.
  • Exibir novamente o formulário em caso de erro.
<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>

O Auxiliar de Marcação de Entrada usa os atributos de DataAnnotations e produz os atributos HTML necessários para a Validação do jQuery no lado do cliente. O Auxiliar de Marcação de Validação exibe erros de validação. Consulte Validação para obter mais informações.

As páginas Criar e Editar não têm nenhuma regra de validação. As regras de validação e as cadeias de caracteres de erro são especificadas somente na classe Movie. Essas regras de validação são aplicadas automaticamente ao Razor Pages que edita o modelo Movie.

Quando a lógica de validação precisa ser alterada, ela é feita apenas no modelo. A validação é aplicada de forma consistente em todo o aplicativo, a lógica de validação é definida em um único lugar. A validação em um único lugar ajuda a manter o código limpo e facilita sua manutenção e atualização.

Usar atributos DataType

Examine a classe Movie. O namespace System.ComponentModel.DataAnnotations fornece atributos de formatação, além do conjunto interno de atributos de validação. O atributo [DataType] é aplicado às propriedades ReleaseDate e Price.

// [Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

Os atributos [DataType] fornecem:

  • Dicas para o mecanismo de exibição para formatar os dados.
  • Fornece atributos como <a> para URLs e <a href="mailto:EmailAddress.com"> para email.

Use o atributo [RegularExpression] para validar o formato dos dados. O atributo [DataType] é usado para especificar um tipo de dados mais específico do que o tipo intrínseco de banco de dados. Os atributos [DataType] não são atributos de validação. No aplicativo de exemplo, apenas a data é exibida, sem a hora.

A enumeração DataType fornece muitos tipos de dados, como Date, Time, PhoneNumber, Currency, EmailAddress e muito mais.

Os atributos [DataType]:

  • Pode permitir que o aplicativo forneça automaticamente recursos específicos a um tipo. Por exemplo, um link mailto: pode ser criado para DataType.EmailAddress.
  • Pode fornecer um seletor de dados DataType.Date em navegadores que dão suporte a HTML5.
  • Emite atributos HTML 5 data-, pronunciados "data dash", que são consumidos por navegadores HTML 5.
  • Não forneça nenhuma validação.

DataType.Date não especifica o formato da data exibida. Por padrão, o campo de dados é exibido de acordo com os formatos padrão com base nas CultureInfo do servidor.

A anotação de dados [Column(TypeName = "decimal(18, 2)")] é necessária para que o Entity Framework Core possa mapear corretamente o Price para a moeda no banco de dados. Para obter mais informações, veja Tipos de Dados.

O atributo [DisplayFormat] é usado para especificar explicitamente o formato de data:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

A configuração ApplyFormatInEditMode especifica que a formatação será aplicada quando o valor for exibido para edição. Talvez esse comportamento não seja desejado para alguns campos. Por exemplo, em valores monetários, o símbolo de moeda não costuma ser desejado na interface do usuário de edição.

O atributo [DisplayFormat] pode ser usado por si só, mas geralmente é uma boa ideia usar o atributo [DataType]. O atributo [DataType] transmite a semântica dos dados em vez de como renderizá-los em uma tela. O atributo [DataType] oferece os seguintes benefícios que não estão disponíveis com [DisplayFormat]:

  • O navegador pode habilitar os recursos do HTML5, por exemplo, mostrar um controle de calendário, o símbolo de moeda apropriado à localidade, links de email etc.
  • Por padrão, o navegador renderiza os dados usando o formato correto de acordo com a localidade.
  • O atributo [DataType] pode permitir que a estrutura ASP.NET Core escolha o modelo de campo correto para renderizar os dados. O DisplayFormat, se usado por si só, usa o modelo de cadeia de caracteres.

Observação: a validação do jQuery não funciona com os atributos [Range] e DateTime. Por exemplo, o seguinte código sempre exibirá um erro de validação do lado do cliente, mesmo quando a data estiver no intervalo especificado:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

É uma boa prática compilar datas rígidas nos modelos e, portanto, o uso do atributo [Range] e de DateTime não é recomendado. Use Configuração para intervalos de datas e outros valores que estão sujeitos a alterações frequentes em vez de especificá-la no código.

O seguinte código mostra como combinar atributos em uma linha:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; } = string.Empty;

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; } = string.Empty;

    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; } = string.Empty;
}

Introdução ao Razor Pages e EF Core mostra operações de EF Core avançadas com o Razor Pages.

Aplicar migrações

As DataAnnotations aplicadas à classe alteram o esquema. Por exemplo, as DataAnnotations aplicadas ao campo Title:

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; } = string.Empty;
  • Limitam os caracteres a 60.
  • Não permitem um valor null.

Atualmente a tabela Movie tem o seguinte esquema:

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (MAX)  NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (MAX)  NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

As alterações do esquema anterior não fazem com que o EF lance uma exceção. No entanto, crie uma migração de forma que o esquema seja consistente com o modelo.

No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes. No PMC, insira os seguintes comandos:

Add-Migration New_DataAnnotations
Update-Database

Update-Database executa o método Up da classe New_DataAnnotations.

Examine o método Up:

public partial class NewDataAnnotations : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "Title",
            table: "Movie",
            type: "nvarchar(60)",
            maxLength: 60,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Rating",
            table: "Movie",
            type: "nvarchar(5)",
            maxLength: 5,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Genre",
            table: "Movie",
            type: "nvarchar(30)",
            maxLength: 30,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");
    }

A tabela Movie atualizada tem o seguinte esquema:

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (60)   NOT NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (30)   NOT NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (5)    NOT NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Publicar no Azure

Para obter informações sobre como fazer uma implantação no Azure, confira Tutorial: Criar um aplicativo ASP.NET Core no Azure com o Banco de Dados SQL.

Obrigado por concluir esta introdução ao Razor Pages. A Introdução ao Razor Pages e ao EF Core é um excelente acompanhamento para este tutorial.

Recursos adicionais

Próximas etapas

Nesta seção, a lógica de validação é adicionada para o modelo Movie. As regras de validação são impostas sempre que um usuário cria ou edita um filme.

Validação

Um princípio-chave do desenvolvimento de software é chamado DRY (“Don't Repeat Yourself”). O Razor Pages incentiva o desenvolvimento em que a funcionalidade é especificada uma vez e, depois, reflete-se em todo o aplicativo. O DRY pode ajudar a:

  • Reduzir a quantidade de código em um aplicativo.
  • Fazer com que o código seja menos propenso a erros e mais fácil de ser testado e mantido.

O suporte à validação fornecido pelo Razor Pages e pelo Entity Framework é um bom exemplo do princípio DRY:

  • As regras de validação são especificadas declarativamente em um só lugar, na classe de modelo.
  • As regras são impostas em todos os lugares do aplicativo.

Adicionar regras de validação ao modelo de filme

O namespace System.ComponentModel.DataAnnotations fornece:

  • Um conjunto de atributos de validação internos aplicados de forma declarativa a uma classe ou propriedade.
  • Atributos de formatação como [DataType], que ajudam com a formatação e não fornecem nenhuma validação.

Atualize a classe Movie para aproveitar os atributos de validação [Required], [StringLength], [RegularExpression] e [Range] internos.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [StringLength(60, MinimumLength = 3)]
        [Required]
        public string Title { get; set; } = string.Empty;

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Range(1, 100)]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
        [Required]
        [StringLength(30)]
        public string Genre { get; set; } = string.Empty;

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
        [StringLength(5)]
        [Required]
        public string Rating { get; set; } = string.Empty;
    }
}

Os atributos de validação especificam o comportamento a ser imposto nas propriedades de modelo às quais eles são aplicados:

  • Os atributos [Required] e [MinimumLength] indicam que uma propriedade deve ter um valor. Nada impede que um usuário insira espaço em branco para atender a essa validação.

  • O atributo [RegularExpression] é usado para limitar quais caracteres podem ser inseridos. No código anterior, Genre:

    • Deve usar apenas letras.
    • A primeira letra deve ser maiúscula. Espaços em branco são permitidos, enquanto números e caracteres especiais não são.
  • O RegularExpressionRating:

    • Exige que o primeiro caractere seja uma letra maiúscula.
    • Permite caracteres especiais e números nos espaços subsequentes. "PG-13" é válido para uma classificação, mas é um erro em Genre.
  • O atributo [Range] restringe um valor a um intervalo especificado.

  • O atributo [StringLength] define o tamanho máximo de uma propriedade de cadeia de caracteres e, opcionalmente, seu tamanho mínimo.

  • Os tipos de valor, como decimal, int, float, DateTime são inerentemente necessários e não precisam do atributo [Required].

As regras de validação anteriores são usadas para demonstração, elas não são ideais para um sistema de produção. Por exemplo, o anterior impede a entrada de um filme com apenas dois caracteres e não permite caracteres especiais em Genre.

Ter as regras de validação automaticamente impostas pelo ASP.NET Core ajuda a:

  • Tornar o aplicativo mais robusto.
  • Reduzir as chances de salvar dados inválidos no banco de dados.

Interface do usuário de erro de validação no Razor Pages

Execute o aplicativo e navegue para Pages/Movies.

Selecione o link Criar Novo. Preencha o formulário com alguns valores inválidos. Quando a validação do lado do cliente do jQuery detecta o erro, ela exibe uma mensagem de erro.

Formulário da exibição de filmes com vários erros de validação do lado do cliente do jQuery

Observação

Talvez você não consiga inserir vírgulas decimais em campos decimais. 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 o comentário 4076 do GitHub para obter instruções sobre como adicionar casas decimais.

Observe como o formulário renderizou automaticamente uma mensagem de erro de validação em cada campo que contém um valor inválido. Os erros são impostos no lado do cliente, usando o JavaScript e o jQuery, e no lado do servidor, quando um usuário tem o JavaScript desabilitado.

Uma vantagem significativa é que nenhuma alteração de código foi necessária nas páginas Criar ou Editar. Após a aplicação das anotações de dados ao modelo, a interface do usuário de validação é habilitada. O Razor Pages criado neste tutorial selecionaram automaticamente as regras de validação, usando os atributos de validação nas propriedades da classe do modelo Movie. Validação do teste usando a página Editar: a mesma validação é aplicada.

Os dados de formulário não serão postados no servidor enquanto houver erros de validação do lado do cliente. Verifique se os dados de formulário não são postados por uma ou mais das seguintes abordagens:

  • Coloque um ponto de interrupção no método OnPostAsync. Envie o formulário selecionando Criar ou Salvar. O ponto de interrupção nunca é atingido.
  • Use a ferramenta Fiddler.
  • Use as ferramentas do desenvolvedor do navegador para monitorar o tráfego de rede.

Validação do servidor

Quando o JavaScript está desabilitado no navegador, o envio do formulário com erros será postado no servidor.

(Opcional) Teste a validação do servidor:

  1. Desabilite o JavaScript no navegador. O JavaScript pode ser desabilitado usando as ferramentas de desenvolvedor do navegador. Se você não conseguir desabilitar o JavaScript no navegador, tente outro navegador.

  2. Defina um ponto de interrupção no método OnPostAsync da página Criar ou Editar.

  3. Envie um formulário com dados inválidos.

  4. Verifique se o estado do modelo é inválido:

     if (!ModelState.IsValid)
     {
        return Page();
     }
    

Como alternativa, Desabilite a validação do lado do cliente no servidor.

O código a seguir mostra uma parte da página Create.cshtml gerada anteriormente com scaffold no tutorial. Ele é usado pelas páginas Criar e Editar para:

  • Exibir o formulário inicial.
  • Exibir novamente o formulário em caso de erro.
<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>

O Auxiliar de Marcação de Entrada usa os atributos de DataAnnotations e produz os atributos HTML necessários para a Validação do jQuery no lado do cliente. O Auxiliar de Marcação de Validação exibe erros de validação. Consulte Validação para obter mais informações.

As páginas Criar e Editar não têm nenhuma regra de validação. As regras de validação e as cadeias de caracteres de erro são especificadas somente na classe Movie. Essas regras de validação são aplicadas automaticamente ao Razor Pages que edita o modelo Movie.

Quando a lógica de validação precisa ser alterada, ela é feita apenas no modelo. A validação é aplicada de forma consistente em todo o aplicativo, a lógica de validação é definida em um único lugar. A validação em um único lugar ajuda a manter o código limpo e facilita sua manutenção e atualização.

Usar atributos DataType

Examine a classe Movie. O namespace System.ComponentModel.DataAnnotations fornece atributos de formatação, além do conjunto interno de atributos de validação. O atributo [DataType] é aplicado às propriedades ReleaseDate e Price.

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

Os atributos [DataType] fornecem:

  • Dicas para o mecanismo de exibição para formatar os dados.
  • Fornece atributos como <a> para URLs e <a href="mailto:EmailAddress.com"> para email.

Use o atributo [RegularExpression] para validar o formato dos dados. O atributo [DataType] é usado para especificar um tipo de dados mais específico do que o tipo intrínseco de banco de dados. Os atributos [DataType] não são atributos de validação. No aplicativo de exemplo, apenas a data é exibida, sem a hora.

A enumeração DataType fornece muitos tipos de dados, como Date, Time, PhoneNumber, Currency, EmailAddress e muito mais.

Os atributos [DataType]:

  • Pode permitir que o aplicativo forneça automaticamente recursos específicos a um tipo. Por exemplo, um link mailto: pode ser criado para DataType.EmailAddress.
  • Pode fornecer um seletor de dados DataType.Date em navegadores que dão suporte a HTML5.
  • Emite atributos HTML 5 data-, pronunciados "data dash", que são consumidos por navegadores HTML 5.
  • Não forneça nenhuma validação.

DataType.Date não especifica o formato da data exibida. Por padrão, o campo de dados é exibido de acordo com os formatos padrão com base nas CultureInfo do servidor.

A anotação de dados [Column(TypeName = "decimal(18, 2)")] é necessária para que o Entity Framework Core possa mapear corretamente o Price para a moeda no banco de dados. Para obter mais informações, veja Tipos de Dados.

O atributo [DisplayFormat] é usado para especificar explicitamente o formato de data:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

A configuração ApplyFormatInEditMode especifica que a formatação será aplicada quando o valor for exibido para edição. Talvez esse comportamento não seja desejado para alguns campos. Por exemplo, em valores monetários, o símbolo de moeda não costuma ser desejado na interface do usuário de edição.

O atributo [DisplayFormat] pode ser usado por si só, mas geralmente é uma boa ideia usar o atributo [DataType]. O atributo [DataType] transmite a semântica dos dados em vez de como renderizá-los em uma tela. O atributo [DataType] oferece os seguintes benefícios que não estão disponíveis com [DisplayFormat]:

  • O navegador pode habilitar os recursos do HTML5, por exemplo, mostrar um controle de calendário, o símbolo de moeda apropriado à localidade, links de email etc.
  • Por padrão, o navegador renderiza os dados usando o formato correto de acordo com a localidade.
  • O atributo [DataType] pode permitir que a estrutura ASP.NET Core escolha o modelo de campo correto para renderizar os dados. O DisplayFormat, se usado por si só, usa o modelo de cadeia de caracteres.

Observação: a validação do jQuery não funciona com os atributos [Range] e DateTime. Por exemplo, o seguinte código sempre exibirá um erro de validação do lado do cliente, mesmo quando a data estiver no intervalo especificado:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

É uma boa prática compilar datas rígidas nos modelos e, portanto, o uso do atributo [Range] e de DateTime não é recomendado. Use Configuração para intervalos de datas e outros valores que estão sujeitos a alterações frequentes em vez de especificá-la no código.

O seguinte código mostra como combinar atributos em uma linha:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [StringLength(60, MinimumLength = 3)]
        public string Title { get; set; } = string.Empty;

        [Display(Name = "Release Date"), DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
        public string Genre { get; set; } = string.Empty;

        [Range(1, 100), DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
        public string Rating { get; set; } = string.Empty;
    }
}

Introdução ao Razor Pages e EF Core mostra operações de EF Core avançadas com o Razor Pages.

Aplicar migrações

As DataAnnotations aplicadas à classe alteram o esquema. Por exemplo, as DataAnnotations aplicadas ao campo Title:

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; } = string.Empty;
  • Limitam os caracteres a 60.
  • Não permitem um valor null.

Atualmente a tabela Movie tem o seguinte esquema:

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (MAX)  NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (MAX)  NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

As alterações do esquema anterior não fazem com que o EF lance uma exceção. No entanto, crie uma migração de forma que o esquema seja consistente com o modelo.

No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes. No PMC, insira os seguintes comandos:

Add-Migration New_DataAnnotations
Update-Database

Update-Database executa o método Up da classe New_DataAnnotations.

Examine o método Up:

public partial class New_DataAnnotations : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "Title",
            table: "Movie",
            type: "nvarchar(60)",
            maxLength: 60,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Rating",
            table: "Movie",
            type: "nvarchar(5)",
            maxLength: 5,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Genre",
            table: "Movie",
            type: "nvarchar(30)",
            maxLength: 30,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");
    }

A tabela Movie atualizada tem o seguinte esquema:

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (60)   NOT NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (30)   NOT NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (5)    NOT NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Publicar no Azure

Para obter informações sobre como fazer uma implantação no Azure, confira Tutorial: Criar um aplicativo ASP.NET Core no Azure com o Banco de Dados SQL.

Obrigado por concluir esta introdução ao Razor Pages. A Introdução ao Razor Pages e ao EF Core é um excelente acompanhamento para este tutorial.

Recursos adicionais

Próximas etapas

Nesta seção, a lógica de validação é adicionada para o modelo Movie. As regras de validação são impostas sempre que um usuário cria ou edita um filme.

Validação

Um princípio-chave do desenvolvimento de software é chamado DRY (“Don't Repeat Yourself”). O Razor Pages incentiva o desenvolvimento em que a funcionalidade é especificada uma vez e, depois, reflete-se em todo o aplicativo. O DRY pode ajudar a:

  • Reduzir a quantidade de código em um aplicativo.
  • Fazer com que o código seja menos propenso a erros e mais fácil de ser testado e mantido.

O suporte à validação fornecido pelo Razor Pages e pelo Entity Framework é um bom exemplo do princípio DRY:

  • As regras de validação são especificadas declarativamente em um só lugar, na classe de modelo.
  • As regras são impostas em todos os lugares do aplicativo.

Adicionar regras de validação ao modelo de filme

O namespace DataAnnotations fornece:

  • Um conjunto de atributos de validação internos aplicados de forma declarativa a uma classe ou propriedade.
  • Atributos de formatação como [DataType], que ajudam com a formatação e não fornecem nenhuma validação.

Atualize a classe Movie para aproveitar os atributos de validação [Required], [StringLength], [RegularExpression] e [Range] internos.

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [StringLength(60, MinimumLength = 3)]
        [Required]
        public string Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Range(1, 100)]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
        [Required]
        [StringLength(30)]
        public string Genre { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
        [StringLength(5)]
        [Required]
        public string Rating { get; set; }
    }
}

Os atributos de validação especificam o comportamento a ser imposto nas propriedades de modelo às quais eles são aplicados:

  • Os atributos [Required] e [MinimumLength] indicam que uma propriedade deve ter um valor. Nada impede que um usuário insira espaço em branco para atender a essa validação.

  • O atributo [RegularExpression] é usado para limitar quais caracteres podem ser inseridos. No código anterior, Genre:

    • Deve usar apenas letras.
    • A primeira letra deve ser maiúscula. Espaços em branco são permitidos, enquanto números e caracteres especiais não são.
  • O RegularExpressionRating:

    • Exige que o primeiro caractere seja uma letra maiúscula.
    • Permite caracteres especiais e números nos espaços subsequentes. "PG-13" é válido para uma classificação, mas é um erro em Genre.
  • O atributo [Range] restringe um valor a um intervalo especificado.

  • O atributo [StringLength] define o tamanho máximo de uma propriedade de cadeia de caracteres e, opcionalmente, seu tamanho mínimo.

  • Os tipos de valor, como decimal, int, float, DateTime são inerentemente necessários e não precisam do atributo [Required].

As regras de validação anteriores são usadas para demonstração, elas não são ideais para um sistema de produção. Por exemplo, o anterior impede a entrada de um filme com apenas dois caracteres e não permite caracteres especiais em Genre.

Ter as regras de validação automaticamente impostas pelo ASP.NET Core ajuda a:

  • Tornar o aplicativo mais robusto.
  • Reduzir as chances de salvar dados inválidos no banco de dados.

Interface do usuário de erro de validação no Razor Pages

Execute o aplicativo e navegue para Pages/Movies.

Selecione o link Criar Novo. Preencha o formulário com alguns valores inválidos. Quando a validação do lado do cliente do jQuery detecta o erro, ela exibe uma mensagem de erro.

Formulário da exibição de filmes com vários erros de validação do lado do cliente do jQuery

Observação

Talvez você não consiga inserir vírgulas decimais em campos decimais. 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 o comentário 4076 do GitHub para obter instruções sobre como adicionar casas decimais.

Observe como o formulário renderizou automaticamente uma mensagem de erro de validação em cada campo que contém um valor inválido. Os erros são impostos no lado do cliente, usando o JavaScript e o jQuery, e no lado do servidor, quando um usuário tem o JavaScript desabilitado.

Uma vantagem significativa é que nenhuma alteração de código foi necessária nas páginas Criar ou Editar. Após a aplicação das anotações de dados ao modelo, a interface do usuário de validação é habilitada. O Razor Pages criado neste tutorial selecionaram automaticamente as regras de validação, usando os atributos de validação nas propriedades da classe do modelo Movie. Validação do teste usando a página Editar: a mesma validação é aplicada.

Os dados de formulário não serão postados no servidor enquanto houver erros de validação do lado do cliente. Verifique se os dados de formulário não são postados por uma ou mais das seguintes abordagens:

  • Coloque um ponto de interrupção no método OnPostAsync. Envie o formulário selecionando Criar ou Salvar. O ponto de interrupção nunca é atingido.
  • Use a ferramenta Fiddler.
  • Use as ferramentas do desenvolvedor do navegador para monitorar o tráfego de rede.

Validação do servidor

Quando o JavaScript está desabilitado no navegador, o envio do formulário com erros será postado no servidor.

(Opcional) Teste a validação do servidor:

  1. Desabilite o JavaScript no navegador. O JavaScript pode ser desabilitado usando as ferramentas de desenvolvedor do navegador. Se o JavaScript não puder ser desabilitado no navegador, tente outro navegador.

  2. Defina um ponto de interrupção no método OnPostAsync da página Criar ou Editar.

  3. Envie um formulário com dados inválidos.

  4. Verifique se o estado do modelo é inválido:

     if (!ModelState.IsValid)
     {
        return Page();
     }
    

Como alternativa, Desabilite a validação do lado do cliente no servidor.

O código a seguir mostra uma parte da página Create.cshtml gerada anteriormente com scaffold no tutorial. Ele é usado pelas páginas Criar e Editar para:

  • Exibir o formulário inicial.
  • Exibir novamente o formulário em caso de erro.
<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>

O Auxiliar de Marcação de Entrada usa os atributos de DataAnnotations e produz os atributos HTML necessários para a Validação do jQuery no lado do cliente. O Auxiliar de Marcação de Validação exibe erros de validação. Consulte Validação para obter mais informações.

As páginas Criar e Editar não têm nenhuma regra de validação. As regras de validação e as cadeias de caracteres de erro são especificadas somente na classe Movie. Essas regras de validação são aplicadas automaticamente ao Razor Pages que edita o modelo Movie.

Quando a lógica de validação precisa ser alterada, ela é feita apenas no modelo. A validação é aplicada de forma consistente em todo o aplicativo, a lógica de validação é definida em um único lugar. A validação em um único lugar ajuda a manter o código limpo e facilita sua manutenção e atualização.

Usar atributos DataType

Examine a classe Movie. O namespace System.ComponentModel.DataAnnotations fornece atributos de formatação, além do conjunto interno de atributos de validação. O atributo [DataType] é aplicado às propriedades ReleaseDate e Price.

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

Os atributos [DataType] fornecem:

  • Dicas para o mecanismo de exibição para formatar os dados.
  • Fornece atributos como <a> para URLs e <a href="mailto:EmailAddress.com"> para email.

Use o atributo [RegularExpression] para validar o formato dos dados. O atributo [DataType] é usado para especificar um tipo de dados mais específico do que o tipo intrínseco de banco de dados. Os atributos [DataType] não são atributos de validação. No aplicativo de exemplo, apenas a data é exibida, sem a hora.

A enumeração DataType fornece muitos tipos de dados, como Date, Time, PhoneNumber, Currency, EmailAddress e muito mais.

Os atributos [DataType]:

  • Pode permitir que o aplicativo forneça automaticamente recursos específicos a um tipo. Por exemplo, um link mailto: pode ser criado para DataType.EmailAddress.
  • Pode fornecer um seletor de dados DataType.Date em navegadores que dão suporte a HTML5.
  • Emite atributos HTML 5 data-, pronunciados "data dash", que são consumidos por navegadores HTML 5.
  • Não forneça nenhuma validação.

DataType.Date não especifica o formato da data exibida. Por padrão, o campo de dados é exibido de acordo com os formatos padrão com base nas CultureInfo do servidor.

A anotação de dados [Column(TypeName = "decimal(18, 2)")] é necessária para que o Entity Framework Core possa mapear corretamente o Price para a moeda no banco de dados. Para obter mais informações, veja Tipos de Dados.

O atributo [DisplayFormat] é usado para especificar explicitamente o formato de data:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

A configuração ApplyFormatInEditMode especifica que a formatação será aplicada quando o valor for exibido para edição. Talvez esse comportamento não seja desejado para alguns campos. Por exemplo, em valores monetários, o símbolo de moeda não costuma ser desejado na interface do usuário de edição.

O atributo [DisplayFormat] pode ser usado por si só, mas geralmente é uma boa ideia usar o atributo [DataType]. O atributo [DataType] transmite a semântica dos dados em vez de como renderizá-los em uma tela. O atributo [DataType] oferece os seguintes benefícios que não estão disponíveis com [DisplayFormat]:

  • O navegador pode habilitar os recursos do HTML5, por exemplo, mostrar um controle de calendário, o símbolo de moeda apropriado à localidade, links de email etc.
  • Por padrão, o navegador renderiza os dados usando o formato correto de acordo com a localidade.
  • O atributo [DataType] pode permitir que a estrutura ASP.NET Core escolha o modelo de campo correto para renderizar os dados. O DisplayFormat, se usado por si só, usa o modelo de cadeia de caracteres.

Observação: a validação do jQuery não funciona com os atributos [Range] e DateTime. Por exemplo, o seguinte código sempre exibirá um erro de validação do lado do cliente, mesmo quando a data estiver no intervalo especificado:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

É uma boa prática compilar datas rígidas nos modelos e, portanto, o uso do atributo [Range] e de DateTime não é recomendado. Use Configuração para intervalos de datas e outros valores que estão sujeitos a alterações frequentes em vez de especificá-la no código.

O seguinte código mostra como combinar atributos em uma linha:

public class Movie
{
    public int ID { get; set; }

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; }

    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; }
}

Introdução ao Razor Pages e EF Core mostra operações de EF Core avançadas com o Razor Pages.

Aplicar migrações

As DataAnnotations aplicadas à classe alteram o esquema. Por exemplo, as DataAnnotations aplicadas ao campo Title:

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; }
  • Limitam os caracteres a 60.
  • Não permitem um valor null.

Atualmente a tabela Movie tem o seguinte esquema:

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (MAX)  NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (MAX)  NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

As alterações do esquema anterior não fazem com que o EF lance uma exceção. No entanto, crie uma migração de forma que o esquema seja consistente com o modelo.

No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes. No PMC, insira os seguintes comandos:

Add-Migration New_DataAnnotations
Update-Database

Update-Database executa os métodos Up da classe New_DataAnnotations. Examine o método Up:

public partial class New_DataAnnotations : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "Title",
            table: "Movie",
            maxLength: 60,
            nullable: false,
            oldClrType: typeof(string),
            oldNullable: true);

        migrationBuilder.AlterColumn<string>(
            name: "Rating",
            table: "Movie",
            maxLength: 5,
            nullable: false,
            oldClrType: typeof(string),
            oldNullable: true);

        migrationBuilder.AlterColumn<string>(
            name: "Genre",
            table: "Movie",
            maxLength: 30,
            nullable: false,
            oldClrType: typeof(string),
            oldNullable: true);
    }

A tabela Movie atualizada tem o seguinte esquema:

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (60)   NOT NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (30)   NOT NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (5)    NOT NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Publicar no Azure

Para obter informações sobre como fazer uma implantação no Azure, confira Tutorial: Criar um aplicativo ASP.NET Core no Azure com o Banco de Dados SQL.

Obrigado por concluir esta introdução ao Razor Pages. A Introdução ao Razor Pages e ao EF Core é um excelente acompanhamento para este tutorial.

Padrões de aplicativo Web confiáveis

Consulte os Vídeo do YouTube e o artigoPadrão de Aplicativo Web Confiável para .NET para obter diretrizes sobre como criar um aplicativo de ASP.NET Core moderno, confiável, com desempenho, testável, econômico e escalonável, seja do zero ou refatorando um aplicativo existente.

Recursos adicionais

Próximas etapas