Partilhar via


Visão geral dos formulários do ASP.NET Core Blazor

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 artigo explica como usar formulários no Blazor.

Formulários e componentes de entrada

A estrutura Blazor dá suporte a formulários e fornece componentes de entrada internos:

Observação

Os recursos de validação do ASP.NET Core sem suporte são abordados na seção Recursos de validação sem suporte.

O namespace Microsoft.AspNetCore.Components.Forms fornece:

  • Classes para gerenciar elementos de formulário, estado e validação.
  • Acesso a componentes Input* internos.

Um projeto criado a partir do modelo de projeto do Blazor inclui o namespace no arquivo _Imports.razor do aplicativo, o que disponibiliza o namespace para os componentes Razor do aplicativo.

Formulários HTML padrão são suportados. Crie um formulário usando a marca HTML <form> normal e especifique um manipulador @onsubmit para lidar com a solicitação de formulário enviada.

StarshipPlainForm.razor:

@page "/starship-plain-form"
@inject ILogger<StarshipPlainForm> Logger

<form method="post" @onsubmit="Submit" @formname="starship-plain-form">
    <AntiforgeryToken />
    <div>
        <label>
            Identifier: 
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</form>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        public string? Id { get; set; }
    }
}
@page "/starship-plain-form"
@inject ILogger<StarshipPlainForm> Logger

<form method="post" @onsubmit="Submit" @formname="starship-plain-form">
    <AntiforgeryToken />
    <div>
        <label>
            Identifier: 
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</form>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        public string? Id { get; set; }
    }
}

No componente StarshipPlainForm anterior:

  • O formulário é renderizado no local em que o elemento <form> aparece. O formulário é nomeado com o atributo de diretiva @formname, que identifica exclusivamente o formulário para a estrutura Blazor.
  • O modelo é criado no bloco @code do componente e mantido em um propriedade privada (Model). O atributo [SupplyParameterFromForm] indica que o valor da propriedade associada deve ser fornecido com base nos dados do formulário. Os dados da solicitação que correspondem ao nome da propriedade estão associados à propriedade.
  • O componente InputText é um componente de entrada para editar valores de cadeia de caracteres. O atributo de diretiva @bind-Value associa a propriedade do modelo Model.Id à propriedade Value do InputText do componente.
  • O método Submit é registrado como um manipulador para o retorno de chamada @onsubmit. O manipulador é chamado quando o formulário é enviado pelo usuário.

Importante

Sempre use o atributo de diretiva @formname com um nome de formulário exclusivo.

Blazor aprimora a navegação da página e o tratamento de formulários interceptando a solicitação para aplicar a resposta ao DOM existente, preservando o máximo possível do formulário renderizado. O aprimoramento evita a necessidade de carregar totalmente a página e fornece uma experiência de usuário muito mais suave, semelhante a um SPA (aplicativo de página única), embora o componente seja renderizado no servidor. Para obter mais informações, confira Roteamento e navegação do Blazor no ASP.NET Core.

Há suporte para a renderização de streaming em formulários HTML sem formatação.

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

O exemplo anterior inclui suporte a antifalsificação pela inclusão de um componente AntiforgeryToken no formulário. O suporte a antifalsificação é explicado com mais detalhes na seção Suporte a antifalsificação deste artigo.

Para enviar um formulário com base em eventos DOM de outro elemento, por exemplo, oninput ou onblur, utilize JavaScript para enviar o formulário (submit (documentação do MDN)).

Em vez de usar formulários sem formatação em aplicativos Blazor, um formulário normalmente é definido com o suporte de formulário interno do Blazor por meio do componente EditForm da estrutura. O componente Razor a seguir demonstra elementos, componentes e código Razor típicos para renderizar um webform usando um componente EditForm.

Um formulário é definido usando o componente EditForm da estrutura Blazor. O componente Razor a seguir demonstra elementos, componentes e código Razor típicos para renderizar um webform usando um componente EditForm.

Starship1.razor:

@page "/starship-1"
@inject ILogger<Starship1> Logger

<EditForm Model="Model" OnSubmit="Submit" FormName="Starship1">
    <div>
        <label>
            Identifier:
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        public string? Id { get; set; }
    }
}
@page "/starship-1"
@inject ILogger<Starship1> Logger

<EditForm Model="Model" OnSubmit="Submit" FormName="Starship1">
    <div>
        <label>
            Identifier:
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        public string? Id { get; set; }
    }
}

No componente Starship1 anterior:

  • O componente EditForm é renderizado onde o elemento <EditForm> aparece. O formulário é nomeado com o atributo de diretiva @formname, que identifica exclusivamente o formulário para a estrutura Blazor.
  • O modelo é criado no bloco @code do componente e mantido em um propriedade privada (Model). A propriedade é atribuída ao parâmetro EditForm.Model. O atributo [SupplyParameterFromForm] indica que o valor da propriedade associada deve ser fornecido com base nos dados do formulário. Os dados da solicitação que correspondem ao nome da propriedade estão associados à propriedade.
  • O componente InputText é um componente de entrada para editar valores de cadeia de caracteres. O atributo de diretiva @bind-Value associa a propriedade do modelo Model.Id à propriedade Value do InputText do componente.
  • O método Submit é registrado como um manipulador para o retorno de chamada OnSubmit. O manipulador é chamado quando o formulário é enviado pelo usuário.

Importante

Sempre use o atributo de diretiva @formname com um nome de formulário exclusivo.

Blazor aprimora a navegação de página e o tratamento de formulários para componentes EditForm. Para obter mais informações, confira Roteamento e navegação do Blazor no ASP.NET Core.

Há suporte para a renderização de streaming em EditForm.

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

@page "/starship-1"
@inject ILogger<Starship1> Logger

<EditForm Model="Model" OnSubmit="Submit">
    <InputText @bind-Value="Model!.Id" />
    <button type="submit">Submit</button>
</EditForm>

@code {
    public Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit()
    {
        Logger.LogInformation("Model.Id = {Id}", Model?.Id);
    }

    public class Starship
    {
        public string? Id { get; set; }
    }
}

No componente Starship1 anterior:

  • O componente EditForm é renderizado onde o elemento <EditForm> aparece.
  • O modelo é criado no bloco de @code do componente e mantido em um campo privado (model). O campo é atribuído ao parâmetro EditForm.Model.
  • O componente InputText é um componente de entrada para editar valores de cadeia de caracteres. O atributo de diretiva @bind-Value associa a propriedade do modelo Model.Id à propriedade Value do componente InputText.
  • O método Submit é registrado como um manipulador para o retorno de chamada OnSubmit. O manipulador é chamado quando o formulário é enviado pelo usuário.

Para obter mais informações sobre a associação de propriedades, confira Associação de dados do Blazor ASP.NET Core.

No próximo exemplo, o componente anterior é modificado para criar o formulário no componente Starship2:

  • OnSubmit é substituído por OnValidSubmit, que processa o manipulador de eventos atribuído se o formulário é válido quando enviado pelo usuário.
  • Um componente ValidationSummary é adicionado para exibir mensagens de validação quando o formulário é inválido no envio do formulário.
  • O validador de anotações de dados (componente† do DataAnnotationsValidator) anexa o suporte à validação usando anotações de dados:
    • Se o campo de formulário <input> for deixado em branco quando o botão Submit for selecionado, um erro será exibido no resumo da validação (componente‡ do ValidationSummary) ("The Id field is required.") e Submit não será chamado.
    • Se o campo de formulário <input> contiver mais de dez caracteres quando o botão Submit for selecionado, um erro aparecerá no resumo de validação ("Id is too long."). Submit não é chamado.
    • Se o campo de formulário <input> contiver um valor válido quando o botão Submit for selecionado, Submit será chamado.

†O componente DataAnnotationsValidator é abordado na seção Componente Validador. ‡O componente ValidationSummary é abordado na seção Resumo de Validação e Componentes da Mensagem de Validação.

Starship2.razor:

@page "/starship-2"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship2> Logger

<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship2">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <label>
        Identifier: 
        <InputText @bind-Value="Model!.Id" />
    </label>
    <button type="submit">Submit</button>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        [Required]
        [StringLength(10, ErrorMessage = "Id is too long.")]
        public string? Id { get; set; }
    }
}
@page "/starship-2"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship2> Logger

<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship2">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <label>
        Identifier: 
        <InputText @bind-Value="Model!.Id" />
    </label>
    <button type="submit">Submit</button>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        [Required]
        [StringLength(10, ErrorMessage = "Id is too long.")]
        public string? Id { get; set; }
    }
}
@page "/starship-2"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship2> Logger

<EditForm Model="Model" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <InputText @bind-Value="Model!.Id" />
    <button type="submit">Submit</button>
</EditForm>

@code {
    public Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit()
    {
        Logger.LogInformation("Id = {Id}", Model?.Id);
    }

    public class Starship
    {
        [Required]
        [StringLength(10, ErrorMessage = "Id is too long.")]
        public string? Id { get; set; }
    }
}

Lidar com o envio de formulários

O EditForm fornece os seguintes retornos de chamada para lidar com o envio de formulário:

  • Use OnValidSubmit a fim de atribuir um manipulador de eventos para ser executado quando um formulário com campos válidos for enviado.
  • Use OnInvalidSubmit a fim de atribuir um manipulador de eventos para ser executado quando um formulário com campos inválidos for enviado.
  • Use OnSubmit a fim de atribuir um manipulador de eventos para ser executado independentemente do status de validação dos campos de formulário. O formulário é validado chamando EditContext.Validate no método do manipulador de eventos. Se Validate retornar true, o formulário será válido.

Limpar um formulário ou campo

Redefine um formulário limpando seu modelo de volta ao estado padrão, o que pode ser feito dentro ou fora da marcação de um EditForm:

<button @onclick="ClearForm">Clear form</button>

...

private void ClearForm() => Model = new();

Como alternativa, use uma expressão Razor explícita:

<button @onclick="@(() => Model = new())">Clear form</button>

Redefine um campo limpando o valor do modelo de volta ao seu estado padrão:

<button @onclick="ResetId">Reset Identifier</button>

...

private void ResetId() => Model!.Id = string.Empty;

Como alternativa, use uma expressão Razor explícita:

<button @onclick="@(() => Model!.Id = string.Empty)">Reset Identifier</button>

Não há necessidade de chamar StateHasChanged nos exemplos anteriores porque StateHasChanged é chamado automaticamente pela estrutura Blazor para renderizar novamente o componente depois que um manipulador de eventos for invocado. Se um manipulador de eventos não for utilizado para invocar os métodos que limpam um formulário ou campo, o código do desenvolvedor deverá chamar StateHasChanged para renderizar novamente o componente.

Suporte à anti-falsificação

Os serviços antifalsificação são adicionados automaticamente aos aplicativos Blazor quando AddRazorComponents é chamado no arquivo Program.

O aplicativo usa o Middleware Antiforgery chamando UseAntiforgery em seu pipeline de processamento de solicitação no arquivo Program. UseAntiforgery é chamado após a chamada para UseRouting. Se houver chamadas para UseRouting e UseEndpoints, a chamada para UseAntiforgery deve ser feita entre elas. Uma chamada para UseAntiforgery deve ser feita após chamadas para UseAuthenticatione UseAuthorization.

O componente AntiforgeryToken renderiza um token anti-falsificação como um campo oculto e o atributo [RequireAntiforgeryToken] permite a proteção anti-falsificação. Se uma verificação anti-falsificação falhar, uma resposta 400 - Bad Request será gerada e o formulário não será processado.

Para formulários baseados em EditForm, o componente AntiforgeryToken e o atributo [RequireAntiforgeryToken] são adicionados automaticamente para fornecer proteção antifalsificação.

No caso de formulários baseados no elemento HTML <form>, adicione manualmente o componente AntiforgeryToken ao formulário:

<form method="post" @onsubmit="Submit" @formname="starshipForm">
    <AntiforgeryToken />
    <input id="send" type="submit" value="Send" />
</form>

@if (submitted)
{
    <p>Form submitted!</p>
}

@code{
    private bool submitted = false;

    private void Submit() => submitted = true;
}

Aviso

Para formulários com base em EditFormou no elemento HTML <form>, a proteção anti-falsificação pode ser desabilitada passando required: false para o atributo [RequireAntiforgeryToken]. O exemplo a seguir desabilita a anti-falsificação, o que não é recomendado para aplicativos públicos:

@using Microsoft.AspNetCore.Antiforgery
@attribute [RequireAntiforgeryToken(required: false)]

Para obter mais informações, confira Autenticação e autorização no Blazor ASP.NET Core.

Atenuar ataques de excesso de postagem

Os formulários do lado do servidor renderizados estaticamente, como aqueles normalmente usados em componentes que criam e editam registros em um banco de dados com um modelo de formulário, podem estar vulneráveis a um ataque de excesso de postagem, também conhecido como um ataque de atribuição em massa. Um ataque de excesso de postagem ocorre quando um usuário mal-intencionado emite um POST de formulário HTML para o servidor que processa dados para propriedades que não fazem parte do formulário renderizado e que o desenvolvedor não deseja permitir que os usuários modifiquem. O termo “excesso de postagem” literalmente significa que o usuário mal-intencionado ultrapassou o limite de POSTs com o formulário.

O excesso de postagem não é uma preocupação quando o modelo não inclui propriedades restritas para operações de criação e atualização. No entanto, é importante ter em mente o excesso de postagem ao trabalhar com formulários estáticos do Blazor baseados em SSR que você mantém.

Para atenuar o excesso de postagem, recomendamos usar um modelo de exibição separado/DTO (objeto de transferência de dados) para o formulário e o banco de dados com operações de criação (inserção) e atualização. Quando o formulário é enviado, somente as propriedades do modelo de exibição/DTO são usadas pelo componente e pelo código C# para modificar o banco de dados. Todos os dados extras incluídos por um usuário mal-intencionado são descartados e, portanto, o usuário mal-intencionado é impedido de realizar um ataque de excesso de postagem.

Tratamento aprimorado de formulários

Aprimore a navegação para solicitações POST de formulário com o parâmetro Enhance para formulários EditForm ou o atributo data-enhance para formulários HTML (<form>):

<EditForm ... Enhance ...>
    ...
</EditForm>
<form ... data-enhance ...>
    ...
</form>

Não suportado: não é possível definir a navegação aprimorada em um elemento ancestral do formulário para habilitar o tratamento aprimorado do formulário.

<div ... data-enhance ...>
    <form ...>
        <!-- NOT enhanced -->
    </form>
</div>

As postagens do formulário aprimorado só funcionam com pontos de extremidade Blazor. A postagem de um formulário aprimorado em um ponto de extremidade diferente de Blazor resulta em um erro.

Para desabilitar o tratamento aprimorado de formulários:

  • Para um EditForm, remova o parâmetro Enhance do elemento do formulário (ou defina-o como false: Enhance="false").
  • Para um HTML <form>, remova o atributo data-enhance do elemento do formulário (ou defina-o como false: data-enhance="false").

A navegação aprimorada e o manuseio de formulários da Blazor podem desfazer alterações dinâmicas no DOM se o conteúdo atualizado não fizer parte da renderização do servidor. Para preservar o conteúdo de um elemento, utilize o atributo data-permanent.

No exemplo a seguir, o conteúdo do elemento <div> é atualizado dinamicamente por um script quando a página é carregada:

<div data-permanent>
    ...
</div>

Para desabilitar a navegação aprimorada e o tratamento de formulários globalmente, consulte ASP.NET Core Blazor inicialização.

Para obter diretrizes sobre o uso do evento enhancedload para escutar atualizações aprimoradas de página, consulte ASP.NET Core Blazor roteamento e navegação.

Exemplos

Os exemplos não adotam o tratamento avançado de formulários para solicitações POST de formulários, mas todos os exemplos podem ser atualizados para adotar os recursos avançados seguindo as diretrizes da seção Tratamento avançado de formulários.

Os exemplos usam o operador new target-typed, que foi introduzido com C# 9.0 e .NET 5. No exemplo a seguir, o tipo não é explicitamente declarado para o operador new:

public ShipDescription ShipDescription { get; set; } = new();

Se estiver usando o C# 8.0 ou anterior (ASP.NET Core 3.1), modifique o código de exemplo para declarar o tipo para o operador new:

public ShipDescription ShipDescription { get; set; } = new ShipDescription();

Os componentes usam NRTs (tipos de referência anuláveis) e o compilador .NET executa uma análise estática de estado nulo, ambas com suporte no .NET 6 ou posterior. Para obter mais informações, consulte Migrar do ASP.NET Core 5.0 para o 6.0.

Se estiver usando o C# 9.0 ou anterior (.NET 5 ou anterior), remova os NRTs dos exemplos. Normalmente, isso envolve apenas a remoção dos pontos de interrogação (?) e pontos de exclamação (!) dos tipos no código de exemplo.

O SDK do .NET aplica diretivas globais using implícitas a projetos ao direcionar o .NET 6 ou posterior. Os exemplos usam um agente para registrar informações sobre o processamento de formulários, mas não é necessário especificar uma diretiva @using para o namespace Microsoft.Extensions.Logging nos exemplos de componente. Para obter mais informações, consulte SDKs de projeto do .NET: diretivas de uso implícito.

Se estiver usando o C# 9.0 ou anterior (.NET 5 ou anterior), adicione diretivas @using à parte superior do componente após a diretiva @page para qualquer API exigida pelo exemplo. Localize namespaces de API por meio do Visual Studio (clique com o botão direito do mouse no objeto e selecione Inspecionar Definição) ou o navegador da API do .NET.

Para demonstrar como os formulários funcionam com a validação das anotações de dados, os componentes de exemplo dependem da API System.ComponentModel.DataAnnotations. Se quiser evitar uma linha extra de código em componentes que usam anotações de dados, torne o namespace disponível em todos os componentes do aplicativo com o arquivo de importações (_Imports.razor):

@using System.ComponentModel.DataAnnotations

Exemplos de formulário fazem referência a aspectos do universo Star Trek. Star Trek é um copyright ©1966-2023 da CBS Studios e Paramount.

A validação do lado do cliente requer um circuito

Em Blazor Web Apps, a validação do lado do cliente requer um circuito BlazorSignalR ativo. A validação do lado do cliente não está disponível para formulários em componentes que adotaram a renderização estática do lado do servidor (SSR estática). Os formulários que adotam SSR estático são validados no servidor depois que o formulário é enviado.

Recursos de validação sem suporte

Todos os validadores internos de anotação de dados são suportados no Blazor, exceto o [Remote] atributo de validação.

A validação do jQuery não é suportada nos Razor componentes. Recomendamos qualquer uma das seguintes abordagens:

  • Siga as diretrizes em ASP.NET validação de formulários principais Blazor para:
    • Validação do lado do servidor em um Blazor Web App que adota um modo de renderização interativo.
    • Validação do lado do cliente em um aplicativo Web Assembly autônomo Blazor .
  • Use atributos de validação HTML nativos (consulte Validação de formulário do lado do cliente (documentação do MDN)).
  • Adote uma biblioteca JavaScript de validação de terceiros.

Para formulários renderizados estaticamente no servidor, um novo mecanismo de validação do lado do cliente está sendo considerado para o .NET 10 no final de 2025. Para obter mais informações, consulte Criar formulários renderizados do servidor com validação de cliente usando Blazor sem um circuito (dotnet/aspnetcore #51040).

Recursos adicionais