Condividi tramite


Panoramica dei moduli di ASP.NET Core Blazor

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 ASP.NET non supportate 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 modello di progetto Blazor include lo spazio dei nomi nel file _Imports.razor dell'app, il che rende lo spazio dei nomi disponibile per i componenti Razor dell'app.

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 modulo viene denominato con l'attributo direttiva @formname, che lo identifica in modo univoco nel framework Blazor.
  • 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 la navigazione delle pagine e la gestione dei moduli intercettando la richiesta per applicare la risposta al DOM esistente, preservando il più possibile il modulo già reso. 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 ulteriori informazioni, vedere ASP.NET Core routing e navigazioneBlazor.

Il rendering in streaming è supportato per i moduli HTML semplici. Si noti che quando POSTsi crea un modulo, vengono trasmessi solo gli aggiornamenti DOM all'interno dei gestori del modulo, ad esempio @onsubmit. Gli aggiornamenti all'interno di OnInitializedAsync vengono trasmessi solo per le richieste GET. Per altre informazioni, vedere Consentire lo streaming della fase di caricamento delle risposte POST (dotnet/aspnetcore #50994).

Nota

I collegamenti della documentazione al codice sorgente di riferimento .NET in genere caricano il branch predefinito del repository, che rappresenta lo sviluppo attuale per la prossima versione di .NET. Per selezionare un tag per una versione specifica, utilizzare il menu a tendina Seleziona rami o tag. Per ulteriori informazioni, vedere Come selezionare un tag di versione del codice sorgente di ASP.NET Core (dotnet/AspNetCore.Docs #26205).

L'esempio precedente include il supporto antifalsificazione aggiungendo un componente AntiforgeryToken nella forma. 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 onblur, usare JavaScript per inviare il modulo (submit).

Invece di usare moduli normali nelle Blazor app, un modulo viene in genere definito con il supporto modulo integrato di Blazor usando il componente EditForm del 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 :

  • Il componente EditForm viene reso dove appare l'elemento <EditForm>. Il form viene denominato con la proprietà FormName, che identifica in modo univoco il form nel framework Blazor.
  • 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

Utilizzare sempre la proprietà FormName con un nome di modulo univoco.

Blazor migliora la navigazione delle pagine e la gestione dei moduli per i componenti EditForm. Per ulteriori informazioni, vedere ASP.NET Core routing e navigazioneBlazor.

Il rendering di streaming è supportato per EditForm. Si noti che quando POSTsi crea un modulo, vengono trasmessi solo gli aggiornamenti DOM all'interno dei gestori del modulo, ad esempio OnValidSubmit. Gli aggiornamenti all'interno di OnInitializedAsync vengono trasmessi solo per le richieste GET. Per altre informazioni, vedere Consentire lo streaming della fase di caricamento delle risposte POST (dotnet/aspnetcore #50994).

Nota

I collegamenti della documentazione al codice sorgente di riferimento .NET in genere caricano il branch predefinito del repository, che rappresenta lo sviluppo attuale per la prossima versione di .NET. Per selezionare un tag per una versione specifica, utilizzare il menu a tendina Seleziona rami o tag. Per ulteriori informazioni, vedere Come selezionare un tag di versione del codice sorgente di 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; }
    }
}

Nel componente precedente Starship1 :

  • Il componente EditForm viene reso dove appare 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 Blazor core.

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 componente ValidationSummary per visualizzare i messaggi di convalida quando il modulo non è valido al momento della sua invio.
  • Il convalidatore delle annotazioni sui dati (componente DataAnnotationsValidator) fornisce supporto per la convalida usando le annotazioni dei dati:
    • Se il campo del modulo <input> viene lasciato vuoto quando si seleziona il pulsante Submit, un errore appare nel riepilogo di convalida (componente ValidationSummary) ("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."). Submit non è chiamato.
    • Se il <input> campo modulo contiene un valore valido quando si seleziona il Submit pulsante, Submit viene chiamato .

†Il componente DataAnnotationsValidator è trattato nella sezione Validatore. Il componente ValidationSummary è trattato nella sezione Riepilogo e messaggio di convalida dei componenti.

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

EditForm fornisce i seguenti callback per la gestione dell'invio dei 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 azzerando il suo modello allo stato predefinito, operazione che può essere eseguita all'interno o all'esterno del markup di un EditForm oggetto:

<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 permettere il ricaricamento del 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 anti-contraffazione 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 AntiforgeryToken rende un token antiforgery come un campo nascosto e l'attributo [RequireAntiforgeryToken] abilita la protezione anticontraffazione. 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 AntiforgeryToken e l'attributo [RequireAntiforgeryToken] vengono aggiunti automaticamente per fornire protezione antifalsificazione.

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 Blazor di base ASP.NET.

Attenuare gli attacchi dovuti al sovraccarico di dati

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 eseguito un "over-POSTing" usando il modulo.

L'overposting non è un problema quando il modello non include attributi limitati per le operazioni di creazione e aggiornamento. È tuttavia importante considerare il rischio di "overposting" quando si lavora con moduli statici basati su SSR che gestisci.

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 overposting.

Gestione avanzata dei moduli

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

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

Non confermato: 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 gli endpoint Blazor. La pubblicazione di un modulo avanzato su un endpoint non-Blazor genera un errore.

Per disabilitare la gestione avanzata dei moduli:

  • Per un EditForm rimuovere il parametro Enhance 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").

BlazorLa navigazione avanzata e la gestione dei moduli possono annullare le modifiche dinamiche al DOM se il contenuto aggiornato non è parte del rendering del server. 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 Blazor di Core.

Per indicazioni sull'uso dell'evento per l'ascolto enhancedload degli aggiornamenti di pagina avanzati, vedere Blazor core.

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 per il tipo di destinazione new, introdotto con C# 9 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 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 in .NET 5 a .NET 6.

Se si usa C# 9 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 ulteriori informazioni, vedere SDK di progetto .NET: Direttive using implicite.

Se si usa C# 9 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 BlazorSignalR attivo. 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 validatori integrati per l'annotazione dei dati sono supportati, ad eccezione dell'attributo di convalida.

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

  • Seguire le indicazioni riportate in convalida dei moduli in ASP.NET Core Blazor per:
    • Convalida lato server in un oggetto Blazor Web App che adotta una modalità di rendering interattiva.
    • Convalida lato client in un'app Web Assembly indipendente Blazor.
  • Usare gli attributi di convalida HTML nativi (vedere Convalida dei moduli 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 ulteriori informazioni, vedere Creare moduli renderizzati dal server con convalida lato client usando Blazor senza un circuito (dotnet/aspnetcore #51040).

Risorse aggiuntive