walidacja formularzy ASP.NET Core Blazor

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby uzyskać bieżącą wersję, zobacz wersję .NET 10 tego artykułu.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz .NET i .NET Core Support Policy. Aby uzyskać bieżącą wersję, zobacz wersję .NET 10 tego artykułu.

W tym artykule wyjaśniono, jak weryfikować dane wejściowe użytkownika w Blazor formularzach.

W przypadku większości formularzy najprostszym i zalecanym podejściem jest dodanie atrybutów weryfikacji adnotacji danych do modelu i umieszczenie DataAnnotationsValidator składnika w elemencie EditForm. Blazor obsługuje również niestandardową walidację za pomocą elementu EditContext formularza, zarówno bezpośrednio w komponencie formularza, jak i w komponencie wielokrotnego użytku służącym do walidacji.

Powiązane artykuły zawierają więcej szczegółów:

Weryfikowanie przy użyciu adnotacji danych

Poniższy model używa elementów RequiredAttribute i RangeAttribute:

Starship.cs:

using System.ComponentModel.DataAnnotations;

public class Starship
{
    [Required]
    public string? Identifier { get; set; }

    [Range(1, 10, ErrorMessage = "Accommodation must be between 1 and 10.")]
    public int MaximumAccommodation { get; set; }
}

Dodaj model do EditForm, uwzględnij DataAnnotationsValidator i wyświetlaj błędy za pomocą ValidationMessage<TValue> lub ValidationSummary. Funkcja zwrotna OnValidSubmit jest wywoływana tylko wtedy, gdy walidacja zakończy się powodzeniem:

<EditForm Model="Model" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <p>
        <label>
            Identifier:
            <InputText @bind-Value="Model.Identifier" />
        </label>
        <ValidationMessage For="() => Model.Identifier" />
    </p>

    <p>
        <label>
            Maximum accommodation:
            <InputNumber @bind-Value="Model.MaximumAccommodation" />
        </label>
        <ValidationMessage For="() => Model.MaximumAccommodation" />
    </p>

    <button type="submit">Submit</button>
</EditForm>

@code {
    private Starship Model { get; } = new Starship();

    private void Submit()
    {
        // Process the valid form.
    }
}

W przypadku statycznego przesłania formularza SSR przypisz unikatowy FormName i odbierz przesłany model za pomocą [SupplyParameterFromForm]:

<EditForm Model="Model" FormName="starship" OnValidSubmit="Submit">
    ...
</EditForm>

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

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

Aby uzyskać więcej informacji na temat przesyłania formularzy i powiązania modelu w trybach renderowania, zobacz omówienie formularzy ASP.NET Core Blazor i powiązanie formularzy Blazor ASP.NET Core.

DataAnnotationsValidator Bez składnika atrybuty weryfikacji w modelu nie uczestniczą w walidacji formularza.

Po uruchomieniu walidacji

Blazor przeprowadza walidację pola i pełną walidację formularza:

  • Walidacja pola jest uruchamiana po zmianie pola. W formularzu interaktywnym występuje to w .NET podczas edytowania formularza przez użytkownika.
  • Walidacja całego formularza zwykle jest uruchamiana, gdy EditForm obsługuje przesłanie formularza za pomocą OnValidSubmit lub OnInvalidSubmit. Program obsługi OnSubmit przejmuje sterowanie walidacją, jak opisano w Kontrolowanie przesyłania formularza.

Statyczny formularz SSR może zapewniać informacje zwrotne w przeglądarce w czasie rzeczywistym dzięki walidacji formularza po stronie klienta w statycznym SSR platformy ASP.NET Core Blazor. Formularz jest ponownie weryfikowany autorytatywnie na serwerze po opublikowaniu.

Statyczny formularz SSR jest weryfikowany na serwerze po opublikowaniu i nie zapewnia weryfikacji pola na żywo między żądaniami.

Wyniki weryfikacji, które identyfikują członka, są powiązane z tym polem. Wyniki bez nazwy elementu członkowskiego są skojarzone z modelem i są wyświetlane w podsumowaniu weryfikacji, a nie w składniku pola ValidationMessage .

Konfigurowanie walidacji adnotacji danych

DataAnnotationsValidator zawsze włącza walidację DataAnnotations dla formularza. Aby użyć rozszerzonych funkcji walidacji udostępnianych przez pakiet Microsoft.Extensions.Validation, wywołaj metodę rozszerzającą AddValidation w pliku Program:

builder.Services.AddValidation();

Wywołanie AddValidation rejestruje usługi weryfikacji pakietu i aktywuje generator źródła, który tworzy metadane weryfikacji dla odnalezionych typów modeli. Dostępne zachowanie zależy od tego, czy te metadane zawierają model formularza:

Konfiguracja Behavior
Wygenerowane metadane są dostępne Weryfikuje zagnieżdżone obiekty i kolekcje oraz obsługuje lokalizację komunikatów.
Wygenerowane metadane nie są dostępne Sprawdza poprawność właściwości najwyższego poziomu, ale nie sprawdza poprawności obiektów zagnieżdżonych ani kolekcji i nie używa mechanizmu lokalizacji komunikatów Microsoft.Extensions.Validation.
Konfiguracja Behavior
Wygenerowane metadane są dostępne Weryfikuje zagnieżdżone obiekty i kolekcje.
Wygenerowane metadane nie są dostępne Weryfikuje tylko właściwości najwyższego poziomu.

Interfejsy API ValidatableTypeAttribute i SkipValidationAttribute są eksperymentalne w .NET 10. Aby uzyskać szczegółowe informacje i dostępne obejścia, zobacz Walidacja w ASP.NET Core.

W przypadku korzystania z programu Microsoft.Extensions.Validationzadeklaruj typy modeli w plikach C# (.cs), a nie Razor w plikach składników (.razor). Generator źródła tworzy metadane weryfikacji ze źródła języka C# i nie może uwzględniać typów modeli zadeklarowanych w Razor składnikach.

Aby uzyskać informacje o wymaganiach dotyczących konfiguracji, kolejności walidacji, reguł niestandardowych, zagnieżdżonych grafach obiektów i wygenerowanych metadanych, zobacz Walidacja w ASP.NET Core.

Weryfikowanie zagnieżdżonych wykresów obiektów

W DataAnnotationsValidator .NET 9 lub starszych wersjach są weryfikowane właściwości modelu najwyższego poziomu, ale nie są rekurencyjnie weryfikowane właściwości kolekcji ani właściwości typów złożonych. Do walidacji rekurencyjnej użyj ObjectGraphDataAnnotationsValidator i [ValidateComplexType] z eksperymentalnego pakietu Microsoft.AspNetCore.Components.DataAnnotations.Validation:

<EditForm Model="Model" OnValidSubmit="Submit">
    <ObjectGraphDataAnnotationsValidator />
    ...
</EditForm>
public class Starship
{
    [ValidateComplexType]
    public ShipDescription Description { get; set; } =
        new ShipDescription();
}

Pakiet pozostaje eksperymentalny w tych wersjach platformy.

Atrybut [CompareProperty]

W przypadku platformy .NET 5 lub wcześniejszej użyj elementu ComparePropertyAttribute z eksperymentalnego pakietu zamiast CompareAttribute. ComparePropertyAttribute Spójnie przypisuje wynik walidacji do pola zarówno podczas walidacji pola, jak i całego formularza.

Pisanie reguł niestandardowych opartych na modelu

Jeśli wbudowane atrybuty nie mogą wyrazić reguły, użyj niestandardowego ValidationAttribute lub IValidatableObject. Aby uzyskać szczegółowe wskazówki, zobacz Walidacja w ASP.NET Core.

Pisanie reguł niestandardowych opartych na modelu

Jeśli wbudowane atrybuty nie mogą wyrazić reguły, użyj niestandardowego atrybutu weryfikacji lub zaimplementuj element IValidatableObject. Oba są uruchamiane przez element DataAnnotationsValidator.

Podczas zwracania obiektu ValidationResult z atrybutu niestandardowego dołącz nazwę zweryfikowanej składowej, aby wynik mógł pojawić się w komponencie ValidationMessage tego pola.

Atrybuty niestandardowe mogą rozpoznawać zarejestrowane usługi za pośrednictwem programu GetService.

Dodaj walidację za pomocą EditContext

EditForm automatycznie tworzy EditContext, gdy przypisany zostanie parametr Model. Aby używać interfejsów API do walidacji bezpośrednio, utwórz EditContext samodzielnie i przypisz go do EditContext. Nie przypisuj jednocześnie Model i EditContext do tego samego formularza.

Walidacja niestandardowa jest często używana:

Poniższy wzorzec formularza interaktywnego dodaje regułę biznesową na poziomie formularza obok walidacji opartej na adnotacjach danych i ponownie sprawdza tę regułę, gdy zmieni się którekolwiek z odpowiednich pól:

@implements IDisposable

<EditForm EditContext="editContext" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    ...
</EditForm>

@code {
    private Starship Model { get; } = new Starship();
    private EditContext editContext = default!;
    private ValidationMessageStore messages = default!;

    protected override void OnInitialized()
    {
        editContext = new EditContext(Model);
        messages = new ValidationMessageStore(editContext);
        editContext.OnValidationRequested += ValidateBusinessRules;
        editContext.OnFieldChanged += ValidateChangedField;
    }

    private void ValidateBusinessRules(
        object? sender, ValidationRequestedEventArgs e)
    {
        messages.Clear();
        ValidateIdentifier();
        editContext.NotifyValidationStateChanged();
    }

    private void ValidateChangedField(
        object? sender, FieldChangedEventArgs e)
    {
        if (e.FieldIdentifier.FieldName != nameof(Starship.Identifier) &&
            e.FieldIdentifier.FieldName != nameof(Starship.MaximumAccommodation))
        {
            return;
        }

        messages.Clear(
            editContext.Field(nameof(Starship.Identifier)));
        ValidateIdentifier();
        editContext.NotifyValidationStateChanged();
    }

    private void ValidateIdentifier()
    {
        if (Model.MaximumAccommodation == 1 &&
            string.IsNullOrWhiteSpace(Model.Identifier))
        {
            messages.Add(
                editContext.Field(nameof(Starship.Identifier)),
                "An identifier is required for a single-occupant ship.");
        }
    }

    private void Submit()
    {
        // Process the valid form.
    }

    public void Dispose()
    {
        editContext.OnValidationRequested -= ValidateBusinessRules;
        editContext.OnFieldChanged -= ValidateChangedField;
    }
}

Moduł obsługi OnFieldChanged otrzymuje zmienione pole w elemencie e.FieldIdentifier. Wyczyść lub zastąp komunikaty, których to dotyczy, i wywołaj NotifyValidationStateChanged, jak pokazano w poprzednim przykładzie.

Usługa SSR statyczna nie zapewnia weryfikacji pól .NET na żywo między żądaniami.

W przypadku asynchronicznej walidacji całego formularza wywołaj metodę e.AddAsyncValidator w programie obsługi OnValidationRequested. Aby przeprowadzić asynchroniczną walidację pola w formularzu interaktywnym, wywołaj EditContext.RegisterAsyncFieldValidator w procedurze obsługi OnFieldChanged. Nowa asynchroniczna walidacja dla tego samego pola zastępuje i anuluje poprzednią.

Aby uzyskać informacje na temat atrybutów walidacji asynchronicznej opartej na modelu, zobacz Walidacja w ASP.NET Core. Aby uzyskać pełny składnik modułu sprawdzania poprawności wielokrotnego użytku, zobacz ASP.NET Core Blazor zaawansowane sprawdzanie poprawności formularza.

Informacje o implementacji wielokrotnego użytku, która enkapsuluje subskrypcje zdarzeń oraz magazyn komunikatów, można znaleźć tutaj: ASP.NET Core Blazor zaawansowane sprawdzanie poprawności formularzy.

Wyświetlanie komunikatów sprawdzania poprawności

Służy ValidationMessage<TValue> do wyświetlania komunikatów skojarzonych z jednym polem:

<ValidationMessage For="() => Model.Identifier" />

Służy ValidationSummary do wyświetlania komunikatów dla formularza:

<ValidationSummary />

Przypisz parametr podsumowania Model , aby ograniczyć go do komunikatów skojarzonych z określonym modelem:

<ValidationSummary Model="Model" />

Aby sprawdzić bieżące komunikaty w kodzie, wywołaj metodę GetValidationMessages:

var allMessages = editContext.GetValidationMessages();
var fieldMessages = editContext.GetValidationMessages(
    editContext.Field(nameof(Starship.Identifier)));

Te metody odczytują bieżący stan weryfikacji. Nie inicjują weryfikacji.

Dostosowywanie wyglądu weryfikacji

Blazor stosuje klasy CSS reprezentujące stan pola i komunikatu:

Element Klasy
Input valid lub invalid, plus modified po edytowaniu pola przez użytkownika
Komunikat dotyczący walidacji validation-message
Podsumowanie weryfikacji validation-summary-errors lub validation-summary-valid

Pola wejściowe z asynchroniczną walidacją pola używają pending lub faulted, opcjonalnie z modified, zamiast valid lub invalid, gdy obowiązuje odpowiedni stan.

Szablony Blazor projektów zawierają style typowych prawidłowych i nieprawidłowych klas. Dodaj style dla innych klas zgodnie z potrzebami. ValidationMessage i ValidationSummary również akceptują dowolne atrybuty HTML. Podanie atrybutu zastępuje domyślną klasę class składnika.

Aby zmienić klasy stosowane w komponentach wejściowych, dziedzicz po FieldCssClassProvider.

using Microsoft.AspNetCore.Components.Forms;

public sealed class BootstrapFieldCssClassProvider : FieldCssClassProvider
{
    public override string GetFieldCssClass(
        EditContext editContext,
        in FieldIdentifier fieldIdentifier)
    {
        if (!editContext.IsModified(fieldIdentifier))
        {
            return string.Empty;
        }

        return editContext.IsValid(fieldIdentifier)
            ? "is-valid"
            : "is-invalid";
    }
}
using System.Linq;
using Microsoft.AspNetCore.Components.Forms;

public sealed class BootstrapFieldCssClassProvider : FieldCssClassProvider
{
    public override string GetFieldCssClass(
        EditContext editContext,
        in FieldIdentifier fieldIdentifier)
    {
        if (!editContext.IsModified(fieldIdentifier))
        {
            return string.Empty;
        }

        return editContext.GetValidationMessages(fieldIdentifier).Any()
            ? "is-invalid"
            : "is-valid";
    }
}

Niestandardowy element FieldCssClassProvider określa pełną wartość atrybutu class dla każdego pola. Jeśli formularz używa asynchronicznej walidacji pól, należy obsłużyć IsValidationPending(fieldIdentifier) i IsValidationFaulted(fieldIdentifier) w dostawcy, gdy wymagane są klasy pending lub faulted.

Przypisz dostawcę do formularza EditContext:

editContext.SetFieldCssClassProvider(
    new BootstrapFieldCssClassProvider());

W przypadku niestandardowych znaczników wejściowych wywołaj metodę FieldCssClass , aby uzyskać klasę wybraną przez bieżącego dostawcę.

Odpowiadanie na stan weryfikacji

EditContext Uwidacznia bieżący stan weryfikacji bez inicjowania walidacji.

  • Użyj IsModified(field) lub IsModified(), aby określić, czy zmieniło się dane pole lub dowolne pole w formularzu.
  • Użyj GetValidationMessages(field) lub GetValidationMessages(), aby sprawdzić bieżące komunikaty pola lub formularza.

Użyj IsValid(field) polecenia , aby określić, czy pole ma obecnie komunikaty sprawdzania poprawności.

W przypadku pola można sprawdzić brak komunikatów za pomocą polecenia !editContext.GetValidationMessages(field).Any().

Poniższy przykład wyświetla niestandardowy interfejs użytkownika dopiero po zmodyfikowaniu pola, gdy jest ono nieprawidłowe:

@{
    var identifier = editContext.Field(nameof(Starship.Identifier));
}

@if (editContext.IsModified(identifier) &&
    !editContext.IsValid(identifier))
{
    <p>Correct the identifier before continuing.</p>
}
@{
    var identifier = editContext.Field(nameof(Starship.Identifier));
}

@if (editContext.IsModified(identifier) &&
    editContext.GetValidationMessages(identifier).Any())
{
    <p>Correct the identifier before continuing.</p>
}

Składniki wejściowe, ValidationMessagei ValidationSummary aktualizują się po zmianie stanu weryfikacji. Składnik, który renderuje inny interfejs użytkownika warunkowej walidacji, powinien subskrybować OnValidationStateChanged i wywoływać StateHasChanged:

private void HandleValidationStateChanged(
    object? sender, ValidationStateChangedEventArgs e) =>
    _ = InvokeAsync(StateHasChanged);

Anuluj subskrypcję OnValidationStateChanged po usunięciu składnika.

Użyj wartości IsValidationPending(field) i IsValidationFaulted(field) do sprawdzania poprawności pola asynchronicznego. Metody bez parametrów opisują przebiegi na poziomie ValidateAsync formularza i nie agregują stanu każdego pola.

Te stany obejmują również pracę asynchroniczną wykonywaną przez DataAnnotationsValidator. Element AsyncValidationAttribute zastosowany do właściwości używa stanu pola podczas walidacji pola, w tym domyślnych klas CSS pending i faulted. Podczas ValidateAsync, atrybuty asynchroniczne i IAsyncValidatableObject przyczyniają się do stanu na poziomie formularza raportowanego przez metody bez parametrów.

Dynamiczne wskaźniki oczekiwania wymagają interaktywnego trybu renderowania. Podczas publikowania statycznego formularza SSR walidacja po stronie serwera zostanie ukończona przed renderowaniem odpowiedzi.

Kontrolowanie przesyłania formularza

EditForm udostępnia trzy funkcje wywołania zwrotnego dla przesyłania:

Oddzwonienie Behavior
OnValidSubmit Uruchamia się po pomyślnej automatycznej weryfikacji.
OnInvalidSubmit Uruchamia się po niepowodzeniu automatycznej walidacji.
OnSubmit Daje programowi obsługi kontrolę nad walidacją i przesyłaniem.

OnValidSubmit i OnInvalidSubmit mogą być używane razem. Nie łącz OnSubmit z żadnym z nich.

EditForm używa ValidateAsync przed wywołaniem OnValidSubmit lub OnInvalidSubmit, więc czeka na synchroniczne i asynchroniczne walidatory. Podczas obsługi OnSubmit wywołaj ValidateAsync przed przetworzeniem formularza:

<EditForm EditContext="editContext" OnSubmit="HandleSubmit">
    ...
</EditForm>

@code {
    private async Task HandleSubmit(EditContext editContext)
    {
        if (await editContext.ValidateAsync())
        {
            await SaveAsync();
        }
    }
}

Metoda synchroniczna Validate jest przestarzała w .NET 11. Nie oczekuje on na walidację asynchroniczną i zgłasza błąd, jeśli program obsługi próbuje zarejestrować pracę asynchroniczną.

W przypadku formularzy interaktywnych stan oczekiwania na poziomie formularza może służyć do wyłączenia przesyłania formularza, gdy działa ValidateAsync:

<button type="submit" disabled="@editContext.IsValidationPending()">
    Save
</button>

Podczas obsługi OnSubmit wywołaj Validate przed przetworzeniem formularza:

<EditForm EditContext="editContext" OnSubmit="HandleSubmit">
    ...
</EditForm>

@code {
    private void HandleSubmit(EditContext editContext)
    {
        if (editContext.Validate())
        {
            Save();
        }
    }
}

Dodatkowe zasoby