Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.
Varování
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Viz verzi .NET 9 tohoto článku pro aktuální vydání.
Tento článek vysvětluje, jak používat ověřování ve Blazor formulářích.
Ověření formuláře
Ve scénářích základního ověřování formulářů může instance použít deklarované instance EditForm a EditContext k ověření polí formuláře. Obslužná rutina pro událost OnValidationRequestedEditContext provádí vlastní logiku ověřování. Výsledek obslužné rutiny aktualizuje ValidationMessageStore instanci.
Základní ověření formuláře je užitečné v případech, kdy je model formuláře definován v rámci komponenty hostující formulář, a to buď jako členy přímo na komponentě, nebo v podtřídě. Použití komponenty validátoru se doporučuje, když se používá nezávislá třída modelu napříč několika komponentami.
Ověření Blazor Web Appna straně klienta vyžaduje aktivní BlazorSignalR okruh. Ověřování na straně klienta není k dispozici pro formuláře v součástech, které přijaly statické vykreslování na straně serveru (statické SSR). Formuláře, které používají statické SSR, jsou po odeslání validovány na serveru.
V následující komponentě HandleValidationRequested metoda obslužné rutiny vymaže všechny existující ověřovací zprávy voláním ValidationMessageStore.Clear před ověřením formuláře.
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;
}
}
}
Komponenta validátoru datových poznámek a vlastní ověření
Prvek DataAnnotationsValidator připojí ověření datových poznámek k prvku EditContext v kaskádě. Povolení ověření datových poznámek vyžaduje komponentu DataAnnotationsValidator . Pokud chcete použít jiný systém ověřování než datové poznámky, použijte místo komponenty vlastní implementaci DataAnnotationsValidator . Implementace architektury pro DataAnnotationsValidator jsou k dispozici pro kontrolu v referenčním zdroji:
Podrobnosti o chování ověřování najdete v DataAnnotationsValidator části chování ověřování .
Pokud potřebujete povolit podporu ověřování datových poznámek pro EditContext v kódu, zavolejte EnableDataAnnotationsValidation vloženým IServiceProvider (@inject IServiceProvider ServiceProvider) na EditContext. Pokročilý příklad naleznete v komponentě NotifyPropertyChangedValidationComponent v rámci ASP.NET Core Blazor ve složce BasicTestApp (úložiště GitHubdotnet/aspnetcore). V produkční verzi příkladu nahraďte argument new TestServiceProvider() pro poskytovatele služeb vloženým IServiceProvider.
Poznámka:
Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Blazor provádí dva typy ověřování:
- Ověření pole se provádí, když uživatel přepne pomocí tabulátoru z pole. Během ověřování pole komponenta DataAnnotationsValidator přidruží všechny ohlášené výsledky ověření k poli.
- Ověření modelu se provede, když uživatel odešle formulář. Během ověřování DataAnnotationsValidator modelu se komponenta pokusí určit pole na základě názvu člena, který hlásí výsledky ověření. Výsledky ověření, které nejsou přidružené k jednotlivým členům, jsou přidružené k modelu, nikoli k poli.
Ve vlastních scénářích ověřování:
- Ověření spravuje ValidationMessageStore pro EditContextformuláře .
- Komponenta DataAnnotationsValidator slouží k připojení podpory ověřování k formulářům na základě atributů ověřování (datových poznámek).
Existují dva obecné přístupy k dosažení vlastního ověřování, které jsou popsány v následujících dvou částech tohoto článku:
-
OnValidationRequestedudálosti : Ručně ověřte pole formuláře pomocí ověření datových poznámek a vlastního kódu pro kontroly polí při vyžádání ověření prostřednictvím obslužné rutiny události přiřazené k události OnValidationRequested. - komponenty validátoru: Jednu nebo více vlastních součástí validátoru lze použít ke zpracování ověřování pro různé formuláře na stejné stránce nebo ve stejném formuláři v různých krocích zpracování formuláře (například ověření klienta následované ověřením serveru).
Ruční ověření pomocí události OnValidationRequested
Formulář můžete ručně ověřit pomocí vlastní obslužné rutiny události přiřazené k události EditContext.OnValidationRequested pro správu ValidationMessageStore.
Architektura Blazor poskytuje komponentu DataAnnotationsValidator pro připojení další podpory ověřování k formulářům na základě ověřovacích atributů (datových poznámek).
Připomeňme si předchozí příklad komponenty Starship8, HandleValidationRequested metoda je přiřazena k OnValidationRequested, kde můžete provést ruční ověření v kódu jazyka C#. Několik změn ukazuje kombinování existujícího ručního ověřování s ověřením datových poznámek prostřednictvím DataAnnotationsValidator a atributu ověření použitého u modelu Holodeck.
Odkaz na obor názvů System.ComponentModel.DataAnnotations v direktivách Razor komponenty v horní části definičního souboru komponenty:
@using System.ComponentModel.DataAnnotations
Přidejte do modelu Id vlastnost Holodeck s ověřovacím atributem, který omezí délku řetězce na šest znaků:
[StringLength(6)]
public string? Id { get; set; }
Do formuláře přidejte komponentu DataAnnotationsValidator (<DataAnnotationsValidator />). Komponenta se obvykle umístí okamžitě pod značku <EditForm>, ale můžete ji umístit kdekoli ve formuláři:
<DataAnnotationsValidator />
Změňte chování odesílání formuláře ve značce <EditForm> z OnSubmit na OnValidSubmit, což zajistí, že formulář bude platný před tím, než se spustí přiřazená metoda obslužné rutiny události.
- OnSubmit="Submit"
+ OnValidSubmit="Submit"
Do <EditForm>přidejte pole pro vlastnost Id:
<div>
<label>
<InputText @bind-Value="Model!.Id" />
ID (6 characters max)
</label>
<ValidationMessage For="() => Model!.Id" />
</div>
Po provedení předchozích změn odpovídá chování formuláře následující specifikaci:
- Ověření datových poznámek ve vlastnosti
Idneaktivuje chybu ověření, když poleIdpouze ztratí fokus. Ověření se spustí, když uživatel vybere tlačítkoUpdate. - Jakékoli ruční ověření, které chcete provést v metodě
HandleValidationRequestedpřiřazené k události OnValidationRequested formuláře, se spustí, když uživatel vybere tlačítkoUpdateformuláře. V existujícím kódu příkladu komponentyStarship8musí uživatel vybrat buď nebo obě zaškrtávací políčka, aby formulář ověřil. - Formulář nezpracuje metodu
Submit, dokud neproběhnou datové poznámky i ruční ověření.
Komponenty validátoru
Komponenty validátoru podporují ověřování formuláře správou ValidationMessageStore pro formulářEditContext.
Architektura Blazor poskytuje komponentu DataAnnotationsValidator pro připojení podpory ověřování k formulářům na základě ověřovacích atributů (datových poznámek). Můžete vytvořit vlastní komponenty validátoru pro zpracování ověřovacích zpráv pro různé formuláře na stejné stránce nebo ve stejném formuláři v různých krocích zpracování formulářů (například ověření klienta následované ověřením serveru). Příklad komponenty validátoru uvedený v této části , CustomValidationse používá v následujících částech tohoto článku:
Z předdefinovaných validátorů datových poznámek není podporován [Remote]validátor atributu pouze Blazor.
Poznámka:
Vlastní atributy ověření datových poznámek lze v mnoha případech použít místo vlastních komponent validátoru. Vlastní atributy použité u modelu formuláře se aktivují pomocí DataAnnotationsValidator komponenty. Při použití s ověřením serveru musí být všechny vlastní atributy použité na modelu spustitelné na serveru. Další informace najdete v části Vlastní ověřovací atributy .
Vytvoření komponenty validátoru z ComponentBase:
- EditContext Formulář je kaskádový parametr komponenty.
- Při inicializaci komponenty validátoru se vytvoří nový ValidationMessageStore , aby se zachoval aktuální seznam chyb formuláře.
- Úložiště zpráv obdrží chyby, když kód vývojáře ve formuláři komponenty volá metodu
DisplayErrors. Chyby jsou předány metoděDisplayErrorsvDictionary<string, List<string>>. Ve slovníku je klíčem název pole formuláře, které obsahuje jednu nebo více chyb. Hodnota je seznam chyb. - Zprávy jsou vymazány, pokud došlo k některé z následujících:
- Ověření je požadováno na EditContext, když je vyvolána událost OnValidationRequested. Všechny chyby jsou vymazány.
- Pole se změní ve formuláři při vyvolání OnFieldChanged události. Vymažou se pouze chyby pole.
- Metoda
ClearErrorsje volána kódem vývojáře. Všechny chyby jsou vymazány.
Aktualizujte obor názvů v následující třídě tak, aby odpovídal oboru názvů vaší aplikace.
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();
}
}
Důležité
Určení oboru názvů je vyžadováno při odvození z ComponentBase. Nezadání oboru názvů způsobí chybu při sestavování:
Tag helpers cannot target tag name '<global namespace>.{CLASS NAME}' because it contains a ' ' character.
Zástupný {CLASS NAME} symbol je název třídy komponenty. Příklad vlastního validátoru v této části specifikuje ukázkový obor názvů BlazorSample.
Poznámka:
Anonymní lambda výrazy jsou v předchozím příkladu registrovanými obslužnými rutinami událostí pro OnValidationRequested a OnFieldChanged. V tomto scénáři není nutné implementovat IDisposable a odhlásit delegáty událostí. Další informace najdete v tématu odstranění komponenty ASP.NET Core Razor.
Ověřování obchodní logiky pomocí komponenty validátoru
Pro obecné ověření obchodní logiky použijte komponentu validátoru, která přijímá chyby formuláře ve slovníku.
Základní ověřování je užitečné v případech, kdy je model formuláře definován v rámci komponenty hostující formulář, a to buď jako členy přímo na komponentě, nebo v podtřídě. Použití komponenty validátoru se doporučuje, když se používá nezávislá třída modelu napříč několika komponentami.
V následujícím příkladu:
- Je použita zkrácená verze formuláře
Starfleet Starship Database(komponentyStarship3) části Příklad formuláře sekce Vstupní komponenty článku, která přijímá pouze klasifikaci a popis hvězdné lodi. Ověření datových poznámek se při odesílání formuláře neaktivuje, protože DataAnnotationsValidator součást není součástí formuláře. - Používá se komponenta
CustomValidationz části Součásti validátoru tohoto článku. - Ověření vyžaduje hodnotu pro popis lodi (
Description), pokud uživatel vybereDefenseklasifikaci lodi (Classification).
Když jsou v komponentě nastavené zprávy validace, přidají se do validátoru ValidationMessageStore a zobrazí se v souhrnu validace EditForm.
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");
}
}
}
Poznámka:
Jako alternativu k použití ověřovacích komponent je možné použít atributy ověření datových poznámek. Vlastní atributy použité u modelu formuláře se aktivují pomocí DataAnnotationsValidator komponenty. Při použití s ověřením serveru musí být atributy spustitelné na serveru. Další informace najdete v části Vlastní ověřovací atributy .
Ověření serveru pomocí komponenty validátoru
Tato část se zaměřuje na Blazor Web App scénáře, ale přístup pro jakýkoli typ aplikace, který používá ověřování serveru s webovým rozhraním API, používá stejný obecný přístup.
Tato část se zaměřuje na hostované Blazor WebAssembly scénáře, ale přístup pro jakýkoli typ aplikace, který používá ověřování serveru s webovým rozhraním API, využívá stejný obecný přístup.
Ověření serveru je podporováno kromě ověření klienta:
- Proveďte validaci klienta ve formuláři s komponentou DataAnnotationsValidator.
- Když je volána funkce validace klienta (OnValidSubmit), odešlete EditContext.Model do API back-endového serveru pro zpracování formuláře.
- Ověření modelu procesu na serveru
- Rozhraní API serveru zahrnuje ověřování integrovaných datových poznámek architektury i vlastní logiku ověřování, kterou poskytl vývojář. Pokud ověření proběhne na serveru, zpracujte formulář a odešlete zpět stavový kód úspěchu (
200 - OK). Pokud ověření selže, vraťte stavový kód chyby (400 - Bad Request) a chyby ověření pole. - Buď zakažte formulář při úspěchu, nebo zobrazte chyby.
Základní ověřování je užitečné v případech, kdy je model formuláře definován v rámci komponenty hostující formulář, a to buď jako členy přímo na komponentě, nebo v podtřídě. Použití komponenty validátoru se doporučuje, když se používá nezávislá třída modelu napříč několika komponentami.
Následující příklad je založen na:
- Komponenta Blazor Web App s interaktivními prvky WebAssembly vytvořená z projektové šablony Blazor Web App.
- Model
Starship(Starship.cs) sekce Příklad formuláře článku Vstupní komponenty. - Komponenta zobrazená
CustomValidationv části Komponenty validátoru.
Starship Umístěte model (Starship.cs) do projektu knihovny sdílených tříd, aby ho mohly používat projekty klienta i serveru. Přidejte nebo aktualizujte obor názvů tak, aby odpovídal oboru názvů sdílené aplikace (například namespace BlazorSample.Shared). Vzhledem k tomu, že model vyžaduje datové poznámky, ověřte, že knihovna sdílených tříd používá sdílenou architekturu System.ComponentModel.Annotations nebo přidá balíček do sdíleného projektu.
Poznámka:
Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.
V hlavním projektu Blazor Web App přidejte kontroler pro zpracování žádostí o validaci vesmírné lodi a vrácení zpráv o neúspěšné validaci. Aktualizujte obory názvů v posledním using příkazu pro projekt knihovny sdílených tříd a namespace třídu kontroleru. Kromě ověření poznámek k datům klienta a serveru kontroler ověří, že je pro popis lodi zadaná hodnota (Description), pokud uživatel vybere Defense klasifikaci (Classification).
- Hostované Blazor WebAssemblyřešení vytvořené zeBlazor WebAssemblyšablony projektu Tento přístup se podporuje pro všechna zabezpečená hostovaná Blazor řešení popsaná v hostované Blazor WebAssembly dokumentaci zabezpečení.
- Model
Starship(Starship.cs) sekce Příklad formuláře článku Vstupní komponenty. - Komponenta zobrazená
CustomValidationv části Komponenty validátoru.
Starship Umístěte model (Starship.cs) do projektu řešení Shared tak, aby ho mohly používat jak klientské, tak serverové aplikace. Přidejte nebo aktualizujte obor názvů tak, aby odpovídal oboru názvů sdílené aplikace (například namespace BlazorSample.Shared). Vzhledem k tomu, že model vyžaduje datové poznámky, přidejte System.ComponentModel.Annotations balíček do Shared projektu.
Poznámka:
Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.
Server V projektu přidejte kontroler pro zpracování žádostí o ověření hvězdicové lodi a vrácení neúspěšných ověřovacích zpráv. Aktualizujte obory názvů v posledním using příkazu pro projekt Shared a pro třídu kontroleru namespace. Kromě ověření poznámek k datům klienta a serveru kontroler ověří, že je pro popis lodi zadaná hodnota (Description), pokud uživatel vybere Defense klasifikaci (Classification).
Ověření klasifikace lodě Defense probíhá pouze na serveru v řadiči, protože nadcházející formulář neprovádí stejné ověření na straně klienta při odeslání formuláře na server. Ověřování serveru bez ověření klienta je běžné v aplikacích, které vyžadují ověřování uživatelských vstupů na serveru pomocí privátní obchodní logiky. Například soukromé informace z dat uložených pro uživatele můžou být nutné k ověření vstupu uživatele. Privátní data se samozřejmě nedají odeslat klientovi pro ověření klienta.
Poznámka:
Kontroler StarshipValidation v této části používá Microsoft Identity 2.0. Webové rozhraní API přijímá pouze tokeny pro uživatele, kteří mají pro toto rozhraní API obor "API.Access". Pokud se název oboru rozhraní API liší od API.Accessnázvu rozhraní API, vyžaduje se další přizpůsobení.
Další informace o zabezpečení najdete tady:
- ASP.NET Core autentizace a autorizace (a další články v uzlu Zabezpečení)
- dokumentaci platformy Microsoft Identity
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);
}
}
Potvrďte nebo aktualizujte obor názvů předchozího kontroleru (BlazorSample.Server.Controllers) tak, aby odpovídal oboru názvů kontrolerů aplikace.
Pokud na serveru dojde k chybě ověření vazby modelu, ApiController (ApiControllerAttribute) obvykle vrátí výchozí chybnou odpověď se špatnou žádostí a ValidationProblemDetails. Odpověď obsahuje více dat než jen chyby ověření, jak je znázorněno v následujícím příkladu, když se neodesílají všechna pole Starfleet Starship Database formuláře a formulář selže s ověřením:
{
"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)." ]
}
}
Poznámka:
Pokud chcete předvést předchozí odpověď JSON, musíte buď zakázat ověření klienta formuláře, aby bylo možné odeslat prázdný formulář pole, nebo použít nástroj k odeslání požadavku přímo na serverové rozhraní API, jako je například Firefox Browser Developer.
Pokud serverové rozhraní API vrátí předchozí výchozí odpověď JSON, může klient analyzovat odpověď v kódu aplikace, aby získal potomky uzlu errors pro zpracování chyb při ověřování formulářů. Není vhodné napsat kód vývojáře, který soubor parsuje. Ruční analýza JSON vyžaduje vytvoření seznamu chyb po volání Dictionary<string, List<string>>. V ideálním případě by serverové rozhraní API mělo vrátit pouze chyby ověření, jak ukazuje následující příklad:
{
"Id": [ "The Id field is required." ],
"Classification": [ "The Classification field is required." ],
"IsValidatedDesign": [ "This form disallows unapproved ships." ],
"MaximumAccommodation": [ "Accommodation invalid (1-100000)." ]
}
Pokud chcete upravit odpověď rozhraní API serveru tak, aby vracela pouze chyby ověření, změňte delegáta, který je vyvolán u akcí anotovaných pomocí ApiControllerAttribute v souboru Program. Pro koncový bod rozhraní API (/StarshipValidation) vraťte BadRequestObjectResult s ModelStateDictionary. Pro všechny ostatní koncové body rozhraní API zachovejte výchozí chování vrácením výsledku objektu s novým ValidationProblemDetails.
Přidejte obor názvů Microsoft.AspNetCore.Mvc na začátek souboru Program v hlavním projektu Blazor Web App:
using Microsoft.AspNetCore.Mvc;
Program Do souboru přidejte nebo aktualizujte následující rozšiřující AddControllersWithViews metodu a přidejte následující volání ConfigureApiBehaviorOptions:
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));
}
};
});
Pokud poprvé přidáváte kontrolery do hlavního projektu Blazor Web App, namapujte koncové body kontroleru při vložení předchozího kódu, který registruje služby pro kontrolery. Následující příklad používá výchozí trasy kontroleru:
app.MapDefaultControllerRoute();
Poznámka:
Předchozí příklad explicitně registruje služby kontroleru tím, že volá AddControllersWithViews pro automatické zmírnění útoků XSRF/CSRF (Cross-Site Request Forgery). Pokud použijete pouze AddControllers, antiforgery se neaktivuje automaticky.
Další informace o chybových odpovědích při selhání směrování a ověřování řadiče najdete v následujících zdrojích:
.Client V projektu přidejte komponentu CustomValidation zobrazenou v části Součásti validátoru. Aktualizujte obor názvů namespace BlazorSample.Client, aby odpovídal aplikaci (například).
V projektu .Client je formulář Starfleet Starship Database aktualizován tak, aby zobrazoval chyby ověření serveru pomocí komponenty CustomValidation. Když rozhraní API serveru vrátí ověřovací zprávy, přidají se do CustomValidation komponenty ValidationMessageStore. Chyby jsou k dispozici ve formuláři EditContext pro zobrazení souhrnem ověření formuláře.
V následující komponentě aktualizujte obor názvů sdíleného projektu (@using BlazorSample.Shared) na obor názvů sdíleného projektu. Všimněte si, že formulář vyžaduje autorizaci, takže uživatel musí být přihlášený k aplikaci, aby se k formuláři dostal.
Microsoft.AspNetCore.Mvc Přidejte obor názvů na začátek Program souboru v Server aplikaci:
using Microsoft.AspNetCore.Mvc;
V souboru Program vyhledejte metodu rozšíření AddControllersWithViews a přidejte následující volání do ConfigureApiBehaviorOptions.
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));
}
};
});
Poznámka:
Předchozí příklad explicitně registruje služby kontroleru tím, že volá AddControllersWithViews pro automatické zmírnění útoků XSRF/CSRF (Cross-Site Request Forgery). Pokud použijete pouze AddControllers, antiforgery se neaktivuje automaticky.
Client V projektu přidejte komponentu CustomValidation zobrazenou v části Součásti validátoru. Aktualizujte obor názvů namespace BlazorSample.Client, aby odpovídal aplikaci (například).
V projektu Client je formulář Starfleet Starship Database aktualizován tak, aby zobrazoval chyby ověření serveru pomocí komponenty CustomValidation. Když rozhraní API serveru vrátí ověřovací zprávy, přidají se do CustomValidation komponenty ValidationMessageStore. Chyby jsou k dispozici ve formuláři EditContext pro zobrazení souhrnem ověření formuláře.
V následující komponentě aktualizujte obor názvů Shared projektu (@using BlazorSample.Shared) na obor názvů sdíleného projektu. Všimněte si, že formulář vyžaduje autorizaci, takže uživatel musí být přihlášený k aplikaci, aby se k formuláři dostal.
Starship10.razor:
Poznámka:
Formuláře založené na EditForm automaticky povolují podporu proti padělání. Kontroler by měl používat AddControllersWithViews k registraci služeb kontroleru a automaticky povolit podporu antiforgery pro webové rozhraní API.
@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.";
}
}
}
Projekt .ClientBlazor Web App musí také zaregistrovat HttpClient pro požadavky HTTP POST na kontroler back-endového webového rozhraní API. Potvrďte nebo přidejte do .Client souboru projektu Program následující:
builder.Services.AddScoped(sp =>
new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
Předchozí příklad nastaví základní adresu s builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), která získává základní adresu pro aplikaci a je obvykle odvozena z hodnoty tagu <base> na hostitelské stránce.
@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.";
}
}
}
Poznámka:
Jako alternativu k použití ověřovací komponenty lze použít atributy ověření datových poznámek. Vlastní atributy použité u modelu formuláře se aktivují pomocí DataAnnotationsValidator komponenty. Při použití s ověřením serveru musí být atributy spustitelné na serveru. Další informace najdete v části Vlastní ověřovací atributy .
Poznámka:
Přístup k ověření serveru v této části je vhodný pro některý z příkladů hostovaného Blazor WebAssembly řešení v této sadě dokumentace:
InputText na základě vstupní události
Použijte komponentu InputText k vytvoření vlastní komponenty, která používá událost oninput (input) místo události onchange (change). Použití události input aktivuje ověření pole při každém stisknutí klávesy.
Následující CustomInputText komponenta dědí komponentu architektury InputText a nastaví vazbu událostí na oninput událost (input).
CustomInputText.razor:
@inherits InputText
<input @attributes="AdditionalAttributes"
class="@CssClass"
@bind="CurrentValueAsString"
@bind:event="oninput" />
Komponentu CustomInputText lze použít kdekoli InputText. Následující komponenta používá sdílenou CustomInputText komponentu.
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; }
}
}
Komponenty souhrnu ověření a ověřovací zprávy
Komponenta ValidationSummary shrnuje všechny ověřovací zprávy podobně jako pomocná rutina Validation Summary Tag Helper:
<ValidationSummary />
Výstupní ověřovací zprávy pro konkrétní model s parametrem Model :
<ValidationSummary Model="Model" />
Komponenta ValidationMessage<TValue> zobrazuje ověřovací zprávy pro konkrétní pole, což je podobné Pomocníkovi pro značku ověřovacích zpráv. Zadejte pole pro ověření pomocí atributu For a výraz lambda s pojmenováním vlastnosti modelu:
<ValidationMessage For="@(() => Model!.MaximumAccommodation)" />
Komponenty ValidationMessage<TValue> a ValidationSummary podporují libovolné atributy. Do vygenerovaného <div> nebo <ul> elementu se přidá jakýkoli atribut, který neodpovídá parametru komponenty.
Umožňuje řídit styl ověřovacích zpráv v šabloně stylů aplikace (wwwroot/css/app.css nebo wwwroot/css/site.css). Výchozí validation-message třída nastaví barvu textu ověřovacích zpráv na červenou:
.validation-message {
color: red;
}
Určení, jestli je pole formuláře platné
Slouží EditContext.IsValid k určení, zda je pole platné bez získání ověřovacích zpráv.
Podporováno, ale nedoporučuje se:
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
Doporučený:
var isValid = editContext.IsValid(fieldIdentifier);
Vlastní ověřovací atributy
Chcete-li zajistit správné přidružení výsledku ověření k poli při použití vlastního ověřovacího atributu, předejte kontext MemberName ověření při vytváření ValidationResult.
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 });
}
}
Vložte služby do vlastních ověřovacích atributů prostřednictvím ValidationContext. Následující příklad ukazuje formulář šéfkuchaře pro saláty, který ověřuje uživatelský vstup pomocí injekce závislostí (DI).
Třída SaladChef označuje schválený seznam složek hvězdicové lodi pro ten forward salát.
SaladChef.cs:
namespace BlazorSample;
public class SaladChef
{
public string[] SaladToppers = { "Horva", "Kanda Root", "Krintar", "Plomeek",
"Syto Bean" };
}
Zaregistrujte SaladChef v souboru Program v kontejneru DI aplikace.
builder.Services.AddTransient<SaladChef>();
Metoda IsValid následující SaladChefValidatorAttribute třídy získá SaladChef službu z DI ke kontrole vstupu uživatele.
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));
}
}
Následující komponenta ověřuje uživatelský vstup použitím SaladChefValidatorAttribute ([SaladChefValidator]) na řetězec složky salátu (SaladIngredient).
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);
}
Vlastní ověřovací atributy třídy CSS
Atributy vlastních ověřovacích tříd CSS jsou užitečné při integraci s architekturami CSS, například Bootstrap.
Pokud chcete zadat vlastní atributy třídy CSS, začněte zadáním stylů CSS pro vlastní ověření. V následujícím příkladu jsou zadány platné (validField) a neplatné (invalidField) styly.
Do šablony stylů aplikace přidejte následující třídy CSS:
.validField {
border-color: lawngreen;
}
.invalidField {
background-color: tomato;
}
Vytvořte třídu odvozenou z FieldCssClassProvider, která kontroluje ověřovací zprávy polí a aplikuje příslušný platný nebo neplatný styl.
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";
}
}
Nastavte CustomFieldClassProvider třídu jako Poskytovatele CSS třídy pole na instanci formuláře EditContext s SetFieldCssClassProvider.
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; }
}
}
Předchozí příklad zkontroluje platnost všech polí formuláře a použije styl pro každé pole. Pokud má formulář použít vlastní styly pouze na podmnožinu polí, upravte CustomFieldClassProvider tak, aby aplikoval styly podmíněně. Následující CustomFieldClassProvider2 příklad aplikuje styl pouze na Name pole. Pro všechna pole s názvy, která neodpovídají Name, string.Empty je vrácena a není použit žádný styl. Pomocí reflexe se pole shoduje s vlastností nebo názvem pole člena modelu, nikoli s přiřazenou entitou id HTML.
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;
}
}
Poznámka:
Při porovnávání názvu pole v předchozím příkladu se rozlišují malá a velká písmena, takže člen vlastnosti modelu označený jako "Name" musí odpovídat podmíněné kontrole "Name":
-
Správně odpovídá:
fieldId.FieldName == "Name" -
Nedaří se shodovat:
fieldId.FieldName == "name" -
Nedaří se shodovat:
fieldId.FieldName == "NAME" -
Nedaří se shodovat:
fieldId.FieldName == "nAmE"
Přidejte další vlastnost k Model, například:
[StringLength(10, ErrorMessage = "Description is too long.")]
public string? Description { get; set; }
Přidejte Description do formuláře komponenty CustomValidationForm.
<InputText @bind-Value="Model!.Description" />
EditContext Aktualizujte instanci v metodě komponenty OnInitialized tak, aby používala nového zprostředkovatele třídy CSS pole:
editContext?.SetFieldCssClassProvider(new CustomFieldClassProvider2());
Vzhledem k tomu, že ověřovací třída CSS není u pole Description použita, není stylované. Ověřování polí se ale spouští normálně. Pokud je zadáno více než 10 znaků, souhrn ověření označuje chybu:
Popis je příliš dlouhý.
V následujícím příkladu:
Vlastní styl CSS se použije u
Namepole.Všechna ostatní pole používají logiku podobnou výchozí logice Blazor a používají výchozí styly ověřování polí v šablonách stylů Blazor, stejně jako
modifiedsvalidneboinvalid. Všimněte si, že u výchozích stylů je nemusíte přidávat do šablony stylů aplikace, pokud je aplikace založená Blazor na šabloně projektu. U aplikací, které nejsou založené na Blazor šabloně projektu, je možné do šablony stylů aplikace přidat výchozí styly:.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";
}
}
}
}
EditContext Aktualizujte instanci v metodě komponenty OnInitialized tak, aby využívala předchozího poskytovatele třídy CSS pole:
editContext.SetFieldCssClassProvider(new CustomFieldClassProvider3());
Pomocí CustomFieldClassProvider3:
- Pole
Namepoužívá vlastní validační CSS styly aplikace. - Pole
Descriptionpoužívá logiku podobnou logice Blazor a výchozím stylům ověřování polí CSS Blazor.
Ověřování na úrovni třídy s využitím IValidatableObject
Ověřování na úrovni třídy s IValidatableObject (dokumentace k rozhraní API) je podporováno pro Blazor modely formulářů.
IValidatableObject Ověření se spustí pouze při odeslání formuláře a pouze v případě, že se úspěšně provede všechny ostatní ověření.
Blazor Ověřovací balíček datových poznámek
Poznámka:
BalíčekMicrosoft.AspNetCore.Components.DataAnnotations.Validation se už nedoporučuje pro aplikace, které cílí na .NET 10 nebo novější. Další informace najdete v části Vnořené objekty, typy kolekcí a komplexní typy .
Balíček Microsoft.AspNetCore.Components.DataAnnotations.Validation vyplní mezery v prostředí ověřování pomocí DataAnnotationsValidator komponenty. Balíček je aktuálně experimentální.
Varování
Balíček Microsoft.AspNetCore.Components.DataAnnotations.Validation má nejnovější verzi release candidate na NuGet.org. V tuto chvíli pokračujte v používání experimentálního balíčku Release Candidate. Experimentální funkce jsou k dispozici pro účely zkoumání životaschopnosti funkcí a nemusí být součástí stabilní verze. Sledujte úložiště GitHub s oznámeními, dotnet/aspnetcore úložiště GitHub nebo tuto sekci tématu pro další aktualizace.
Atribut [CompareProperty]
CompareAttribute nefunguje dobře s komponentou DataAnnotationsValidator, protože DataAnnotationsValidator nepřidružuje výsledek ověření ke konkrétnímu členu. To může vést k nekonzistentnímu chování mezi ověřováním na úrovni pole a ověřením celého modelu při odeslání.
Microsoft.AspNetCore.Components.DataAnnotations.Validation
balíček zavádí další ověřovací atribut, ComparePropertyAttributekterý funguje s těmito omezeními. V aplikaci Blazor je [CompareProperty] přímou náhradou za atribut [Compare].
Vnořené objekty a typy kolekcí
Blazor Ověřování formuláře zahrnuje podporu ověřování vlastností vnořených objektů a položek kolekce pomocí integrovaného DataAnnotationsValidator.
Pokud chcete vytvořit ověřený formulář, použijte komponentu DataAnnotationsValidatorEditForm uvnitř komponenty stejně jako předtím.
Přihlášení k funkci ověřování vnořených objektů a typů kolekcí:
- Volejte rozšiřující metodu AddValidation v souboru
Program, kde jsou zaregistrované služby. - Deklarujte typy modelu formuláře v souboru třídy jazyka C#, nikoli v komponentě Razor (
.razor). - Označte typ modelu kořenového tvaru pomocí atributu
[ValidatableType].
Bez dodržení předchozích kroků nezahrnuje ověřování formulářů vnořený model a ověření typu kolekce.
Následující příklad ukazuje objednávky zákazníků s vylepšeným ověřením formuláře (podrobnosti vynechány pro stručnost):
Ve Program.cs zavolejte AddValidation na kolekci služeb.
builder.Services.AddValidation();
V následující Order třídě [ValidatableType] se atribut vyžaduje u typu modelu nejvyšší úrovně. Ostatní typy se automaticky zjistí.
OrderItem a ShippingAddress nejsou uvedeny pro stručnost, ale vnořené a kolekční ověřování funguje stejným způsobem, pokud by byly uvedeny.
Order.cs:
using System.ComponentModel.DataAnnotations;
[ValidatableType]
public class Order
{
public Customer Customer { get; set; } = new();
public List<OrderItem> OrderItems { get; set; } = [];
}
public class Customer
{
[Required(ErrorMessage = "Name is required.")]
public string? FullName { get; set; }
[Required(ErrorMessage = "Email is required.")]
public string? Email { get; set; }
public ShippingAddress ShippingAddress { get; set; } = new();
}
V následující komponentě OrderPage se komponenta DataAnnotationsValidator nachází v komponentě EditForm.
OrderPage.razor:
<EditForm Model="Model">
<DataAnnotationsValidator />
<h3>Customer Details</h3>
<div class="mb-3">
<label>
Full Name
<InputText @bind-Value="Model!.Customer.FullName" />
</label>
<ValidationMessage For="@(() => Model!.Customer.FullName)" />
</div>
// ... form continues ...
</EditForm>
@code {
public Order? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
}
Požadavek na deklaraci typů modelů mimo Razor komponenty (.razor soubory) je způsoben tím, že nová ověřovací funkce i Razor samotný kompilátor používají generátor zdrojů. Výstup jednoho zdrojového generátoru se v současné době nedá použít jako vstup pro jiný generátor zdroje.
Pokyny k používání ověřovacích modelů z jiného sestavení najdete v části Použití ověřovacích modelů z jiné části sestavení .
Vnořené objekty, typy kolekcí a komplexní typy
Poznámka:
Pro aplikace, které cílí na .NET 10 nebo novější, už nedoporučujeme používat Microsoft.AspNetCore.Components.DataAnnotations.Validationexperimentální balíček a přístup popsaný v této části. Doporučujeme používat integrované ověřovací funkce DataAnnotationsValidator komponenty.
Blazor poskytuje podporu pro ověřování vstupu formuláře pomocí datových poznámek s integrovaným DataAnnotationsValidator. V DataAnnotationsValidator .NET 9 nebo starších verzích však ověřuje pouze vlastnosti nejvyšší úrovně modelu vázaného na formulář, který není vlastností kolekce nebo komplexního typu.
K ověření celého grafu objektu vázaného modelu, včetně vlastností kolekce a komplexního typu, použijte ObjectGraphDataAnnotationsValidatorexperimentálníMicrosoft.AspNetCore.Components.DataAnnotations.Validation balíček v .NET 9 nebo starší:
<EditForm ...>
<ObjectGraphDataAnnotationsValidator />
...
</EditForm>
Přidávání poznámek k vlastnostem modelu pomocí [ValidateComplexType]. V následujících třídách modelu třída ShipDescription obsahuje dodatečné datové anotace pro ověření při vázání modelu na formulář.
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; }
}
Použití ověřovacích modelů z jiného sestavení
Pro ověřování modelu, který je definován v jiném sestavení, jako je například knihovna nebo projekt .ClientBlazor Web App:
- Pokud je knihovna běžnou knihovnou tříd (není založená na sadách SDK
nebo ), přidejte do ní odkaz na balíček NuGet . Další kroky jsou vyžadovány pro knihovny prostých tříd, které jsou popsány dále v této části. - Vytvořte v knihovně nebo
.Clientprojektu metodu, která přijímá instanci IServiceCollection jako argument a volá AddValidation na ni. - V aplikaci volejte metodu i AddValidation.
Předchozí přístup vede k ověření typů z obou sestavení.
V následujícím příkladu je metoda AddValidationForTypesInClient vytvořena pro projekt .ClientBlazor Web App ověřování s použitím typů definovaných v projektu .Client.
ServiceCollectionExtensions.cs (v projektu .Client)
namespace BlazorSample.Client.Extensions;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddValidationForTypesInClient(
this IServiceCollection collection)
{
return collection.AddValidation();
}
}
Do souboru projektu Program serveru přidejte obor názvů a volejte metodu .Client rozšíření kolekce služeb projektu (AddValidationForTypesInClient) a AddValidation:
using BlazorSample.Client.Extensions;
...
builder.Services.AddValidationForTypesInClient();
builder.Services.AddValidation();
Nové atributy z Microsoft.Extensions.Validation balíčku (ValidatableTypeAttribute a SkipValidationAttribute) se publikují jako experimentální v .NET 10. Cílem balíčku je poskytnout novou sdílenou infrastrukturu pro funkce ověřování napříč architekturami a publikování experimentálních typů poskytuje větší flexibilitu pro konečný návrh veřejného rozhraní API pro lepší podporu při využívání architektur.
V Blazor aplikacích jsou typy zpřístupněny prostřednictvím vygenerovaného vloženého atributu. Pokud projekt webové aplikace, který používá Microsoft.NET.Sdk.Web sadu SDK (<Project Sdk="Microsoft.NET.Sdk.Web">) nebo seznam RCL, který používá Microsoft.NET.Sdk.Razor sadu SDK (<Project Sdk="Microsoft.NET.Sdk.Razor">), obsahuje Razor komponenty (.razor), architektura automaticky vygeneruje interní atribut uvnitř projektu (Microsoft.Extensions.Validation.Embedded.ValidatableType, Microsoft.Extensions.Validation.Embedded.SkipValidation). Tyto typy jsou zaměnitelné se skutečnými atributy a nejsou označeny experimentální. Ve většině případů vývojáři používají [ValidatableType]/[SkipValidation] atributy ve svých třídách bez obav o zdroj.
Předchozí přístup ale není možné použít v knihovnách prostých tříd, které používají Microsoft.NET.Sdk sadu SDK (<Project Sdk="Microsoft.NET.Sdk">). Použití typů v knihovně prostých tříd vede k upozornění analýzy kódu:
ASP0029: Microsoft.Extensions.Validation.ValidatableTypeAttribute je určen pouze pro účely vyhodnocení a v budoucích aktualizacích se může změnit nebo odebrat. Chcete-li pokračovat, potlačíte tuto diagnostiku.
Upozornění lze potlačit pomocí některého z následujících přístupů:
Vlastnost
<NoWarn>v souboru projektu:<PropertyGroup> <NoWarn>$(NoWarn);ASP0029</NoWarn> </PropertyGroup>Direktiva
pragma, kde se atribut používá:#pragma warning disable ASP0029 [Microsoft.Extensions.Validation.ValidatableType] #pragma warning restore ASP0029Pravidlo pro soubor
EditorConfig (): dotnet_diagnostic.ASP0029.severity = none
Pokud potlačení upozornění není přijatelné, ručně vytvořte vložený atribut v knihovně, kterou web a Razor sady SDK generují automaticky.
ValidatableTypeAttribute.cs:
namespace Microsoft.Extensions.Validation.Embedded
{
[AttributeUsage(AttributeTargets.Class)]
internal sealed class ValidatableTypeAttribute : Attribute
{
}
}
Použijte přesný obor názvů (Microsoft.Extensions.Validation.Embedded) a název třídy (ValidatableTypeAttribute), aby generátor zdroje ověření mohl zjistit a použít typ. Globální příkaz pro obor názvů můžete deklarovat buď s použitím using, příkazu global using Microsoft.Extensions.Validation.Embedded;, nebo položky <Using Include="Microsoft.Extensions.Validation.Embedded" /> v souboru projektu knihovny.
Podle toho, který přístup se přijme, označte přítomnost alternativního řešení pro budoucí aktualizaci kódu. Aktualizace rozhraní, které usnadňují přijetí typů ověřování v knihovnách prostých tříd, se plánují pro .NET 11 (listopad 2026).
Aktivace tlačítka pro odeslání na základě validace formuláře
Pokud chcete povolit a zakázat tlačítko odeslat na základě ověření formuláře, použijte následující příklad:
- Používá zkrácenou verzi dřívějšího
Starfleet Starship Databaseformuláře (Starship3součást) části Příklad formuláře článku Vstupní komponenty, která přijímá pouze hodnotu pro ID lodi. OstatníStarshipvlastnosti obdrží platné výchozí hodnoty při vytvoření instanceStarshiptypu. - Použije formulář EditContext k přiřazení modelu při inicializaci komponenty.
- Ověří formulář v zpětném volání kontextu OnFieldChanged a povolí a zakáže tlačítko odeslat.
- Implementuje IDisposable a odhlásí obslužnou rutinu události v metodě
Dispose. Další informace najdete v tématu odstranění komponenty ASP.NET Core Razor.
Poznámka:
Při přiřazování k EditForm.EditContext, neprovádějte současně přiřazení EditForm.Model k EditForm.
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;
}
}
}
Pokud formulář není předvyplněn platnými hodnotami a chcete při jeho načtení zakázat tlačítko Submit, nastavte příslušný prvek na hodnotu formInvalidtrue.
Vedlejším účinkem předchozího přístupu je, že souhrn ověření (ValidationSummary součást) je naplněn neplatnými poli poté, co uživatel pracuje s libovolným polem. Tento scénář můžete vyřešit některým z následujících způsobů:
- Nepoužívejte komponentu ValidationSummary ve formuláři.
- Zviditelnit komponentu ValidationSummary , když je vybráno tlačítko odeslat (například v
Submitmetodě).
<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";
}
}
DataAnnotationsValidator chování ověřování
Komponenta DataAnnotationsValidator má stejné pořadí ověření a chování zkratek jako System.ComponentModel.DataAnnotations.Validator. Při ověřování instance typu Tse použijí následující pravidla:
- Vlastnosti
Tčlenů jsou ověřeny, včetně rekurzivního ověřování vnořených objektů. - Ověřují se atributy
Tna úrovni typu. - Metoda IValidatableObject.Validate se provede, pokud
Tji implementuje.
Pokud některý z předchozích kroků způsobí chybu ověření, zbývající kroky se přeskočí.