Skip to content

Commit

Permalink
Async validation method (#137)
Browse files Browse the repository at this point in the history
* Async validation method

* Added info to readme and tidied up samples
  • Loading branch information
chrissainty committed Jun 1, 2022
1 parent f8eff24 commit 170ac3d
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 253 deletions.
1 change: 1 addition & 0 deletions Blazored.FluentValidation.sln
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Global
GlobalSection(NestedProjects) = preSolution
{8BC1065A-A71E-4568-8A67-9C3AF039F73A} = {D5C6DCA9-C2BD-4117-BCCC-19E36E8406AB}
{2459CF4B-6548-4031-B784-43E943E270A9} = {D5C6DCA9-C2BD-4117-BCCC-19E36E8406AB}
{42276235-5139-41D6-923D-18B7EB5E3E44} = {D5C6DCA9-C2BD-4117-BCCC-19E36E8406AB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {42B22D99-6E59-4B30-88AD-B9CC07E0DA49}
Expand Down
66 changes: 52 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ A library for using FluentValidation with Blazor

![Nuget](https://img.shields.io/nuget/v/blazored.fluentvalidation.svg)

### Installing
## Installing

You can install from Nuget using the following command:

Expand All @@ -16,43 +16,40 @@ Or via the Visual Studio package manger.
## Basic Usage
Start by add the following using statement to your root `_Imports.razor`.

```csharp
```razor
@using Blazored.FluentValidation
```

You can then use it as follows within a `EditForm` component.

```html
<EditForm Model="@Person" OnValidSubmit="@SubmitValidForm">
```razor
<EditForm Model="@_person" OnValidSubmit="@SubmitValidForm">
<FluentValidationValidator />
<ValidationSummary />
<p>
<label>Name: </label>
<InputText @bind-Value="@Person.Name" />
<InputText @bind-Value="@_person.Name" />
</p>
<p>
<label>Age: </label>
<InputNumber @bind-Value="@Person.Age" />
<InputNumber @bind-Value="@_person.Age" />
</p>
<p>
<label>Email Address: </label>
<InputText @bind-Value="@Person.EmailAddress" />
<InputText @bind-Value="@_person.EmailAddress" />
</p>
<button type="submit">Save</button>

</EditForm>
@code {
Person Person { get; set; } = new Person();
private Person _person = new();
void SubmitValidForm()
{
Console.WriteLine("Form Submitted Successfully!");
}
private void SubmitValidForm()
=> Console.WriteLine("Form Submitted Successfully!");
}
```

Expand All @@ -67,4 +64,45 @@ You can control this behaviour using the `DisableAssemblyScanning` parameter. If

You can find examples of different configurations in the sample projects. The Blazor Server project is configured to load validators from DI only. The Blazor WebAssembly project is setup to load validators using reflection.

**Note:** When scanning assemblies the component will swallow any exceptions thrown by that process. This is to stop exceptions thrown by scanning third party dependencies crashing your app.
**Note:** When scanning assemblies the component will swallow any exceptions thrown by that process. This is to stop exceptions thrown by scanning third party dependencies crashing your app.

## Async Validation
If you're using async validation, you can use the `ValidateAsync` method on the `FluentValidationValidator`.

```razor
<EditForm Model="@_person" OnSubmit="@SubmitFormAsync">
<FluentValidationValidator @ref="_fluentValidationValidator" />
<ValidationSummary />
<p>
<label>Name: </label>
<InputText @bind-Value="@_person.Name" />
</p>
<p>
<label>Age: </label>
<InputNumber @bind-Value="@_person.Age" />
</p>
<p>
<label>Email Address: </label>
<InputText @bind-Value="@_person.EmailAddress" />
</p>
<button type="submit">Save</button>
</EditForm>
@code {
private Person _person = new();
private FluentValidationValidator? _fluentValidationValidator;
private void SubmitFormAsync()
{
if (await _fluentValidationValidator!.ValidateAsync())
{
Console.WriteLine("Form Submitted Successfully!");
}
}
}
```
51 changes: 23 additions & 28 deletions samples/BlazorServer/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,63 @@

<hr class="mb-5" />

<EditForm Model="@Person" OnValidSubmit="@SubmitValidForm">
<EditForm Model="@_person" OnValidSubmit="@SubmitValidForm">
<FluentValidationValidator @ref="_fluentValidationValidator" DisableAssemblyScanning="@true" />
<ValidationSummary />

<p>
<label>First Name: </label>
<InputText @bind-Value="@Person.FirstName" />
<ValidationMessage For="@(() => Person.FirstName)" />
<InputText @bind-Value="@_person.FirstName" />
<ValidationMessage For="@(() => _person.FirstName)" />
</p>

<p>
<label>Last Name: </label>
<InputText @bind-Value="@Person.LastName" />
<ValidationMessage For="@(() => Person.LastName)" />
<InputText @bind-Value="@_person.LastName" />
<ValidationMessage For="@(() => _person.LastName)" />
</p>

<hr />

<p>
<label>Age: </label>
<InputNumber @bind-Value="@Person.Age" />
<ValidationMessage For="@(() => Person.Age)" />
<InputNumber @bind-Value="@_person.Age" />
<ValidationMessage For="@(() => _person.Age)" />
</p>

<p>
<label>Email Address: </label>
<InputText @bind-Value="@Person.EmailAddress" />
<ValidationMessage For="@(() => Person.EmailAddress)" />
<InputText @bind-Value="@_person.EmailAddress" />
<ValidationMessage For="@(() => _person.EmailAddress)" />
</p>

<p>
<label>Address: Line 1: </label>
<InputText @bind-Value="@Person.Address.Line1" />
<ValidationMessage For="@(() => Person.Address.Line1)" />
<InputText @bind-Value="@_person.Address.Line1" />
<ValidationMessage For="@(() => _person.Address.Line1)" />
</p>

<p>
<label>Address: Line 2: </label>
<InputText @bind-Value="@Person.Address.Line2" />
<InputText @bind-Value="@_person.Address.Line2" />
</p>

<p>
<label>Address: Town: </label>
<InputText @bind-Value="@Person.Address.Town" />
<ValidationMessage For="@(() => Person.Address.Town)" />
<InputText @bind-Value="@_person.Address.Town" />
<ValidationMessage For="@(() => _person.Address.Town)" />
</p>

<p>
<label>Address: County: </label>
<InputText @bind-Value="@Person.Address.County" />
<ValidationMessage For="@(() => Person.Address.County)" />
<InputText @bind-Value="@_person.Address.County" />
<ValidationMessage For="@(() => _person.Address.County)" />
</p>

<p>
<label>Address: Postcode: </label>
<InputText @bind-Value="@Person.Address.Postcode" />
<ValidationMessage For="@(() => Person.Address.Postcode)" />
<InputText @bind-Value="@_person.Address.Postcode" />
<ValidationMessage For="@(() => _person.Address.Postcode)" />
</p>

<button type="submit">Save</button>
Expand All @@ -70,17 +70,12 @@
<button @onclick="PartialValidate">Partial Validation</button>

@code {
Person Person { get; set; } = new();

private readonly Person _person = new();
private FluentValidationValidator? _fluentValidationValidator;

void SubmitValidForm()
{
Console.WriteLine("Form Submitted Successfully!");
}
private void SubmitValidForm()
=> Console.WriteLine("Form Submitted Successfully!");

void PartialValidate()
{
Console.WriteLine($"Partial validation result : {_fluentValidationValidator?.Validate(options => options.IncludeRuleSets("Names"))}");
}
private void PartialValidate()
=> Console.WriteLine($"Partial validation result : {_fluentValidationValidator?.Validate(options => options.IncludeRuleSets("Names"))}");
}
52 changes: 26 additions & 26 deletions samples/BlazorWebAssembly/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,63 @@

<hr class="mb-5" />

<EditForm Model="@Person" OnValidSubmit="@SubmitValidForm">
<EditForm Model="@_person" OnSubmit="@SubmitFormAsync">
<FluentValidationValidator @ref="_fluentValidationValidator" />
<ValidationSummary />

<p>
<label>First Name: </label>
<InputText @bind-Value="@Person.FirstName" />
<ValidationMessage For="@(() => Person.FirstName)" />
<InputText @bind-Value="@_person.FirstName" />
<ValidationMessage For="@(() => _person.FirstName)" />
</p>

<p>
<label>Last Name: </label>
<InputText @bind-Value="@Person.LastName" />
<ValidationMessage For="@(() => Person.LastName)" />
<InputText @bind-Value="@_person.LastName" />
<ValidationMessage For="@(() => _person.LastName)" />
</p>

<hr />

<p>
<label>Age: </label>
<InputNumber @bind-Value="@Person.Age" />
<ValidationMessage For="@(() => Person.Age)" />
<InputNumber @bind-Value="@_person.Age" />
<ValidationMessage For="@(() => _person.Age)" />
</p>

<p>
<label>Email Address: </label>
<InputText @bind-Value="@Person.EmailAddress" />
<ValidationMessage For="@(() => Person.EmailAddress)" />
<InputText @bind-Value="@_person.EmailAddress" />
<ValidationMessage For="@(() => _person.EmailAddress)" />
</p>

<p>
<label>Address: Line 1: </label>
<InputText @bind-Value="@Person.Address.Line1" />
<ValidationMessage For="@(() => Person.Address.Line1)" />
<InputText @bind-Value="@_person.Address.Line1" />
<ValidationMessage For="@(() => _person.Address.Line1)" />
</p>

<p>
<label>Address: Line 2: </label>
<InputText @bind-Value="@Person.Address.Line2" />
<InputText @bind-Value="@_person.Address.Line2" />
</p>

<p>
<label>Address: Town: </label>
<InputText @bind-Value="@Person.Address.Town" />
<ValidationMessage For="@(() => Person.Address.Town)" />
<InputText @bind-Value="@_person.Address.Town" />
<ValidationMessage For="@(() => _person.Address.Town)" />
</p>

<p>
<label>Address: County: </label>
<InputText @bind-Value="@Person.Address.County" />
<ValidationMessage For="@(() => Person.Address.County)" />
<InputText @bind-Value="@_person.Address.County" />
<ValidationMessage For="@(() => _person.Address.County)" />
</p>

<p>
<label>Address: Postcode: </label>
<InputText @bind-Value="@Person.Address.Postcode" />
<ValidationMessage For="@(() => Person.Address.Postcode)" />
<InputText @bind-Value="@_person.Address.Postcode" />
<ValidationMessage For="@(() => _person.Address.Postcode)" />
</p>

<button type="submit">Save</button>
Expand All @@ -70,17 +70,17 @@
<button @onclick="PartialValidate">Partial Validation</button>

@code {
Person Person { get; set; } = new Person();

private readonly Person _person = new();
private FluentValidationValidator? _fluentValidationValidator;

void SubmitValidForm()
private async Task SubmitFormAsync()
{
Console.WriteLine("Form Submitted Successfully!");
if (await _fluentValidationValidator!.ValidateAsync())
{
Console.WriteLine("Form Submitted Successfully!");
}
}

void PartialValidate()
{
Console.WriteLine($"Partial validation result : {_fluentValidationValidator?.Validate(options => options.IncludeRuleSets("Names"))}");
}
private void PartialValidate()
=> Console.WriteLine($"Partial validation result : {_fluentValidationValidator?.Validate(options => options.IncludeRuleSets("Names"))}");
}
8 changes: 4 additions & 4 deletions samples/Shared/SharedModels/Person.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ public PersonValidator()
.LessThan(150).WithMessage("Age cannot be greater than 150");

RuleFor(p => p.EmailAddress)
.NotEmpty().WithMessage("You must enter a email address")
.NotEmpty().WithMessage("You must enter an email address")
.EmailAddress().WithMessage("You must provide a valid email address")
.MustAsync(async (email, _) => await IsUniqueAsync(email)).WithMessage("Email address must be unique").When(p => !string.IsNullOrEmpty(p.EmailAddress));
.MustAsync(async (email, _) => await IsUniqueAsync(email)).WithMessage("Email address must be unique");

RuleFor(p => p.Address).SetValidator(new AddressValidator());
}

private static async Task<bool> IsUniqueAsync(string email)
private static async Task<bool> IsUniqueAsync(string? email)
{
await Task.Delay(300);
return email.ToLower() != "mail@my.com";
return email?.ToLower() != "mail@my.com";
}
}
}
Loading

0 comments on commit 170ac3d

Please sign in to comment.