Condividi tramite


Panoramica dei moduli di Blazor base di ASP.NET

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Avviso

Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Questo articolo illustra come usare i moduli in Blazor.

Componenti e moduli di input

Il Blazor framework supporta i moduli e fornisce componenti di input predefiniti:

Nota

Le funzionalità di convalida di base non supportate ASP.NET sono descritte nella sezione Funzionalità di convalida non supportate.

Lo Microsoft.AspNetCore.Components.Forms spazio dei nomi fornisce:

  • Classi per la gestione di elementi del modulo, stato e convalida.
  • Accesso ai componenti predefiniti Input* .

Un progetto creato dal Blazor modello di progetto include lo spazio dei nomi nel file dell'app _Imports.razor , che rende lo spazio dei nomi disponibile per i componenti dell'app Razor .

I moduli HTML standard sono supportati. Creare un modulo usando il normale tag HTML <form> e specificare un @onsubmit gestore per la gestione della richiesta di modulo inviata.

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; }
    }
}

Nel componente precedente StarshipPlainForm :

  • Viene eseguito il rendering del modulo in cui viene visualizzato l'elemento <form> . Il form viene denominato con l'attributo @formname di direttiva , che identifica in modo univoco il modulo nel Blazor framework.
  • Il modello viene creato nel blocco del @code componente e mantenuto in una proprietà pubblica (Model). L'attributo [SupplyParameterFromForm] indica che il valore della proprietà associata deve essere fornito dai dati del modulo. I dati nella richiesta che corrispondono al nome della proprietà vengono associati alla proprietà .
  • Il InputText componente è un componente di input per la modifica dei valori stringa. L'attributo @bind-Value della direttiva associa la Model.Id proprietà del modello alla InputText proprietà del Value componente.
  • Il Submit metodo viene registrato come gestore per il @onsubmit callback. Il gestore viene chiamato quando il modulo viene inviato dall'utente.

Importante

Usare sempre l'attributo @formname di direttiva con un nome di modulo univoco.

Blazor migliora lo spostamento delle pagine e la gestione dei moduli intercettando la richiesta per applicare la risposta al DOM esistente, mantenendo la maggior parte possibile del modulo sottoposto a rendering. Il miglioramento evita la necessità di caricare completamente la pagina e offre un'esperienza utente molto più fluida, simile a un'app a pagina singola (SPA), anche se il rendering del componente viene eseguito nel server. Per altre informazioni, vedere ASP.NET routing e navigazione coreBlazor.

Il rendering in streaming è supportato per i moduli HTML semplici.

Nota

I collegamenti della documentazione all'origine del riferimento .NET in genere caricano il ramo predefinito del repository, che rappresenta lo sviluppo corrente per la versione successiva di .NET. Per selezionare un tag per una versione specifica, usare l'elenco a discesa Switch branches or tags. Per altre informazioni, vedere How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Come selezionare un tag di versione del codice sorgente di ASP.NET - dotnet/AspNetCore.Docs #26205).

L'esempio precedente include il supporto antiforgery includendo un AntiforgeryToken componente nel modulo. Il supporto antiforgery è illustrato più avanti nella sezione supporto antiforgery di questo articolo.

Per inviare un modulo in base agli eventi DOM di un altro elemento, ad esempio oninput o , usare JavaScript per inviare il modulo (submit (documentazione MDN)onblur).

Invece di usare moduli normali nelle Blazor app, un modulo viene in genere definito con Blazoril supporto predefinito del modulo usando il componente del EditForm framework. Il componente seguente Razor illustra elementi, componenti e Razor codice tipici per eseguire il rendering di una webform usando un EditForm componente.

Un modulo viene definito usando il Blazor componente del EditForm framework. Il componente seguente Razor illustra elementi, componenti e Razor codice tipici per eseguire il rendering di una webform usando un EditForm componente.

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; }
    }
}

Nel componente precedente Starship1 :

  • Viene eseguito il rendering del EditForm componente in cui viene visualizzato l'elemento <EditForm> . Il form viene denominato con l'attributo @formname di direttiva , che identifica in modo univoco il modulo nel Blazor framework.
  • Il modello viene creato nel blocco del @code componente e mantenuto in una proprietà pubblica (Model). La proprietà viene assegnata al EditForm.Model parametro . L'attributo [SupplyParameterFromForm] indica che il valore della proprietà associata deve essere fornito dai dati del modulo. I dati nella richiesta che corrispondono al nome della proprietà vengono associati alla proprietà .
  • Il InputText componente è un componente di input per la modifica dei valori stringa. L'attributo @bind-Value della direttiva associa la Model.Id proprietà del modello alla InputText proprietà del Value componente.
  • Il Submit metodo viene registrato come gestore per il OnSubmit callback. Il gestore viene chiamato quando il modulo viene inviato dall'utente.

Importante

Usare sempre l'attributo @formname di direttiva con un nome di modulo univoco.

Blazor migliora lo spostamento delle pagine e la gestione dei moduli per EditForm i componenti. Per altre informazioni, vedere ASP.NET routing e navigazione coreBlazor.

Il rendering di streaming è supportato per EditForm.

Nota

I collegamenti della documentazione all'origine del riferimento .NET in genere caricano il ramo predefinito del repository, che rappresenta lo sviluppo corrente per la versione successiva di .NET. Per selezionare un tag per una versione specifica, usare l'elenco a discesa Switch branches or tags. Per altre informazioni, vedere How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Come selezionare un tag di versione del codice sorgente di ASP.NET - 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; }
    }
}

Nel componente precedente Starship1 :

  • Viene eseguito il rendering del EditForm componente in cui viene visualizzato l'elemento <EditForm> .
  • Il modello viene creato nel blocco del @code componente e mantenuto in un campo privato (model). Il campo viene assegnato al EditForm.Model parametro .
  • Il InputText componente è un componente di input per la modifica dei valori stringa. L'attributo @bind-Value di direttiva associa la Model.Id proprietà del modello alla InputText proprietà del Value componente†.
  • Il Submit metodo viene registrato come gestore per il OnSubmit callback. Il gestore viene chiamato quando il modulo viene inviato dall'utente.

†Per altre informazioni sull'associazione di proprietà, vedere ASP.NET Data Binding coreBlazor.

Nell'esempio successivo, il componente precedente viene modificato per creare il modulo nel Starship2 componente:

  • OnSubmit viene sostituito con OnValidSubmit, che elabora il gestore eventi assegnato se il modulo è valido quando inviato dall'utente.
  • Viene aggiunto un ValidationSummary componente per visualizzare i messaggi di convalida quando il modulo non è valido per l'invio del modulo.
  • Il validator delle annotazioni dati (DataAnnotationsValidator component†) associa il supporto per la convalida usando le annotazioni dei dati:
    • Se il <input> campo modulo viene lasciato vuoto quando si seleziona il Submit pulsante, viene visualizzato un errore nel riepilogo di convalida (ValidationSummary component**) ("The Id field is required.") e Submit non viene chiamato.
    • Se il <input> campo modulo contiene più di dieci caratteri quando si seleziona il Submit pulsante, viene visualizzato un errore nel riepilogo della convalida ("Id is too long."). Submitnon viene chiamato.
    • Se il <input> campo modulo contiene un valore valido quando si seleziona il Submit pulsante, Submit viene chiamato .

†Il DataAnnotationsValidator componente è trattato nella sezione Componente validator. *Il ValidationSummary componente è trattato nella sezione Riepilogo convalida e componenti del messaggio di convalida.

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; }
    }
}

Gestire gli invii del modulo

Fornisce EditForm i callback seguenti per la gestione dell'invio di moduli:

  • Utilizzare OnValidSubmit per assegnare un gestore eventi da eseguire quando viene inviato un modulo con campi validi.
  • Utilizzare OnInvalidSubmit per assegnare un gestore eventi da eseguire quando viene inviato un modulo con campi non validi.
  • Usare OnSubmit per assegnare un gestore eventi da eseguire indipendentemente dallo stato di convalida dei campi modulo. Il modulo viene convalidato chiamando EditContext.Validate nel metodo del gestore eventi. Se Validate restituisce true, il modulo è valido.

Cancellare un modulo o un campo

Reimpostare un modulo cancellando lo stato predefinito del modello, che può essere eseguito all'interno o all'esterno del markup di un EditFormoggetto :

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

...

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

In alternativa, usare un'espressione esplicita Razor :

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

Reimpostare un campo cancellando il valore del modello sullo stato predefinito:

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

...

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

In alternativa, usare un'espressione esplicita Razor :

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

Non è necessario chiamare StateHasChanged negli esempi precedenti perché StateHasChanged viene chiamato automaticamente dal framework per eseguire il Blazor rerendere il componente dopo che viene richiamato un gestore eventi. Se un gestore eventi non viene usato per richiamare i metodi che cancellano una maschera o un campo, il codice dello sviluppatore deve chiamare StateHasChanged per risolvere il problema.

Supporto antiforgerato

I servizi antiforgery vengono aggiunti automaticamente alle Blazor app quando AddRazorComponents viene chiamato nel Program file.

L'app usa il middleware antiforgery chiamando UseAntiforgery nella pipeline di elaborazione delle richieste nel Program file. UseAntiforgery viene chiamato dopo la chiamata a UseRouting. Se sono presenti chiamate a UseRouting e UseEndpoints, la chiamata a UseAntiforgery deve passare tra di esse. Una chiamata a UseAntiforgery deve essere effettuata dopo le chiamate a UseAuthentication e UseAuthorization.

Il componente esegue il AntiforgeryToken rendering di un token antiforgery come campo nascosto e l'attributo [RequireAntiforgeryToken] abilita la protezione antiforgeria. Se un controllo antiforgery ha esito negativo, viene generata una 400 - Bad Request risposta e il modulo non viene elaborato.

Per i moduli basati su EditForm, il componente e [RequireAntiforgeryToken] l'attributo AntiforgeryToken vengono aggiunti automaticamente per fornire protezione antiforgeria.

Per i moduli basati sull'elemento HTML <form> , aggiungere manualmente il AntiforgeryToken componente al modulo:

<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;
}

Avviso

Per i moduli basati su uno EditForm o sull'elemento HTML <form> , la protezione antiforgery può essere disabilitata passando required: false all'attributo [RequireAntiforgeryToken] . L'esempio seguente disabilita l'antiforgeria e non è consigliato per le app pubbliche:

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

Per altre informazioni, vedere autenticazione e autorizzazione di base ASP.NETBlazor.

Attenuare gli attacchi di overposting

I moduli lato server sottoposti a rendering statico, ad esempio quelli usati in genere nei componenti che creano e modificano record in un database con un modello di modulo, possono essere vulnerabili a un attacco di overposting , noto anche come attacco di assegnazione di massa. Un attacco di overposting si verifica quando un utente malintenzionato rilascia un POST in formato HTML al server che elabora i dati per le proprietà che non fanno parte del modulo sottoposto a rendering e che lo sviluppatore non vuole consentire agli utenti di modificare. Il termine "overposting" significa letteralmente che l'utente malintenzionato ha over-POSTed con il modulo.

L'overposting non è un problema quando il modello non include proprietà limitate per le operazioni di creazione e aggiornamento. Tuttavia, è importante tenere presente l'overposting quando si lavora con moduli statici basati su Blazor SSR gestiti.

Per ridurre l'overposting, è consigliabile usare un oggetto DTO (View Model/Data Transfer Object) separato per il modulo e il database con operazioni di creazione (inserimento) e aggiornamento. Quando il modulo viene inviato, solo le proprietà del modello di visualizzazione/DTO vengono usate dal componente e dal codice C# per modificare il database. Tutti i dati aggiuntivi inclusi da un utente malintenzionato vengono eliminati, quindi l'utente malintenzionato non può condurre un attacco di sovrasposto.

Gestione avanzata dei moduli

Migliorare la navigazione per le richieste POST del modulo con il Enhance parametro per EditForm i moduli o l'attributo data-enhance per i moduli HTML (<form>):

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

Non supportato: non è possibile impostare lo spostamento avanzato sull'elemento predecessore di un modulo per abilitare la gestione avanzata dei moduli.

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

I post di modulo avanzati funzionano solo con Blazor gli endpoint. La pubblicazione di un modulo avanzato in un endpoint diversoBlazor da un endpoint genera un errore.

Per disabilitare la gestione avanzata dei moduli:

  • Per un EditFormoggetto , rimuovere il Enhance parametro dall'elemento del modulo (o impostarlo su false: Enhance="false").
  • Per un codice HTML <form>, rimuovere l'attributo dall'elemento data-enhance form (o impostarlo su false: data-enhance="false").

BlazorSe il contenuto aggiornato non fa parte del rendering del server, la navigazione avanzata e la mano del modulo possono annullare modifiche dinamiche al DOM. Per mantenere il contenuto di un elemento, usare l'attributo data-permanent .

Nell'esempio seguente il contenuto dell'elemento <div> viene aggiornato dinamicamente da uno script quando la pagina viene caricata:

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

Per disabilitare l'esplorazione avanzata e la gestione dei moduli a livello globale, vedere ASP.NET avvio di CoreBlazor.

Per indicazioni sull'uso dell'evento per l'ascolto enhancedload degli aggiornamenti di pagina avanzati, vedere ASP.NET routing e navigazione coreBlazor.

Esempi

Gli esempi non adottano una gestione avanzata dei moduli per le richieste POST, ma tutti gli esempi possono essere aggiornati per adottare le funzionalità avanzate seguendo le indicazioni nella sezione Gestione avanzata dei moduli.

Gli esempi usano l'operatore tipizzato new di destinazione, introdotto con C# 9.0 e .NET 5. Nell'esempio seguente il tipo non viene dichiarato in modo esplicito per l'operatore new :

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

Se si usa C# 8.0 o versioni precedenti (ASP.NET Core 3.1), modificare il codice di esempio per indicare il tipo all'operatore new :

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

I componenti usano tipi di riferimento nullable (NRT) e il compilatore .NET esegue analisi statiche con stato Null, entrambe supportate in .NET 6 o versioni successive. Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 5.0 a 6.0.

Se si usa C# 9.0 o versioni precedenti (.NET 5 o versioni precedenti), rimuovere i valori NRT dagli esempi. In genere, questo comporta semplicemente la rimozione dei punti interrogativi (?) e dei punti esclamativi (!) dai tipi nel codice di esempio.

.NET SDK applica direttive globali using implicite ai progetti quando la destinazione è .NET 6 o versione successiva. Negli esempi viene usato un logger per registrare informazioni sull'elaborazione dei moduli, ma non è necessario specificare una @using direttiva per lo Microsoft.Extensions.Logging spazio dei nomi negli esempi di componenti. Per altre informazioni, vedere SDK di progetto .NET: Direttive using implicite.

Se si usa C# 9.0 o versioni precedenti (.NET 5 o versioni precedenti), aggiungere @using direttive all'inizio del componente dopo la @page direttiva per qualsiasi API richiesta dall'esempio. Trovare spazi dei nomi API tramite Visual Studio (fare clic con il pulsante destro del mouse sull'oggetto e scegliere Visualizza definizione) o il browser api .NET.

Per illustrare il funzionamento dei moduli con la convalida delle annotazioni dei dati, i componenti di esempio si basano sull'API System.ComponentModel.DataAnnotations . Se vuoi evitare una riga di codice aggiuntiva nei componenti che usano annotazioni di dati, rendi disponibile lo spazio dei nomi nei componenti dell'app con il file imports (_Imports.razor):

@using System.ComponentModel.DataAnnotations

Esempi di moduli fanno riferimento ad aspetti dell'universo di Star Trek . Star Trek è un copyright ©del 1966-2023 di CBS Studios e Paramount.

La convalida lato client richiede un circuito

In Blazor Web Apps la convalida lato client richiede un circuito attivo BlazorSignalR . La convalida lato client non è disponibile per i moduli nei componenti che hanno adottato il rendering statico lato server (SSR statico). I moduli che adottano ssr statici vengono convalidati nel server dopo l'invio del modulo.

Funzionalità di convalida non supportate

Tutti i validator predefiniti per l'annotazione dei dati sono supportati, Blazor ad eccezione dell'attributo di [Remote] convalida.

La convalida di jQuery non è supportata nei Razor componenti. È consigliabile adottare uno degli approcci seguenti:

  • Seguire le indicazioni riportate in ASP.NET Convalida dei moduli di base Blazor per:
    • Convalida lato server in un oggetto Blazor Web App che adotta una modalità di rendering interattiva.
    • Convalida lato client in un'app assembly Web autonoma Blazor .
  • Usare gli attributi di convalida HTML nativi (vedere la documentazione relativa alla convalida dei moduli sul lato client).
  • Adottare una libreria JavaScript di convalida di terze parti.

Per i moduli sottoposti a rendering statico nel server, un nuovo meccanismo per la convalida lato client è in considerazione per .NET 10 alla fine del 2025. Per altre informazioni, vedere Creare moduli sottoposti a rendering del server con convalida client usando Blazor senza un circuito (dotnet/aspnetcore #51040).

Risorse aggiuntive