Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Warnung
Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der .NET- und .NET Core-Supportrichtlinie. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Wichtig
Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.
Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
In diesem Artikel wird erläutert, wie Sie die Überprüfung in Blazor-Formularen verwenden.
Formularprüfung
In grundlegenden Formularvalidierungsszenarien kann eine EditForm-Instanz deklarierte EditContext- und ValidationMessageStore-Instanzen verwenden, um Formularfelder zu überprüfen. Ein Handler für das OnValidationRequested-Ereignis von EditContext führt eine benutzerdefinierte Validierungslogik aus. Das Ergebnis des Handlers aktualisiert die ValidationMessageStore-Instanz.
Die grundlegende Formularvalidierung ist in Fällen nützlich, in denen das Modell des Formulars in der Komponente definiert ist, die das Formular hostet, entweder als Member direkt in der Komponente oder in einer Unterklasse. Die Verwendung einer Validierungskomponente wird empfohlen, wenn eine unabhängige Modellklasse für mehrere Komponenten verwendet wird.
In Blazor Web Apps erfordert die clientseitige Validierung eine aktive BlazorSignalR-Schaltung. Die clientseitige Überprüfung ist für Formulare in Komponenten, die statisches serverseitiges Rendering (statisches SSR) übernommen haben, nicht verfügbar. Formulare, die statisches SSR übernehmen, werden auf dem Server überprüft, nachdem das Formular gesendet wurde.
In der folgenden Komponente löscht die HandleValidationRequested
-Handlermethode alle vorhandenen Validierungsnachrichten, indem sie vor dem Überprüfen des Formulars ValidationMessageStore.Clear aufruft.
Starship8.razor
:
@page "/starship-8"
@implements IDisposable
@inject ILogger<Starship8> Logger
<h2>Holodeck Configuration</h2>
<EditForm EditContext="editContext" OnValidSubmit="Submit" FormName="Starship8">
<div>
<label>
<InputCheckbox @bind-Value="Model!.Subsystem1" />
Safety Subsystem
</label>
</div>
<div>
<label>
<InputCheckbox @bind-Value="Model!.Subsystem2" />
Emergency Shutdown Subsystem
</label>
</div>
<div>
<ValidationMessage For="() => Model!.Options" />
</div>
<div>
<button type="submit">Update</button>
</div>
</EditForm>
@code {
private EditContext? editContext;
[SupplyParameterFromForm]
private Holodeck? Model { get; set; }
private ValidationMessageStore? messageStore;
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
editContext.OnValidationRequested += HandleValidationRequested;
messageStore = new(editContext);
}
private void HandleValidationRequested(object? sender,
ValidationRequestedEventArgs args)
{
messageStore?.Clear();
// Custom validation logic
if (!Model!.Options)
{
messageStore?.Add(() => Model.Options, "Select at least one.");
}
}
private void Submit() => Logger.LogInformation("Submit: Processing form");
public class Holodeck
{
public bool Subsystem1 { get; set; }
public bool Subsystem2 { get; set; }
public bool Options => Subsystem1 || Subsystem2;
}
public void Dispose()
{
if (editContext is not null)
{
editContext.OnValidationRequested -= HandleValidationRequested;
}
}
}
@page "/starship-8"
@implements IDisposable
@inject ILogger<Starship8> Logger
<h2>Holodeck Configuration</h2>
<EditForm EditContext="editContext" OnValidSubmit="Submit" FormName="Starship8">
<div>
<label>
<InputCheckbox @bind-Value="Model!.Subsystem1" />
Safety Subsystem
</label>
</div>
<div>
<label>
<InputCheckbox @bind-Value="Model!.Subsystem2" />
Emergency Shutdown Subsystem
</label>
</div>
<div>
<ValidationMessage For="() => Model!.Options" />
</div>
<div>
<button type="submit">Update</button>
</div>
</EditForm>
@code {
private EditContext? editContext;
[SupplyParameterFromForm]
private Holodeck? Model { get; set; }
private ValidationMessageStore? messageStore;
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
editContext.OnValidationRequested += HandleValidationRequested;
messageStore = new(editContext);
}
private void HandleValidationRequested(object? sender,
ValidationRequestedEventArgs args)
{
messageStore?.Clear();
// Custom validation logic
if (!Model!.Options)
{
messageStore?.Add(() => Model.Options, "Select at least one.");
}
}
private void Submit() => Logger.LogInformation("Submit: Processing form");
public class Holodeck
{
public bool Subsystem1 { get; set; }
public bool Subsystem2 { get; set; }
public bool Options => Subsystem1 || Subsystem2;
}
public void Dispose()
{
if (editContext is not null)
{
editContext.OnValidationRequested -= HandleValidationRequested;
}
}
}
@page "/starship-8"
@implements IDisposable
@inject ILogger<Starship8> Logger
<h2>Holodeck Configuration</h2>
<EditForm EditContext="editContext" OnValidSubmit="Submit">
<div>
<label>
<InputCheckbox @bind-Value="Model!.Subsystem1" />
Safety Subsystem
</label>
</div>
<div>
<label>
<InputCheckbox @bind-Value="Model!.Subsystem2" />
Emergency Shutdown Subsystem
</label>
</div>
<div>
<ValidationMessage For="() => Model!.Options" />
</div>
<div>
<button type="submit">Update</button>
</div>
</EditForm>
@code {
private EditContext? editContext;
public Holodeck? Model { get; set; }
private ValidationMessageStore? messageStore;
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
editContext.OnValidationRequested += HandleValidationRequested;
messageStore = new(editContext);
}
private void HandleValidationRequested(object? sender,
ValidationRequestedEventArgs args)
{
messageStore?.Clear();
// Custom validation logic
if (!Model!.Options)
{
messageStore?.Add(() => Model.Options, "Select at least one.");
}
}
private void Submit()
{
Logger.LogInformation("Submit called: Processing the form");
}
public class Holodeck
{
public bool Subsystem1 { get; set; }
public bool Subsystem2 { get; set; }
public bool Options => Subsystem1 || Subsystem2;
}
public void Dispose()
{
if (editContext is not null)
{
editContext.OnValidationRequested -= HandleValidationRequested;
}
}
}
Validierungssteuerelementkomponente für Datenanmerkungen und benutzerdefinierte Validierung
Die DataAnnotationsValidator-Komponente fügt einem kaskadierten EditContext Validierung durch Datenanmerkungen hinzu. Zum Aktivieren der Validierung durch Datenanmerkungen ist die DataAnnotationsValidator-Komponente erforderlich. Wenn Sie ein anderes Validierungssystem als Datenanmerkungen verwenden möchten, verwenden Sie eine benutzerdefinierte Implementierung anstelle der DataAnnotationsValidator-Komponente. Die Frameworkimplementierungen für DataAnnotationsValidator können Sie sich in der Verweisquelle ansehen:
Wenn Sie die Unterstützung für die Validierung von Datenkommentaren für ein EditContext im Code aktivieren müssen, rufen Sie EnableDataAnnotationsValidation mit einem injizierten IServiceProvider (@inject IServiceProvider ServiceProvider
) auf dem EditContextauf. Ein erweitertes Beispiel finden Sie in der NotifyPropertyChangedValidationComponent
Komponente im ASP.NET Core Blazor Frameworks BasicTestApp
(dotnet/aspnetcore
GitHub-Repository). In einer Produktionsversion des Beispiels ersetzen Sie das Argument new TestServiceProvider()
für den Dienstanbieter durch ein injiziertes IServiceProvider.
Hinweis
Dokumentationslinks zur .NET-Referenzquelle laden in der Regel den Standardbranch des Repositorys, der die aktuelle Entwicklung für das nächste Release von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).
Blazor führt zwei Validierungstypen aus:
- Die Feldvalidierung wird ausgeführt, wenn der Benutzer auf eine Stelle außerhalb des Felds tippt. Während der Feldvalidierung ordnet die DataAnnotationsValidator-Komponente alle gemeldeten Validierungsergebnisse dem Feld zu.
- Modellvalidierung wird ausgeführt, wenn der Benutzer ein Formular sendet. Während der Modellvalidierung versucht die DataAnnotationsValidator-Komponente, das Feld basierend auf dem vom Validierungsergebnis gemeldeten Mitgliedsnamen zu ermitteln. Validierungsergebnisse, die keinem einzelnen Member zugeordnet werden, werden dem Modell und keinem Feld zugeordnet.
In benutzerdefinierten Überprüfungsszenarien:
- Die Validierung verwaltet ein ValidationMessageStore für das EditContexteines Formulars.
- Die DataAnnotationsValidator Komponente wird verwendet, um Validierungsunterstützung an Formulare anzufügen, die auf Validierungsattributen (Datenanmerkungen)basieren.
Es gibt zwei allgemeine Ansätze zum Erreichen der benutzerdefinierten Validierung, die in den nächsten beiden Abschnitten dieses Artikels beschrieben werden:
- Manuelle Überprüfung mithilfe des
OnValidationRequested
-Ereignisses: Manuelle Überprüfung der Felder eines Formulars mit Datenanmerkungsüberprüfung und benutzerdefiniertem Code für Feldprüfungen, wenn die Überprüfung über einen Ereignishandler angefordert wird, der dem OnValidationRequested-Ereignis zugewiesen ist. - Validator-Komponenten: Eine oder mehrere benutzerdefinierte Validatorkomponenten können verwendet werden, um die Überprüfung für verschiedene Formulare auf derselben Seite oder dasselbe Formular bei verschiedenen Schritten der Formularverarbeitung zu verarbeiten (z. B. clientvalidierung gefolgt von der Serverüberprüfung).
Manuelle Überprüfung mithilfe des OnValidationRequested
-Ereignisses
Sie können ein Formular manuell validieren, indem Sie einen benutzerdefinierten Ereignishandler verwenden, der dem EditContext.OnValidationRequested-Ereignis zugewiesen ist, um ein ValidationMessageStorezu verwalten.
Das Blazor-Framework bietet die DataAnnotationsValidator-Komponente, um Formulare auf der Grundlage von Validierungsattributen (Datenannotationen)mit zusätzlicher Validierungsunterstützung zu versehen.
Unter Hinweis auf das frühere Starship8
Komponentenbeispiel wird die HandleValidationRequested
Methode OnValidationRequestedzugewiesen, wo Sie eine manuelle Überprüfung im C#-Code ausführen können. Einige Änderungen zeigen, wie man die vorhandene manuelle Überprüfung mit der Überprüfung durch Datenanmerkungen unter Verwendung von DataAnnotationsValidator und einem Überprüfungsattribut, das auf das Holodeck
-Modell angewendet wird, kombiniert.
Verweisen Sie auf den System.ComponentModel.DataAnnotations-Namensraum in den Razor-Direktiven der Komponente am Anfang der Komponentendefinitionsdatei:
@using System.ComponentModel.DataAnnotations
Fügen Sie dem Holodeck
-Modell eine Id
-Eigenschaft mit einem Überprüfungsattribut hinzu, um die Länge der Zeichenfolge auf sechs Zeichen zu beschränken:
[StringLength(6)]
public string? Id { get; set; }
Fügen Sie dem Formular eine DataAnnotationsValidator Komponente (<DataAnnotationsValidator />
) hinzu. In der Regel wird die Komponente direkt unter dem <EditForm>
-Tag platziert, Sie können sie jedoch an einer beliebigen Stelle im Formular platzieren:
<DataAnnotationsValidator />
Ändern Sie das Sendeverhalten des Formulars im tag <EditForm>
von OnSubmit in OnValidSubmit, wodurch sichergestellt wird, dass das Formular gültig ist, bevor die zugewiesene Ereignishandlermethode ausgeführt wird:
- OnSubmit="Submit"
+ OnValidSubmit="Submit"
Fügen Sie im <EditForm>
ein Feld für die eigenschaft Id
hinzu:
<div>
<label>
<InputText @bind-Value="Model!.Id" />
ID (6 characters max)
</label>
<ValidationMessage For="() => Model!.Id" />
</div>
Nachdem Sie die vorherigen Änderungen vorgenommen haben, entspricht das Verhalten des Formulars der folgenden Spezifikation:
- Die Überprüfung der Datenanmerkungen für die
Id
-Eigenschaft löst keinen Überprüfungsfehler aus, wenn dasId
Feld lediglich den Fokus verliert. Die Überprüfung wird ausgeführt, wenn der Benutzer die SchaltflächeUpdate
auswählt. - Jede manuelle Überprüfung, die Sie in der
HandleValidationRequested
Methode ausführen möchten, die dem OnValidationRequested Ereignis des Formulars zugewiesen ist, wird ausgeführt, wenn der Benutzer die SchaltflächeUpdate
des Formulars auswählt. Im vorhandenen Code desStarship8
Komponentenbeispiels muss der Benutzer entweder oder beide Kontrollkästchen auswählen, um das Formular zu überprüfen. - Das Formular verarbeitet die
Submit
Methode erst, wenn sowohl die Datenanmerkungen als auch die manuelle Validierung bestanden wurden.
Validatorkomponenten
Validierungssteuerelementkomponenten unterstützen Formularvalidierung durch die Verwaltung eines ValidationMessageStore für den EditContext eines Formulars.
Das Blazor-Framework stellt die DataAnnotationsValidator-Komponente zum Anfügen von Validierungsunterstützung zu Formularen auf der Grundlage von Validierungsattributen (Datenanmerkungen) zur Verfügung. Sie können Komponenten für benutzerdefinierte Validierungssteuerelemente erstellen, um Validierungsmeldungen für verschiedene Formulare auf derselben Seite oder im selben Formular in verschiedenen Schritten der Formularverarbeitung zu verarbeiten, z. B. Clientvalidierung gefolgt von Servervalidierung. Das in diesem Abschnitt gezeigte Beispiel für eine Validierungssteuerelementkomponente (CustomValidation
) wird in den folgenden Abschnitten dieses Artikels verwendet:
- Geschäftslogikvaliderung mit einer Validierungskomponente
- Servervaliderung mit einer Validierungskomponente
Von den in Datenanmerkungen integrierten Validatoren wird nur das [Remote]
-Überprüfungsattribut in Blazor nicht unterstützt.
Hinweis
In vielen Fällen können benutzerdefinierte Validierungsattribute für Datenanmerkungen anstelle von benutzerdefinierten Validator-Komponenten verwendet werden. Benutzerdefinierte Attribute, die auf das Modell des Formulars angewendet werden, werden mit der Verwendung der DataAnnotationsValidator-Komponente aktiviert. Bei Verwendung mit Servervalidierung müssen alle benutzerdefinierten Attribute, die auf das Modell angewendet werden, auf dem Server ausführbar sein. Weitere Informationen finden Sie im Abschnitt Benutzerdefinierte Validierungsattribute.
Erstellen Sie eine Validator-Komponente aus ComponentBase:
- Der EditContext des Formulars ist ein kaskadierender Parameter der Komponente.
- Wenn die Validierungskomponente initialisiert wird, wird ein neuer ValidationMessageStore erstellt, um eine aktuelle Liste der Formular-Fehler zu verwalten.
- Der Nachrichtenspeicher empfängt Fehler, wenn Entwicklercode in der Komponente des Formulars die
DisplayErrors
-Methode aufruft. Die Fehler werden an dieDisplayErrors
-Methode in einemDictionary<string, List<string>>
übergeben. Im Wörterbuch ist der Schlüssel der Name des Formularfelds, das mindestens einen Fehler aufweist. Der Wert ist die Fehlerliste. - Meldungen werden gelöscht, wenn eines der folgenden Ereignisse aufgetreten ist:
- Validierung wird für den EditContext angefordert, wenn das OnValidationRequested-Ereignis ausgelöst wird. Alle Fehler werden gelöscht.
- Ein Feld ändert sich im Formular, wenn das OnFieldChanged-Ereignis ausgelöst wird. Nur die Fehler für das Feld werden gelöscht.
- Die
ClearErrors
-Methode wird vom Entwicklercode aufgerufen. Alle Fehler werden gelöscht.
Aktualisieren Sie den Namespace in der folgenden Klasse so, dass er dem Namespace Ihrer App entspricht.
CustomValidation.cs
:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
namespace BlazorSample;
public class CustomValidation : ComponentBase
{
private ValidationMessageStore? messageStore;
[CascadingParameter]
private EditContext? CurrentEditContext { get; set; }
protected override void OnInitialized()
{
if (CurrentEditContext is null)
{
throw new InvalidOperationException(
$"{nameof(CustomValidation)} requires a cascading " +
$"parameter of type {nameof(EditContext)}. " +
$"For example, you can use {nameof(CustomValidation)} " +
$"inside an {nameof(EditForm)}.");
}
messageStore = new(CurrentEditContext);
CurrentEditContext.OnValidationRequested += (s, e) =>
messageStore?.Clear();
CurrentEditContext.OnFieldChanged += (s, e) =>
messageStore?.Clear(e.FieldIdentifier);
}
public void DisplayErrors(Dictionary<string, List<string>> errors)
{
if (CurrentEditContext is not null)
{
foreach (var err in errors)
{
messageStore?.Add(CurrentEditContext.Field(err.Key), err.Value);
}
CurrentEditContext.NotifyValidationStateChanged();
}
}
public void ClearErrors()
{
messageStore?.Clear();
CurrentEditContext?.NotifyValidationStateChanged();
}
}
Wichtig
Beim Ableiten von ComponentBase ist die Angabe eines Namespace erforderlich. Wenn kein Namespace angegeben wird, führt dies zu einem Buildfehler:
Tag helpers cannot target tag name '<global namespace>.{CLASS NAME}' because it contains a ' ' character.
Der Platzhalter {CLASS NAME}
ist der Name der Komponentenklasse. Im Beispiel für einen benutzerdefinierten Validator in diesem Abschnitt wird der Beispiel-Namespace BlazorSample
angegeben.
Hinweis
Im obigen Beispiel sind anonyme Lambdaausdrücke registrierte Ereignishandler für OnValidationRequested und OnFieldChanged. In diesem Szenario muss IDisposable nicht implementiert und das Abonnement der Ereignisdelegate nicht beendet werden. Weitere Informationen finden Sie unter ASP.NET Core Razor Komponentenentsorgung.
Geschäftslogikvaliderung mit einer Validierungskomponente
Verwenden Sie zur allgemeinen Validierung der Geschäftslogik eine Validator-Komponente, die Formularfehler in einem Wörterbuch empfängt.
Die grundlegende Validierung ist in Fällen nützlich, in denen das Modell des Formulars in der Komponente definiert ist, die das Formular hostet, entweder als Member direkt in der Komponente oder in einer Unterklasse. Die Verwendung einer Validierungskomponente wird empfohlen, wenn eine unabhängige Modellklasse für mehrere Komponenten verwendet wird.
Im folgenden Beispiel:
- Es wird eine verkürzte Version des
Starfleet Starship Database
-Formulars (Starship3
-Komponente) aus dem Abschnitt Beispielformular im Artikel Eingabekomponenten verwendet, die nur die Klassifizierung und Beschreibung des Raumfahrzeugs akzeptiert. Die Validierung von Datenkommentaren wird bei der Übermittlung des Formulars nicht ausgelöst, da die Komponente DataAnnotationsValidator nicht im Formular enthalten ist. - Die Komponente
CustomValidation
aus dem Abschnitt Validator-Komponenten dieses Artikels wird verwendet. - Die Validierung erfordert einen Wert für die Beschreibung des Schiffs (
Description
), wenn der Benutzer die Schiffsklassifizierung (Defense
) „Classification
“ auswählt.
Wenn Validierungsmeldungen in der Komponente festgelegt werden, werden sie dem ValidationMessageStore des Validators hinzugefügt und in der Validierungszusammenfassung des EditForm angezeigt.
Starship9.razor
:
@page "/starship-9"
@inject ILogger<Starship9> Logger
<h1>Starfleet Starship Database</h1>
<h2>New Ship Entry Form</h2>
<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship9">
<CustomValidation @ref="customValidation" />
<ValidationSummary />
<div>
<label>
Primary Classification:
<InputSelect @bind-Value="Model!.Classification">
<option value="">
Select classification ...
</option>
<option checked="@(Model!.Classification == "Exploration")"
value="Exploration">
Exploration
</option>
<option checked="@(Model!.Classification == "Diplomacy")"
value="Diplomacy">
Diplomacy
</option>
<option checked="@(Model!.Classification == "Defense")"
value="Defense">
Defense
</option>
</InputSelect>
</label>
</div>
<div>
<label>
Description (optional):
<InputTextArea @bind-Value="Model!.Description" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
private CustomValidation? customValidation;
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() =>
Model ??= new() { ProductionDate = DateTime.UtcNow };
private void Submit()
{
customValidation?.ClearErrors();
var errors = new Dictionary<string, List<string>>();
if (Model!.Classification == "Defense" &&
string.IsNullOrEmpty(Model.Description))
{
errors.Add(nameof(Model.Description),
[ "For a 'Defense' ship classification, " +
"'Description' is required." ]);
}
if (errors.Any())
{
customValidation?.DisplayErrors(errors);
}
else
{
Logger.LogInformation("Submit called: Processing the form");
}
}
}
@page "/starship-9"
@inject ILogger<Starship9> Logger
<h1>Starfleet Starship Database</h1>
<h2>New Ship Entry Form</h2>
<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship9">
<CustomValidation @ref="customValidation" />
<ValidationSummary />
<div>
<label>
Primary Classification:
<InputSelect @bind-Value="Model!.Classification">
<option value="">
Select classification ...
</option>
<option checked="@(Model!.Classification == "Exploration")"
value="Exploration">
Exploration
</option>
<option checked="@(Model!.Classification == "Diplomacy")"
value="Diplomacy">
Diplomacy
</option>
<option checked="@(Model!.Classification == "Defense")"
value="Defense">
Defense
</option>
</InputSelect>
</label>
</div>
<div>
<label>
Description (optional):
<InputTextArea @bind-Value="Model!.Description" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
private CustomValidation? customValidation;
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() =>
Model ??= new() { ProductionDate = DateTime.UtcNow };
private void Submit()
{
customValidation?.ClearErrors();
var errors = new Dictionary<string, List<string>>();
if (Model!.Classification == "Defense" &&
string.IsNullOrEmpty(Model.Description))
{
errors.Add(nameof(Model.Description),
[ "For a 'Defense' ship classification, " +
"'Description' is required." ]);
}
if (errors.Any())
{
customValidation?.DisplayErrors(errors);
}
else
{
Logger.LogInformation("Submit called: Processing the form");
}
}
}
@page "/starship-9"
@inject ILogger<Starship9> Logger
<h1>Starfleet Starship Database</h1>
<h2>New Ship Entry Form</h2>
<EditForm Model="Model" OnValidSubmit="Submit">
<CustomValidation @ref="customValidation" />
<ValidationSummary />
<div>
<label>
Primary Classification:
<InputSelect @bind-Value="Model!.Classification">
<option value="">Select classification ...</option>
<option value="Exploration">Exploration</option>
<option value="Diplomacy">Diplomacy</option>
<option value="Defense">Defense</option>
</InputSelect>
</label>
</div>
<div>
<label>
Description (optional):
<InputTextArea @bind-Value="Model!.Description" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
private CustomValidation? customValidation;
public Starship? Model { get; set; }
protected override void OnInitialized() =>
Model ??= new() { ProductionDate = DateTime.UtcNow };
private void Submit()
{
customValidation?.ClearErrors();
var errors = new Dictionary<string, List<string>>();
if (Model!.Classification == "Defense" &&
string.IsNullOrEmpty(Model.Description))
{
errors.Add(nameof(Model.Description),
new() { "For a 'Defense' ship classification, " +
"'Description' is required." });
}
if (errors.Any())
{
customValidation?.DisplayErrors(errors);
}
else
{
Logger.LogInformation("Submit called: Processing the form");
}
}
}
Hinweis
Als Alternative zur Verwendung von Validierungkomponenten können Datenanmerkungs-Validierungsattribute verwendet werden. Benutzerdefinierte Attribute, die auf das Modell des Formulars angewendet werden, werden mit der Verwendung der DataAnnotationsValidator-Komponente aktiviert. Bei Verwendung mit Servervalidierung müssen die Attribute auf dem Server ausführbar sein. Weitere Informationen finden Sie im Abschnitt Benutzerdefinierte Validierungsattribute.
Servervaliderung mit einer Validierungskomponente
In diesem Abschnitt geht es primär um Blazor Web App-Szenarien, aber der gleiche allgemeine Ansatz wird für jede Art von App verwendet, die eine Servervalidierung mit der Web-API nutzt.
In diesem Abschnitt geht es primär um gehostete Blazor WebAssembly-Szenarien, aber der gleiche allgemeine Ansatz wird für jede Art von App verwendet, die eine Servervalidierung mit der Web-API nutzt.
Die Servervalidierung wird zusätzlich zur Clientvalidierung unterstützt:
- Verarbeiten Sie die Clientvalidierung im Formular mit der DataAnnotationsValidator-Komponente.
- Wenn das Formular die Clientvalidierung besteht (OnValidSubmit wird aufgerufen), senden Sie EditContext.Model zur Formularverarbeitung an eine Back-End-Server-API.
- Validierung des Prozessmodells auf dem Server.
- Die Server-API umfasst sowohl die integrierte Framework-Datenanmerkungsvalidierung als auch benutzerdefinierte Validierungslogik, die vom Entwickler bereitgestellt wird. Wenn die Validierung auf dem Server bestanden wird, wird das Formular verarbeitet und ein Erfolgsstatuscode zurückgesendet (
200 - OK
). Wenn die Validierung fehlschlägt, werden ein Fehlerstatuscode (400 - Bad Request
) und die Feldvalidierungsfehler zurückgegeben. - Deaktivieren Sie entweder das Formular bei Erfolg, oder zeigen Sie die Fehler an.
Die grundlegende Validierung ist in Fällen nützlich, in denen das Modell des Formulars in der Komponente definiert ist, die das Formular hostet, entweder als Member direkt in der Komponente oder in einer Unterklasse. Die Verwendung einer Validierungskomponente wird empfohlen, wenn eine unabhängige Modellklasse für mehrere Komponenten verwendet wird.
Das folgende Beispiel beruht auf Folgendem:
- Ein Blazor Web App mit interaktiven WebAssembly-Komponenten, die aus der Blazor Web App Projektvorlageerstellt wurden.
- Das
Starship
-Modell (Starship.cs
) aus dem Abschnitt Beispielformular des Artikels Eingabekomponenten - Die
CustomValidation
-Komponente, die im Abschnitt Validator-Komponenten gezeigt wird.
Platzieren Sie das Starship
-Modell (Starship.cs
) in einem freigegebenen Klassenbibliotheksprojekt, damit sowohl Client- als auch Serverprojekte das Modell verwenden können. Fügen Sie den Namespace hinzu, oder aktualisieren Sie ihn so, dass er mit dem Namespace der freigegebenen App (z. B. namespace BlazorSample.Shared
) übereinstimmt. Da für das Modell Datenanmerkungen erforderlich sind, vergewissern Sie sich, dass die freigegebene Klassenbibliothek das freigegebene Framework verwendet, oder fügen Sie das System.ComponentModel.Annotations
-Paket dem freigegebenen Projekt hinzu.
Hinweis
Eine Anleitung zum Hinzufügen von Paketen zu .NET-Anwendungen finden Sie in den Artikeln unter Pakete installieren und verwalten unter Workflow für die Paketnutzung (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.
Fügen Sie im Hauptprojekt des Blazor Web Appeinen Controller hinzu, der Validierungsanfragen für Raumschiffe verarbeitet und Meldungen über fehlgeschlagene Validierungen zurückgibt. Aktualisieren Sie die Namespaces in der letzten using
-Anweisung für das freigegebene Klassenbibliotheksprojekt und in der namespace
-Anweisung für die Controllerklasse. Zusätzlich zur Client- und Servervalidierung durch Datenanmerkungen überprüft der Controller, ob ein Wert für die Beschreibung des Schiffs (Description
) angegeben ist, wenn der oder die Benutzer*in die Schiffsklassifizierung Defense
(Classification
) auswählt.
- Einer gehosteten Blazor WebAssemblyLösung, die auf Grundlage der Blazor WebAssembly-Projektvorlage erstellt wurde. Der Ansatz wird für alle sicheren gehosteten Blazor-Lösungen unterstützt, die in der Dokumentation zur gehosteten Blazor WebAssembly-Sicherheit beschrieben sind.
- Das
Starship
-Modell (Starship.cs
) aus dem Abschnitt Beispielformular des Artikels Eingabekomponenten - Der
CustomValidation
-Komponent im Abschnitt Validator-Komponenten.
Platzieren Sie das Starship
-Modell (Starship.cs
) im Shared
-Projekt der Lösung, sodass sowohl die Client- als auch die Server-App das Modell verwenden kann. Fügen Sie den Namespace hinzu, oder aktualisieren Sie ihn so, dass er mit dem Namespace der freigegebenen App (z. B. namespace BlazorSample.Shared
) übereinstimmt. Fügen Sie das Paket System.ComponentModel.Annotations
dem Projekt Shared
hinzu, da das Modell Datenanmerkungen erfordert.
Hinweis
Eine Anleitung zum Hinzufügen von Paketen zu .NET-Anwendungen finden Sie in den Artikeln unter Pakete installieren und verwalten unter Workflow für die Paketnutzung (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.
Fügen Sie im Server -Projekt einen Controller hinzu, um die Anforderungen für die Validierung von „Starship“ zu verarbeiten und bei Validierungsfehlern Meldungen zurückzugeben. Aktualisieren Sie die Namespaces in der letzten using
-Anweisung sowohl für das Shared
-Projekt als auch für die namespace
-Controllerklasse. Zusätzlich zur Client- und Servervalidierung durch Datenanmerkungen überprüft der Controller, ob ein Wert für die Beschreibung des Schiffs (Description
) angegeben ist, wenn der oder die Benutzer*in die Schiffsklassifizierung Defense
(Classification
) auswählt.
Die Validierung für die Schiffsklassifizierung Defense
erfolgt nur serverseitig im Controller, da das anstehende Formular clientseitig nicht dieselbe Validierung ausführt, wenn das Formular an den Server übermittelt wird. Die Serverüberprüfung ohne Clientüberprüfung ist in Apps üblich, die eine private Überprüfung der Geschäftslogik von Benutzereingaben auf dem Server erfordern. Beispielsweise können private Informationen aus Daten, die für einen Benutzer gespeichert sind, erforderlich sein, um Benutzereingaben zu überprüfen. Private Daten können offensichtlich nicht zur Clientvalidierung an den Client gesendet werden.
Hinweis
Der StarshipValidation
-Controller in diesem Abschnitt verwendet Microsoft Identity 2.0. Die Web-API akzeptiert nur Token für Benutzer, die den Bereich API.Access
für diese API besitzen. Eine zusätzliche Anpassung ist erforderlich, wenn sich der Bereichsname der API von API.Access
unterscheidet.
Weitere Informationen zur Sicherheit finden Sie unter:
- ASP.NET Core Blazor Authentifizierung und Autorisierung (und die anderen Artikel im Knoten BlazorSicherheit und Identity )
- Microsoft Identity Platform-Dokumentation
Controllers/StarshipValidation.cs
:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using BlazorSample.Shared;
namespace BlazorSample.Server.Controllers;
[Authorize]
[ApiController]
[Route("[controller]")]
public class StarshipValidationController(
ILogger<StarshipValidationController> logger)
: ControllerBase
{
static readonly string[] scopeRequiredByApi = [ "API.Access" ];
[HttpPost]
public async Task<IActionResult> Post(Starship model)
{
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
try
{
if (model.Classification == "Defense" &&
string.IsNullOrEmpty(model.Description))
{
ModelState.AddModelError(nameof(model.Description),
"For a 'Defense' ship " +
"classification, 'Description' is required.");
}
else
{
logger.LogInformation("Processing the form asynchronously");
// async ...
return Ok(ModelState);
}
}
catch (Exception ex)
{
logger.LogError("Validation Error: {Message}", ex.Message);
}
return BadRequest(ModelState);
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using BlazorSample.Shared;
namespace BlazorSample.Server.Controllers;
[Authorize]
[ApiController]
[Route("[controller]")]
public class StarshipValidationController(
ILogger<StarshipValidationController> logger)
: ControllerBase
{
static readonly string[] scopeRequiredByApi = new[] { "API.Access" };
[HttpPost]
public async Task<IActionResult> Post(Starship model)
{
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
try
{
if (model.Classification == "Defense" &&
string.IsNullOrEmpty(model.Description))
{
ModelState.AddModelError(nameof(model.Description),
"For a 'Defense' ship " +
"classification, 'Description' is required.");
}
else
{
logger.LogInformation("Processing the form asynchronously");
// async ...
return Ok(ModelState);
}
}
catch (Exception ex)
{
logger.LogError("Validation Error: {Message}", ex.Message);
}
return BadRequest(ModelState);
}
}
Überprüfen Sie, ob der Namespace des vorherigen Controllers (BlazorSample.Server.Controllers
) mit dem Namespace des Controllers der App übereinstimmt, oder aktualisieren Sie ihn.
Wenn ein Validierungsfehler bei der Modellbindung auf dem Server auftritt, gibt ein ApiController
(ApiControllerAttribute) normalerweise eine Standardantwort „Ungültige Anforderung“ mit ValidationProblemDetails zurück. Die Antwort enthält mehr Daten als nur die Validierungsfehler (wie im folgenden Beispiel gezeigt), wenn alle Felder des Starfleet Starship Database
-Formulars nicht übermittelt wurden und die Validierung des Formulars fehlschlägt:
{
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"Id": [ "The Id field is required." ],
"Classification": [ "The Classification field is required." ],
"IsValidatedDesign": [ "This form disallows unapproved ships." ],
"MaximumAccommodation": [ "Accommodation invalid (1-100000)." ]
}
}
Hinweis
Um die vorangehende JSON-Antwort zu veranschaulichen, müssen Sie entweder die Clientvalidierung des Formulars deaktivieren, um die Übermittlung leerer Feldformulare zu ermöglichen, oder ein Tool verwenden, um eine Anforderung direkt an die Server-API zu senden, z. B. Firefox Browser Developer.
Wenn die Server-API die vorherige JSON-Standardantwort zurückgibt, ist es möglich, dass der Client die Antwort im Entwicklercode analysiert, um die untergeordneten Elemente des errors
-Knotens für die Verarbeitung von Formularvalidierungsfehlern abzurufen. Es ist unpraktisch, Entwicklercode zu schreiben, um die Datei zu analysieren. Das manuelle Parsen des JSON erfordert nach dem Aufruf von ReadFromJsonAsynceine Dictionary<string, List<string>>
Fehlermeldung. Im Idealfall sollte die Server-API nur die Überprüfungsfehler zurückgeben, wie im folgenden Beispiel gezeigt:
{
"Id": [ "The Id field is required." ],
"Classification": [ "The Classification field is required." ],
"IsValidatedDesign": [ "This form disallows unapproved ships." ],
"MaximumAccommodation": [ "Accommodation invalid (1-100000)." ]
}
Um die Antwort der Server-API so zu ändern, dass sie nur die Validierungsfehler zurückgibt, ändern Sie den Delegaten, der bei Aktionen aufgerufen wird, die mit ApiControllerAttribute in der Datei Program
annotiert sind. Geben Sie für den API-Endpunkt (/StarshipValidation
) ein BadRequestObjectResult mit ModelStateDictionary zurück. Behalten Sie für alle anderen API-Endpunkte das Standardverhalten bei, indem Sie das Objektergebnis mit einem neuen ValidationProblemDetails zurückgeben.
Fügen Sie den Microsoft.AspNetCore.Mvc-Namespace am Anfang der Datei Program
im Hauptprojekt der Blazor Web App hinzu:
using Microsoft.AspNetCore.Mvc;
Fügen Sie in der Datei Program
die folgende AddControllersWithViews-Erweiterungsmethode hinzu, oder aktualisieren Sie sie, und fügen Sie den folgenden Aufruf von ConfigureApiBehaviorOptions ein:
builder.Services.AddControllersWithViews()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
if (context.HttpContext.Request.Path == "/StarshipValidation")
{
return new BadRequestObjectResult(context.ModelState);
}
else
{
return new BadRequestObjectResult(
new ValidationProblemDetails(context.ModelState));
}
};
});
Wenn Sie dem Hauptprojekt des Blazor Web App zum ersten Mal Controller hinzufügen, ordnen Sie die Controller-Endpunkte zu, wenn Sie den vorangehenden Code platzieren, der die Dienste für die Controller registriert. Im folgenden Beispiel werden Standardcontrollerrouten verwendet:
app.MapDefaultControllerRoute();
Hinweis
Im obigen Beispiel werden Controllerdienste explizit registriert, indem AddControllersWithViews aufgerufen wird, um automatisch XSRF/CSRF-Angriffe (Cross-Site Request Forgery, websiteübergreifende Anforderungsfälschung) abzumildern. Wenn Sie nur AddControllers verwenden, wird der Fälschungsschutz nicht automatisch aktiviert.
Weitere Informationen zur Reaktion auf Fehler beim Controllerrouting und bei Überprüfungen finden Sie in den folgenden Ressourcen:
- Routing von Controller-Aktionen in ASP.NET Core
- Behandeln von Fehlern in ASP.NET Core-controllerbasierten Web-APIs
Fügen Sie im .Client
-Projekt die im Abschnitt "Validator-Komponenten" gezeigte CustomValidation
-Komponente hinzu. Aktualisieren Sie den Namespace so, dass er mit dem der App (z. B.namespace BlazorSample.Client
) übereinstimmt.
Im .Client
-Projekt wird das Starfleet Starship Database
-Formular aktualisiert, um Servervalidierungsfehler mithilfe der CustomValidation
-Komponente anzuzeigen. Wenn die Server-API Validierungsmeldungen zurückgibt, werden diese dem CustomValidation
der ValidationMessageStore-Komponente hinzugefügt. Die Fehler sind im EditContext des Formulars zur Anzeige durch die Validierungszusammenfassung des Formulars verfügbar.
Ändern Sie in der folgenden Komponente den Namespace des freigegebenen Projekts (@using BlazorSample.Shared
) in den Namespace des freigegebenen Projekts. Beachten Sie, dass das Formular eine Autorisierung erfordert, weshalb der Benutzer bei der App angemeldet sein muss, um zum Formular navigieren zu können.
Fügen Sie den Microsoft.AspNetCore.Mvc-Namespace am Anfang der Datei Program
in der Server -App hinzu:
using Microsoft.AspNetCore.Mvc;
Suchen Sie in der Datei Program
nach der Erweiterungsmethode AddControllersWithViews und fügen Sie den folgenden Aufruf zu ConfigureApiBehaviorOptions hinzu:
builder.Services.AddControllersWithViews()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
if (context.HttpContext.Request.Path == "/StarshipValidation")
{
return new BadRequestObjectResult(context.ModelState);
}
else
{
return new BadRequestObjectResult(
new ValidationProblemDetails(context.ModelState));
}
};
});
Hinweis
Im obigen Beispiel werden Controllerdienste explizit registriert, indem AddControllersWithViews aufgerufen wird, um automatisch XSRF/CSRF-Angriffe (Cross-Site Request Forgery, websiteübergreifende Anforderungsfälschung) abzumildern. Wenn Sie nur AddControllers verwenden, wird der Fälschungsschutz nicht automatisch aktiviert.
Fügen Sie im Client-Projekt die im Abschnitt Validator-Komponenten gezeigte CustomValidation
-Komponente hinzu. Aktualisieren Sie den Namespace so, dass er mit dem der App (z. B.namespace BlazorSample.Client
) übereinstimmt.
Im Client -Projekt wird das Starfleet Starship Database
-Formular aktualisiert, um Servervalidierungsfehler mithilfe der CustomValidation
-Komponente anzuzeigen. Wenn die Server-API Validierungsmeldungen zurückgibt, werden diese dem CustomValidation
der ValidationMessageStore-Komponente hinzugefügt. Die Fehler sind im EditContext des Formulars zur Anzeige durch die Validierungszusammenfassung des Formulars verfügbar.
Aktualisieren Sie in der folgenden Komponente den Namespace des Shared
-Projekts (@using BlazorSample.Shared
) auf den Namespace des gemeinsam genutzten Projekts. Beachten Sie, dass das Formular eine Autorisierung erfordert, weshalb der Benutzer bei der App angemeldet sein muss, um zum Formular navigieren zu können.
Starship10.razor
:
Hinweis
Formulare, die auf EditForm basieren, aktivieren automatisch den Schutz vor Fälschung. Der Controller sollte AddControllersWithViews zum Registrieren von Controllerdiensten verwenden und die Unterstützung für den Schutz vor Fälschung für die Web-API automatisch aktivieren.
@page "/starship-10"
@rendermode InteractiveWebAssembly
@using System.Net
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using BlazorSample.Shared
@attribute [Authorize]
@inject HttpClient Http
@inject ILogger<Starship10> Logger
<h1>Starfleet Starship Database</h1>
<h2>New Ship Entry Form</h2>
<EditForm FormName="Starship10" Model="Model" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<CustomValidation @ref="customValidation" />
<ValidationSummary />
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" disabled="@disabled" />
</label>
</div>
<div>
<label>
Description (optional):
<InputTextArea @bind-Value="Model!.Description"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Primary Classification:
<InputSelect @bind-Value="Model!.Classification" disabled="@disabled">
<option value="">Select classification ...</option>
<option value="Exploration">Exploration</option>
<option value="Diplomacy">Diplomacy</option>
<option value="Defense">Defense</option>
</InputSelect>
</label>
</div>
<div>
<label>
Maximum Accommodation:
<InputNumber @bind-Value="Model!.MaximumAccommodation"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Engineering Approval:
<InputCheckbox @bind-Value="Model!.IsValidatedDesign"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Production Date:
<InputDate @bind-Value="Model!.ProductionDate" disabled="@disabled" />
</label>
</div>
<div>
<button type="submit" disabled="@disabled">Submit</button>
</div>
<div style="@messageStyles">
@message
</div>
</EditForm>
@code {
private CustomValidation? customValidation;
private bool disabled;
private string? message;
private string messageStyles = "visibility:hidden";
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() =>
Model ??= new() { ProductionDate = DateTime.UtcNow };
private async Task Submit(EditContext editContext)
{
customValidation?.ClearErrors();
try
{
using var response = await Http.PostAsJsonAsync<Starship>(
"StarshipValidation", (Starship)editContext.Model);
var errors = await response.Content
.ReadFromJsonAsync<Dictionary<string, List<string>>>() ??
new Dictionary<string, List<string>>();
if (response.StatusCode == HttpStatusCode.BadRequest &&
errors.Any())
{
customValidation?.DisplayErrors(errors);
}
else if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException(
$"Validation failed. Status Code: {response.StatusCode}");
}
else
{
disabled = true;
messageStyles = "color:green";
message = "The form has been processed.";
}
}
catch (AccessTokenNotAvailableException ex)
{
ex.Redirect();
}
catch (Exception ex)
{
Logger.LogError("Form processing error: {Message}", ex.Message);
disabled = true;
messageStyles = "color:red";
message = "There was an error processing the form.";
}
}
}
Das .Client
-Projekt eines Blazor Web App muss auch ein HttpClient für HTTP POST-Anfragen an einen Backend-Web-API-Controller registrieren. Überprüfen Sie Folgendes in der Datei Program
des .Client
-Projekts, oder fügen Sie es hinzu:
builder.Services.AddScoped(sp =>
new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
Im vorherigen Beispiel wird die Basisadresse mit builder.HostEnvironment.BaseAddress
(IWebAssemblyHostEnvironment.BaseAddress) festgelegt, wodurch die Basisadresse für die App abgerufen und in der Regel vom <base>
-Wert des href
-Tags auf der Hostseite abgeleitet wird.
@page "/starship-10"
@using System.Net
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using BlazorSample.Shared
@attribute [Authorize]
@inject HttpClient Http
@inject ILogger<Starship10> Logger
<h1>Starfleet Starship Database</h1>
<h2>New Ship Entry Form</h2>
<EditForm Model="Model" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<CustomValidation @ref="customValidation" />
<ValidationSummary />
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" disabled="@disabled" />
</label>
</div>
<div>
<label>
Description (optional):
<InputTextArea @bind-Value="Model!.Description"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Primary Classification:
<InputSelect @bind-Value="Model!.Classification" disabled="@disabled">
<option value="">Select classification ...</option>
<option value="Exploration">Exploration</option>
<option value="Diplomacy">Diplomacy</option>
<option value="Defense">Defense</option>
</InputSelect>
</label>
</div>
<div>
<label>
Maximum Accommodation:
<InputNumber @bind-Value="Model!.MaximumAccommodation"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Engineering Approval:
<InputCheckbox @bind-Value="Model!.IsValidatedDesign"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Production Date:
<InputDate @bind-Value="Model!.ProductionDate" disabled="@disabled" />
</label>
</div>
<div>
<button type="submit" disabled="@disabled">Submit</button>
</div>
<div style="@messageStyles">
@message
</div>
</EditForm>
@code {
private CustomValidation? customValidation;
private bool disabled;
private string? message;
private string messageStyles = "visibility:hidden";
public Starship? Model { get; set; }
protected override void OnInitialized() =>
Model ??= new() { ProductionDate = DateTime.UtcNow };
private async Task Submit(EditContext editContext)
{
customValidation?.ClearErrors();
try
{
using var response = await Http.PostAsJsonAsync<Starship>(
"StarshipValidation", (Starship)editContext.Model);
var errors = await response.Content
.ReadFromJsonAsync<Dictionary<string, List<string>>>() ??
new Dictionary<string, List<string>>();
if (response.StatusCode == HttpStatusCode.BadRequest &&
errors.Any())
{
customValidation?.DisplayErrors(errors);
}
else if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException(
$"Validation failed. Status Code: {response.StatusCode}");
}
else
{
disabled = true;
messageStyles = "color:green";
message = "The form has been processed.";
}
}
catch (AccessTokenNotAvailableException ex)
{
ex.Redirect();
}
catch (Exception ex)
{
Logger.LogError("Form processing error: {Message}", ex.Message);
disabled = true;
messageStyles = "color:red";
message = "There was an error processing the form.";
}
}
}
Hinweis
Als Alternative zur Verwendung einer Validierungskomponente können Validierungsattribute von Datenanmerkungen verwendet werden. Benutzerdefinierte Attribute, die auf das Modell des Formulars angewendet werden, werden mit der Verwendung der DataAnnotationsValidator-Komponente aktiviert. Bei Verwendung mit Servervalidierung müssen die Attribute auf dem Server ausführbar sein. Weitere Informationen finden Sie im Abschnitt Benutzerdefinierte Validierungsattribute.
Hinweis
Der Servervalidierungsansatz in diesem Abschnitt eignet sich für jedes der Beispiele für gehostete Blazor WebAssembly-Lösungen in dieser Dokumentation:
InputText
basierend auf dem Eingabeereignis
Verwenden Sie die InputText-Komponente, um eine benutzerdefinierte Komponente zu erstellen, die das oninput
-Ereignis (input
) anstelle des onchange
-Ereignisses (change
) nutzt. Die Verwendung des input
-Ereignisses löst die Feldvalidierung bei jeder Tastatureingabe aus.
Die folgende CustomInputText
-Komponente erbt die InputText
-Komponente des Frameworks und legt die Ereignisbindung auf das oninput
-Ereignis (input
) fest.
CustomInputText.razor
:
@inherits InputText
<input @attributes="AdditionalAttributes"
class="@CssClass"
@bind="CurrentValueAsString"
@bind:event="oninput" />
Die CustomInputText
-Komponente kann überall dort verwendet werden, wo InputText verwendet wird. Die folgende Komponente verwendet die gemeinsam genutzte CustomInputText
-Komponente.
Starship11.razor
:
@page "/starship-11"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship11> Logger
<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship11">
<DataAnnotationsValidator />
<ValidationSummary />
<div>
<label>
Identifier:
<CustomInputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
<div>
CurrentValue: @Model?.Id
</div>
@code {
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void Submit() => Logger.LogInformation("Submit: Processing form");
public class Starship
{
[Required]
[StringLength(10, ErrorMessage = "Id is too long.")]
public string? Id { get; set; }
}
}
@page "/starship-11"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship11> Logger
<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship11">
<DataAnnotationsValidator />
<ValidationSummary />
<div>
<label>
Identifier:
<CustomInputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
<div>
CurrentValue: @Model?.Id
</div>
@code {
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void Submit() => Logger.LogInformation("Submit: Processing form");
public class Starship
{
[Required]
[StringLength(10, ErrorMessage = "Id is too long.")]
public string? Id { get; set; }
}
}
@page "/starship-11"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship11> Logger
<EditForm Model="Model" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<ValidationSummary />
<CustomInputText @bind-Value="Model!.Id" />
<button type="submit">Submit</button>
</EditForm>
<div>
CurrentValue: @Model?.Id
</div>
@code {
public Starship? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private void Submit()
{
Logger.LogInformation("Submit called: Processing the form");
}
public class Starship
{
[Required]
[StringLength(10, ErrorMessage = "Id is too long.")]
public string? Id { get; set; }
}
}
Komponenten der Validierungszusammenfassung und der Validierungsnachricht
Die ValidationSummary-Komponente fasst alle Validierungsnachrichten zusammen. Das ähnelt dem Taghilfsprogramm für Validierungszusammenfassungen:
<ValidationSummary />
Validierungsmeldungen für ein bestimmtes Modell werden mit dem Model
-Parameter ausgegeben:
<ValidationSummary Model="Model" />
Die ValidationMessage<TValue>-Komponente zeigt Validierungsnachrichten für ein bestimmtes Feld an. Das ähnelt dem Taghilfsprogramm für Validierungsmeldungen. Das Validierungsfeld wird mit dem For-Attribut und einem Lambdaausdruck angegeben, der die Modelleigenschaft benennt:
<ValidationMessage For="@(() => Model!.MaximumAccommodation)" />
Die ValidationMessage<TValue>- und ValidationSummary-Komponenten unterstützen arbiträre Attribute. Attribute, die nicht mit einem Komponentenparameter übereinstimmen, werden dem gerenderten <div>
- oder <ul>
-Element hinzugefügt.
Steuern Sie den Stil von Validierungsmeldungen im Stylesheet (wwwroot/css/app.css
oder wwwroot/css/site.css
) der App. Die validation-message
-Standardklasse legt die Textfarbe von Validierungsmeldungen auf Rot fest:
.validation-message {
color: red;
}
Ermitteln der Gültigkeit eines Formularfelds
Verwenden Sie EditContext.IsValid, um zu ermitteln, ob ein Feld gültig ist, ohne Validierungsmeldungen abzurufen.
wird unterstützt, aber nicht empfohlen:
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
empfohlen:
var isValid = editContext.IsValid(fieldIdentifier);
Benutzerdefinierte Validierungsattribute
Übergeben Sie die MemberName-Eigenschaft des Validierungskontexts bei der Erstellung der ValidationResult-Klasse, um sicherzustellen, dass ein Validierungsergebnis korrekt einem Feld zugeordnet wird, wenn ein benutzerdefiniertes Validierungsattribut verwendet wird.
CustomValidator.cs
:
using System;
using System.ComponentModel.DataAnnotations;
public class CustomValidator : ValidationAttribute
{
protected override ValidationResult IsValid(object? value,
ValidationContext validationContext)
{
...
return new ValidationResult("Validation message to user.",
[ validationContext.MemberName! ]);
}
}
using System;
using System.ComponentModel.DataAnnotations;
public class CustomValidator : ValidationAttribute
{
protected override ValidationResult IsValid(object? value,
ValidationContext validationContext)
{
...
return new ValidationResult("Validation message to user.",
new[] { validationContext.MemberName! });
}
}
using System;
using System.ComponentModel.DataAnnotations;
public class CustomValidator : ValidationAttribute
{
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
...
return new ValidationResult("Validation message to user.",
new[] { validationContext.MemberName });
}
}
Fügen Sie über ValidationContext Dienste in benutzerdefinierte Validierungsattribute ein. Das folgende Beispiel demonstriert ein SaladChef-Formular, das Benutzereingaben mit Abhängigkeitsinjektion (Dependency Injection, DI) validiert.
Die SaladChef
-Klasse gibt die genehmigte Zutatenliste für einen Ten Forward-Salat auf dem Sternenschiff an.
SaladChef.cs
:
namespace BlazorSample;
public class SaladChef
{
public string[] SaladToppers = { "Horva", "Kanda Root", "Krintar", "Plomeek",
"Syto Bean" };
}
Registrieren Sie SaladChef
im DI-Container der App in der Datei Program
:
builder.Services.AddTransient<SaladChef>();
Die IsValid
-Methode der folgenden SaladChefValidatorAttribute
-Klasse ruft den Dienst SaladChef
aus DI ab, um die Eingaben des Benutzers zu prüfen.
SaladChefValidatorAttribute.cs
:
using System.ComponentModel.DataAnnotations;
namespace BlazorSample;
public class SaladChefValidatorAttribute : ValidationAttribute
{
protected override ValidationResult? IsValid(object? value,
ValidationContext validationContext)
{
var saladChef = validationContext.GetRequiredService<SaladChef>();
if (saladChef.SaladToppers.Contains(value?.ToString()))
{
return ValidationResult.Success;
}
return new ValidationResult("Is that a Vulcan salad topper?! " +
"The following toppers are available for a Ten Forward salad: " +
string.Join(", ", saladChef.SaladToppers));
}
}
Die folgende Komponente validiert Benutzereingaben, indem sie das SaladChefValidatorAttribute
([SaladChefValidator]
) auf die Zeichenfolge für Salatzutaten (SaladIngredient
) anwendet.
Starship12.razor
:
@page "/starship-12"
@inject SaladChef SaladChef
<EditForm Model="this" autocomplete="off" FormName="Starship12">
<DataAnnotationsValidator />
<div>
<label>
Salad topper (@saladToppers):
<input @bind="SaladIngredient" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
<ul>
@foreach (var message in context.GetValidationMessages())
{
<li class="validation-message">@message</li>
}
</ul>
</EditForm>
@code {
private string? saladToppers;
[SaladChefValidator]
public string? SaladIngredient { get; set; }
protected override void OnInitialized() =>
saladToppers ??= string.Join(", ", SaladChef.SaladToppers);
}
@page "/starship-12"
@inject SaladChef SaladChef
<EditForm Model="this" autocomplete="off" FormName="Starship12">
<DataAnnotationsValidator />
<div>
<label>
Salad topper (@saladToppers):
<input @bind="SaladIngredient" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
<ul>
@foreach (var message in context.GetValidationMessages())
{
<li class="validation-message">@message</li>
}
</ul>
</EditForm>
@code {
private string? saladToppers;
[SaladChefValidator]
public string? SaladIngredient { get; set; }
protected override void OnInitialized() =>
saladToppers ??= string.Join(", ", SaladChef.SaladToppers);
}
@page "/starship-12"
@inject SaladChef SaladChef
<EditForm Model="this" autocomplete="off">
<DataAnnotationsValidator />
<p>
<label>
Salad topper (@saladToppers):
<input @bind="SaladIngredient" />
</label>
</p>
<button type="submit">Submit</button>
<ul>
@foreach (var message in context.GetValidationMessages())
{
<li class="validation-message">@message</li>
}
</ul>
</EditForm>
@code {
private string? saladToppers;
[SaladChefValidator]
public string? SaladIngredient { get; set; }
protected override void OnInitialized() =>
saladToppers ??= string.Join(", ", SaladChef.SaladToppers);
}
Benutzerdefinierte CSS-Klassenattribute für die Validierung
CSS-Klassenattribute für die benutzerdefinierte Validierung sind nützlich, wenn eine Integration in CSS-Frameworks wie Bootstrap erfolgt.
Um CSS-Klassenattribute für die benutzerdefinierte Validierung anzugeben, geben Sie zunächst CSS-Stile für die benutzerdefinierte Validierung an. Im folgenden Beispiel werden Stile für „gültig“ (validField
) und für „ungültig“ (invalidField
) angegeben.
Fügen Sie die folgenden CSS-Klassen zur Formatvorlage der App hinzu:
.validField {
border-color: lawngreen;
}
.invalidField {
background-color: tomato;
}
Erstellen Sie eine von FieldCssClassProvider abgeleitete Klasse, die auf Feldvalidierungsmeldungen prüft und den entsprechenden Stil für „gültig“ oder „ungültig“ anwendet.
CustomFieldClassProvider.cs
:
using Microsoft.AspNetCore.Components.Forms;
public class CustomFieldClassProvider : FieldCssClassProvider
{
public override string GetFieldCssClass(EditContext editContext,
in FieldIdentifier fieldIdentifier)
{
var isValid = editContext.IsValid(fieldIdentifier);
return isValid ? "validField" : "invalidField";
}
}
using Microsoft.AspNetCore.Components.Forms;
public class CustomFieldClassProvider : FieldCssClassProvider
{
public override string GetFieldCssClass(EditContext editContext,
in FieldIdentifier fieldIdentifier)
{
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
return isValid ? "validField" : "invalidField";
}
}
Legen Sie die CustomFieldClassProvider
-Klasse als CSS-Klassenanbieter für Felder auf der EditContext-Instanz des Formulars mit SetFieldCssClassProvider fest.
Starship13.razor
:
@page "/starship-13"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship13> Logger
<EditForm EditContext="editContext" OnValidSubmit="Submit" FormName="Starship13">
<DataAnnotationsValidator />
<ValidationSummary />
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
private EditContext? editContext;
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
editContext.SetFieldCssClassProvider(new CustomFieldClassProvider());
}
private void Submit() => Logger.LogInformation("Submit: Processing form");
public class Starship
{
[Required]
[StringLength(10, ErrorMessage = "Id is too long.")]
public string? Id { get; set; }
}
}
@page "/starship-13"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship13> Logger
<EditForm EditContext="editContext" OnValidSubmit="Submit" FormName="Starship13">
<DataAnnotationsValidator />
<ValidationSummary />
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
@code {
private EditContext? editContext;
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
editContext.SetFieldCssClassProvider(new CustomFieldClassProvider());
}
private void Submit() => Logger.LogInformation("Submit: Processing form");
public class Starship
{
[Required]
[StringLength(10, ErrorMessage = "Id is too long.")]
public string? Id { get; set; }
}
}
@page "/starship-13"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship13> Logger
<EditForm EditContext="editContext" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText @bind-Value="Model!.Id" />
<button type="submit">Submit</button>
</EditForm>
@code {
private EditContext? editContext;
public Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??= new();
editContext = new(Model);
editContext.SetFieldCssClassProvider(new CustomFieldClassProvider());
}
private void Submit()
{
Logger.LogInformation("Submit called: Processing the form");
}
public class Starship
{
[Required]
[StringLength(10, ErrorMessage = "Id is too long.")]
public string? Id { get; set; }
}
}
Im vorherigen Beispiel wird die Gültigkeit aller Formularfelder überprüft und auf jedes Feld ein Stil angewendet. Wenn das Formular benutzerdefinierte Stile nur auf eine Teilmenge der Felder anwenden soll, lassen Sie CustomFieldClassProvider
Stile bedingt anwenden. Im folgenden CustomFieldClassProvider2
-Beispiel wird ein Stil nur auf das Feld Name
angewendet. Für Felder, deren Namen nicht Name
entsprechen, wird string.Empty
zurückgegeben, und es wird kein Stil angewendet. Mithilfe der Reflexion wird das Feld mit der Eigenschaft oder dem Feldnamen des Modellelements abgeglichen, und nicht mit einer der HTML-Entität zugewiesenen id
.
CustomFieldClassProvider2.cs
:
using Microsoft.AspNetCore.Components.Forms;
public class CustomFieldClassProvider2 : FieldCssClassProvider
{
public override string GetFieldCssClass(EditContext editContext,
in FieldIdentifier fieldIdentifier)
{
if (fieldIdentifier.FieldName == "Name")
{
var isValid = editContext.IsValid(fieldIdentifier);
return isValid ? "validField" : "invalidField";
}
return string.Empty;
}
}
using Microsoft.AspNetCore.Components.Forms;
public class CustomFieldClassProvider2 : FieldCssClassProvider
{
public override string GetFieldCssClass(EditContext editContext,
in FieldIdentifier fieldIdentifier)
{
if (fieldIdentifier.FieldName == "Name")
{
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
return isValid ? "validField" : "invalidField";
}
return string.Empty;
}
}
Hinweis
Beim Abgleich des Feldnamens im vorherigen Beispiel wird die Groß-/Kleinschreibung beachtet, sodass ein Modelleigenschaftenmember, der als „Name
“ festgelegt ist, einer bedingten Überprüfung von „Name
“ entsprechen muss:
- Stimmt überein:
fieldId.FieldName == "Name"
- Stimmt nicht überein:
fieldId.FieldName == "name"
- Stimmt nicht überein:
fieldId.FieldName == "NAME"
- Stimmt nicht überein:
fieldId.FieldName == "nAmE"
Fügen Sie Model
eine zusätzliche Eigenschaft hinzu, z. B.:
[StringLength(10, ErrorMessage = "Description is too long.")]
public string? Description { get; set; }
Fügen Sie Description
dem Formular der CustomValidationForm
-Komponente hinzu.
<InputText @bind-Value="Model!.Description" />
Aktualisieren Sie die EditContext-Instanz in der OnInitialized
-Methode der Komponente, um den neuen CSS-Klassenanbieter für Felder zu verwenden:
editContext?.SetFieldCssClassProvider(new CustomFieldClassProvider2());
Da eine CSS-Validierungsklasse nicht auf das Feld Description
angewendet wird, wird sie nicht formatiert. Die Feldvalidierung wird jedoch normal ausgeführt. Wenn mehr als 10 Zeichen angegeben werden, gibt die Validierungszusammenfassung den Fehler an:
Die Beschreibung ist zu lang.
Im folgenden Beispiel:
Der benutzerdefinierte CSS-Stil wird auf das
Name
-Feld angewendet.Alle anderen Felder wenden eine Logik ähnlich der Standardlogik von Blazor an und verwenden die CSS-Validierungsstile des Standardfelds von Blazor mit
modified
,valid
oderinvalid
. Beachten Sie, dass Sie für die Standardstile diese nicht dem Stylesheet der App hinzufügen müssen, wenn die App auf einer Blazor-Projektvorlage basiert. Für Apps, die nicht auf einer Blazor-Projektvorlage basieren, können die Standardstile dem Stylesheet der App hinzugefügt werden:.valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; } .invalid { outline: 1px solid red; }
CustomFieldClassProvider3.cs
:
using Microsoft.AspNetCore.Components.Forms;
public class CustomFieldClassProvider3 : FieldCssClassProvider
{
public override string GetFieldCssClass(EditContext editContext,
in FieldIdentifier fieldIdentifier)
{
var isValid = editContext.IsValid(fieldIdentifier);
if (fieldIdentifier.FieldName == "Name")
{
return isValid ? "validField" : "invalidField";
}
else
{
if (editContext.IsModified(fieldIdentifier))
{
return isValid ? "modified valid" : "modified invalid";
}
else
{
return isValid ? "valid" : "invalid";
}
}
}
}
using Microsoft.AspNetCore.Components.Forms;
public class CustomFieldClassProvider3 : FieldCssClassProvider
{
public override string GetFieldCssClass(EditContext editContext,
in FieldIdentifier fieldIdentifier)
{
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
if (fieldIdentifier.FieldName == "Name")
{
return isValid ? "validField" : "invalidField";
}
else
{
if (editContext.IsModified(fieldIdentifier))
{
return isValid ? "modified valid" : "modified invalid";
}
else
{
return isValid ? "valid" : "invalid";
}
}
}
}
Aktualisieren Sie die EditContext-Instanz in der OnInitialized
-Methode der Komponente, um den vorherigen CSS-Klassenanbieter für Felder zu verwenden:
editContext.SetFieldCssClassProvider(new CustomFieldClassProvider3());
Verwenden von CustomFieldClassProvider3
:
- Das
Name
-Feld verwendet die benutzerdefinierten CSS-Validierungsstile der App. - Das
Description
-Feld verwendet Logik ähnlich der Logik von Blazor und die CSS-Validierungsstile des Standardfelds von Blazor.
Validierung auf Klassenebene mit IValidatableObject
Die Überprüfung auf Klassenebene mit IValidatableObject
(API-Dokumentation) wird für Blazor-Formularmodelle unterstützt. Die IValidatableObject-Überprüfung wird nur ausgeführt, wenn das Formular übermittelt wird und nur dann, wenn alle anderen Überprüfungen erfolgreich sind.
Blazor Validierungspaket für Datenanmerkungen
Microsoft.AspNetCore.Components.DataAnnotations.Validation
ist ein Paket, das Lücken bei der Validierung mithilfe der DataAnnotationsValidator-Komponente schließt. Das Paket ist aktuell experimentell.
Warnung
Das Paket Microsoft.AspNetCore.Components.DataAnnotations.Validation
enthält die neueste Version des Release Candidate auf NuGet.org. Verwenden Sie bis auf Weiteres das experimentelle Release Candidate-Paket. Experimentelle Features werden für die Untersuchung der Funktionsfähigkeit von Features bereitgestellt und dürfen nicht in einer stabilen Version enthalten sein. Weitere Aktualisierungen finden Sie im GitHub-Repository „Ankündigungen“, im dotnet/aspnetcore
Repository von GitHub oder in diesem Themenabschnitt.
[CompareProperty]
-Attribut
Das CompareAttribute funktioniert nicht gut mit der DataAnnotationsValidator-Komponente, weil das DataAnnotationsValidator das Validierungsergebnis nicht mit einem bestimmten Mitglied verknüpft. Das kann zu einem inkonsistenten Verhalten zwischen der Validierung auf Feldebene und der Validierung des gesamten Modells bei der Einreichung führen. Das Microsoft.AspNetCore.Components.DataAnnotations.Validation
experimentelle Paket führt ein zusätzliches Validierungsattribut, ComparePropertyAttribute
, ein, das diese Einschränkungen umgeht. In einer Blazor Anwendung ist [CompareProperty]
ein direkter Ersatz für das [Compare]
Attribut.
Verschachtelte Modelle, Sammlungstypen und komplexe Typen
Blazor bietet Unterstützung für die Validierung von Formulareingaben mithilfe von Datenanmerkungen mit dem integrierten DataAnnotationsValidator. DataAnnotationsValidator validiert jedoch nur Eigenschaften des Modells auf oberster Ebene, die an das Formular gebunden sind, bei denen es sich aber um keine Sammlungs- oder komplexen Eigenschaften handelt.
Um den gesamten Objektgraphen des gebundenen Modells zu überprüfen, einschließlich der Eigenschaften vom Typ Sammlung und Komplex, verwenden Sie das ObjectGraphDataAnnotationsValidator
, das vom Paket experimentalMicrosoft.AspNetCore.Components.DataAnnotations.Validation
bereitgestellt wird:
<EditForm ...>
<ObjectGraphDataAnnotationsValidator />
...
</EditForm>
Annotieren Sie Modelleigenschaften mit [ValidateComplexType]
. In den folgenden Modellklassen enthält die ShipDescription
-Klasse zusätzliche Datenanmerkungen für die Validierung, wenn das Modell an das Formular gebunden ist:
Starship.cs
:
using System;
using System.ComponentModel.DataAnnotations;
public class Starship
{
...
[ValidateComplexType]
public ShipDescription ShipDescription { get; set; } = new();
...
}
ShipDescription.cs
:
using System;
using System.ComponentModel.DataAnnotations;
public class ShipDescription
{
[Required]
[StringLength(40, ErrorMessage = "Description too long (40 char).")]
public string? ShortDescription { get; set; }
[Required]
[StringLength(240, ErrorMessage = "Description too long (240 char).")]
public string? LongDescription { get; set; }
}
Aktivieren der Schaltfläche zum Senden basierend auf der Formularvalidierung
Um die Senden-Schaltfläche basierend auf der Formularvalidierung zu aktivieren oder zu deaktivieren, verwenden Sie das folgende Beispiel:
- Verwendet eine gekürzte Version des obigen
Starfleet Starship Database
-Formulars (Starship3
-Komponente) aus dem Abschnitt Beispielformular im Artikel Eingabekomponenten, der nur einen Wert für die ID des Raumfahrzeugs akzeptiert. Die anderenStarship
-Eigenschaften erhalten gültige Standardwerte, wenn eine Instanz desStarship
-Typs erstellt wird. - Es verwendet den EditContext des Formulars, um das Modell zuzuweisen, wenn die Komponente initialisiert wird.
- Es validiert das Formular im OnFieldChanged-Rückruf des Kontexts, um die Schaltfläche zum Senden zu aktivieren oder zu deaktivieren.
- Implementiert IDisposable und beendet das Abonnement des Ereignishandlers in der
Dispose
-Methode. Weitere Informationen finden Sie unter ASP.NET Core Razor Komponentenentsorgung.
Hinweis
Weisen Sie bei der Zuweisung zu EditForm.EditContext nicht auch EditForm.Model dem EditForm zu.
Starship14.razor
:
@page "/starship-14"
@implements IDisposable
@inject ILogger<Starship14> Logger
<EditForm EditContext="editContext" OnValidSubmit="Submit" FormName="Starship14">
<DataAnnotationsValidator />
<ValidationSummary />
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit" disabled="@formInvalid">Submit</button>
</div>
</EditForm>
@code {
private bool formInvalid = false;
private EditContext? editContext;
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??=
new()
{
Id = "NCC-1701",
Classification = "Exploration",
MaximumAccommodation = 150,
IsValidatedDesign = true,
ProductionDate = new DateTime(2245, 4, 11)
};
editContext = new(Model);
editContext.OnFieldChanged += HandleFieldChanged;
}
private void HandleFieldChanged(object? sender, FieldChangedEventArgs e)
{
if (editContext is not null)
{
formInvalid = !editContext.Validate();
StateHasChanged();
}
}
private void Submit() => Logger.LogInformation("Submit: Processing form");
public void Dispose()
{
if (editContext is not null)
{
editContext.OnFieldChanged -= HandleFieldChanged;
}
}
}
@page "/starship-14"
@implements IDisposable
@inject ILogger<Starship14> Logger
<EditForm EditContext="editContext" OnValidSubmit="Submit" FormName="Starship14">
<DataAnnotationsValidator />
<ValidationSummary />
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit" disabled="@formInvalid">Submit</button>
</div>
</EditForm>
@code {
private bool formInvalid = false;
private EditContext? editContext;
[SupplyParameterFromForm]
private Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??=
new()
{
Id = "NCC-1701",
Classification = "Exploration",
MaximumAccommodation = 150,
IsValidatedDesign = true,
ProductionDate = new DateTime(2245, 4, 11)
};
editContext = new(Model);
editContext.OnFieldChanged += HandleFieldChanged;
}
private void HandleFieldChanged(object? sender, FieldChangedEventArgs e)
{
if (editContext is not null)
{
formInvalid = !editContext.Validate();
StateHasChanged();
}
}
private void Submit() => Logger.LogInformation("Submit: Processing form");
public void Dispose()
{
if (editContext is not null)
{
editContext.OnFieldChanged -= HandleFieldChanged;
}
}
}
@page "/starship-14"
@implements IDisposable
@inject ILogger<Starship14> Logger
<EditForm EditContext="editContext" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<ValidationSummary />
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" />
</label>
</div>
<div>
<button type="submit" disabled="@formInvalid">Submit</button>
</div>
</EditForm>
@code {
private bool formInvalid = false;
private EditContext? editContext;
private Starship? Model { get; set; }
protected override void OnInitialized()
{
Model ??=
new()
{
Id = "NCC-1701",
Classification = "Exploration",
MaximumAccommodation = 150,
IsValidatedDesign = true,
ProductionDate = new DateTime(2245, 4, 11)
};
editContext = new(Model);
editContext.OnFieldChanged += HandleFieldChanged;
}
private void HandleFieldChanged(object? sender, FieldChangedEventArgs e)
{
if (editContext is not null)
{
formInvalid = !editContext.Validate();
StateHasChanged();
}
}
private void Submit()
{
Logger.LogInformation("Submit called: Processing the form");
}
public void Dispose()
{
if (editContext is not null)
{
editContext.OnFieldChanged -= HandleFieldChanged;
}
}
}
Wenn ein Formular nicht mit gültigen Werten vorab geladen wird und Sie die Schaltfläche Submit
beim Laden des Formulars deaktivieren möchten, legen Sie formInvalid
auf true
fest.
Eine Nebenwirkung des vorangehenden Ansatzes ist, dass eine Validierungszusammenfassung (ValidationSummary-Komponente) mit ungültigen Feldern aufgefüllt wird, nachdem der Benutzer mit einem beliebigen Feld interagiert hat. Behandeln Sie dieses Szenario auf eine der folgenden Arten:
- Verwenden Sie keine ValidationSummary-Komponente des Formulars.
- Lassen Sie die ValidationSummary-Komponente einblenden, wenn auf die Schaltfläche zum Senden geklickt wird, z. B. in einer
Submit
-Methode.
<EditForm ... EditContext="editContext" OnValidSubmit="Submit" ...>
<DataAnnotationsValidator />
<ValidationSummary style="@displaySummary" />
...
<button type="submit" disabled="@formInvalid">Submit</button>
</EditForm>
@code {
private string displaySummary = "display:none";
...
private void Submit()
{
displaySummary = "display:block";
}
}