
FluentValidation und Blazilla erweitern die Standardvalidierung in Blazor um flexible, testbare und wartbare Validierungsregeln. Der Artikel zeigt anhand praxisnaher Beispiele, wie sich grundlegende Validierungen, verschachtelte Objekte, asynchrone Prüfungen und kontextabhängige RuleSets effizient umsetzen lassen. Das Ergebnis ist eine skalierbare Validierungsarchitektur für moderne Blazor-Anwendungen.
In modernen Webanwendungen ist die Validierung von Benutzereingaben ein zentraler Bestandteil der User Experience und Datenintegrität. Blazor, Microsofts komponentenbasiertem Web-Framework für .NET, bietet mit dem EditForm-Konzept bereits eine solide Grundlage. Doch die Standardvalidierung über DataAnnotations stößt bei komplexeren Anforderungen schnell an ihre Grenzen.
Dieser Artikel zeigt, wie sich mit der Kombination aus FluentValidation und der Open-Source-Bibliothek Blazilla eine wartbare, testbare und flexible Architektur für die Validierung in Blazor aufbauen lässt. Die Umsetzung wird anhand eines praxisnahen Beispielprojekts erläutert.
Blazor setzt standardmäßig auf DataAnnotations – Attribute wie [Required], [StringLength] oder [EmailAddress], die direkt an Modelleigenschaften annotiert werden. Für einfache Szenarien ist das ausreichend.
Sobald Validierungsregeln jedoch kontextabhängig sind, auf andere Felder verweisen oder asynchrone Prüfungen erfordern, wird dieser Ansatz unhandlich. Die Validierungslogik vermischt sich mit dem Datenmodell, Cross-Field-Validierungen erfordern Workarounds und asynchrone Prüfungen, beispielsweise Duplikatsprüfungen gegen eine Datenbank, sind nicht vorgesehen.
FluentValidation löst diese Probleme durch einen regelbasierten Ansatz, bei dem die Validierungslogik in eigenen Klassen gekapselt wird – getrennt vom Modell, testbar und flexibel erweiterbar.
Blazilla ist eine schlanke Komponentenbibliothek, die FluentValidation nahtlos in das EditForm-Ökosystem von Blazor integriert. Die zentrale Komponente FluentValidator übernimmt die Rolle des DataAnnotationsValidator und leitet Validierungsergebnisse automatisch an ValidationSummary und ValidationMessage weiter.
Die Einrichtung ist minimal. Im Projekt wird Blazilla als NuGet-Paket referenziert und die Validatoren werden als Services registriert:
1builder.Services.AddSingleton<IValidator<Person>, PersonValidator>();
2builder.Services.AddSingleton<IValidator<Registration>, RegistrationValidator>();
3builder.Services.AddSingleton<IValidator<Product>, ProductValidator>();In der Razor-Komponente ersetzt FluentValidator den DataAnnotationsValidator:
1<EditForm Model="person" OnValidSubmit="HandleValidSubmit">
2 <FluentValidator />
3 <ValidationSummary />
4 <!-- Formularfelder -->
5</EditForm>
Das Beispielprojekt demonstriert vier typische Validierungsanforderungen, die in realen Anwendungen regelmäßig auftreten.
Das einfachste Szenario ist ein Personenformular mit Pflichtfeldern, Längenbegrenzungen und Formatprüfungen. Der PersonValidator definiert die Regeln klar und lesbar:
1public class PersonValidator : AbstractValidator<Person>
2{
3 public PersonValidator()
4 {
5 RuleFor(p => p.FirstName)
6 .NotEmpty().WithMessage("Vorname ist erforderlich.")
7 .MaximumLength(50);
8
9 RuleFor(p => p.EmailAddress)
10 .NotEmpty()
11 .EmailAddress().WithMessage("Bitte geben Sie eine gültige E-Mail-Adresse ein.");
12
13 RuleFor(p => p.BirthDate)
14 .NotNull()
15 .LessThan(DateTime.Today).WithMessage("Geburtsdatum muss in der Vergangenheit liegen.");
16 }
17}Die Regeln lassen sich nahezu wie natürliche Sprache lesen – ein entscheidender Vorteil gegenüber attributbasierter Validierung.
Reale Formulare enthalten häufig verschachtelte Datenstrukturen. Ein PersonWithAddress-Modell enthält beispielsweise ein Address-Unterobjekt mit eigenen Validierungsregeln. FluentValidation unterstützt dies über Child-Validatoren:
1public class PersonWithAddressValidator : AbstractValidator<PersonWithAddress>
2{
3 public PersonWithAddressValidator()
4 {
5 RuleFor(p => p.FirstName).NotEmpty().MaximumLength(50);
6 RuleFor(p => p.LastName).NotEmpty().MaximumLength(50);
7
8 RuleFor(p => p.Address)
9 .SetValidator(new AddressValidator());
10 }
11}Der AddressValidator validiert Straße, Stadt und Postleitzahl unabhängig. Dadurch kann er sowohl eigenständig als auch innerhalb anderer Validatoren wiederverwendet werden. Die Postleitzahl wird dabei per Regex auf das Format deutscher und österreichischer Postleitzahlen geprüft.
Eine Registrierungsseite muss häufig prüfen, ob Benutzername oder E-Mail-Adresse bereits vergeben sind. Da hierfür ein Serveraufruf erforderlich ist, bietet FluentValidation die Methode MustAsync:
1RuleFor(r => r.Username)
2 .NotEmpty()
3 .MinimumLength(3)
4 .MustAsync(async (username, cancellation) =>
5 {
6 await Task.Delay(800, cancellation);
7
8 string[] takenUsernames = ["admin", "root", "user", "test"];
9
10 return !takenUsernames.Contains(username.ToLower());
11 })
12 .WithMessage("Dieser Benutzername ist bereits vergeben.");Blazilla unterstützt dieses Szenario über den Parameter AsyncMode. Im Code-Behind wird die Validierung explizit ausgelöst:
1private async Task HandleSubmit(EditContext editContext)
2{
3 isSubmitting = true;
4
5 var isValid = await editContext.ValidateAsync();
6
7 if (isValid)
8 {
9 submitted = true;
10 }
11
12 isSubmitting = false;
13}Die Kombination aus OnSubmit und ValidateAsync() ermöglicht die vollständige Kontrolle über den Ablauf einschließlich Ladeanzeigen während der Prüfung.
In vielen Anwendungen gelten abhängig vom Anwendungsfall unterschiedliche Regeln. Ein Produktformular benötigt beispielsweise beim Anlegen eine SKU, während bei einer Aktualisierung andere Anforderungen gelten.
FluentValidation unterstützt dieses Szenario mit RuleSets:
1public class ProductValidator : AbstractValidator<Product>
2{
3 public ProductValidator()
4 {
5 RuleFor(p => p.Name).NotEmpty().MaximumLength(100);
6 RuleFor(p => p.Price).GreaterThan(0);
7
8 RuleSet("Create", () =>
9 {
10 RuleFor(p => p.SKU)
11 .NotEmpty()
12 .Matches(@"^[A-Z]{2,4}-\d{4,6}$")
13 .WithMessage("SKU muss im Format 'AB-1234' sein.");
14 });
15
16 RuleSet("Update", () =>
17 {
18 RuleFor(p => p.Description).MaximumLength(500);
19 });
20 }
21}In der Razor-Komponente wird das gewünschte RuleSet aktiviert:
1<FluentValidator RuleSets="@(new[] { "Create" })" />
2
3<!-- oder alle Regeln -->
4<FluentValidator AllRules="true" />Dadurch lässt sich ein Formular für verschiedene Geschäftsprozesse nutzen, ohne Validierungslogik zu duplizieren.
Der Ansatz bietet gegenüber der Standardvalidierung mehrere Vorteile:
Mit FluentValidation und Blazilla lässt sich die Validierung in Blazor deutlich flexibler und wartbarer gestalten als mit klassischen DataAnnotations.
Die Trennung von Modell und Validierungslogik, die Unterstützung verschachtelter Objekte, asynchroner Prüfungen sowie kontextabhängiger Regeln ermöglicht eine Architektur, die auch in größeren Blazor-Anwendungen problemlos skaliert.
Der Einstieg ist unkompliziert: Ein NuGet-Paket, eine Service-Registrierung und der Austausch einer Komponente im Formular genügen, um die Leistungsfähigkeit von FluentValidation in Blazor vollständig zu nutzen.
GitHub-Projekt: https://github.com/Nutzlastkaktus8/BlazillaTest.git

Unser Geschäftsführer Tibor Csizmadia und unser Kundenbetreuer Jens Walter stehen Ihnen persönlich zur Verfügung. Profitieren Sie von unserer langjährigen Erfahrung und erhalten Sie eine kompetente Beratung in einem unverbindlichen Austausch.