I am struggling with a custom validation in an EditForm using basic validation in my Blazor server-side app. In this MS doc it is stated
A handler for the OnValidationRequested event of the EditContext
executes custom validation logic. The handler’s result updates the
ValidationMessageStore instance.
but nothing is mentioned on how to inform the validation logic if the custom validation was successful or failed. The code below shows how error messages can be added in a custom validation handler, but OnValidSubmit
is called during the await
-ing of the DB query in the custom validation handler. So it seems necessary, to perform the custom validation also in OnValidSubmit
, which is acceptable in my case but not nice.
Q: Is there no other/nicer way to inform the validation logic about the result of a custom validation in order to prevent having to re-check inside OnValidSubmit
?
Here is my code in OnParametersSetAsync
:
// Create EditContext
editContext = new EditContext(assignment);
// Create additional message store for the custom validation messages
validationMessageStore = new(editContext);
// Add additional validation handler
editContext.OnValidationRequested += OnValidationRequestedAsync;
Here is the code for the custom validation handler:
private async void OnValidationRequestedAsync(object sender, ValidationRequestedEventArgs e)
{
// clear previous error messages
validationMessageStore.Clear();
// check DB if Title already exists
bool exists = await myService.IsPresent(myModel.Title);
// While waiting for this async process, OnValidSubmit gets called
if (exists)
{
// yes, so add a validation message
validationMessageStore.Add(() => myModel.Title, "The Title is already used.");
// inform ValidationSummary that a new error message has been added
editContext.NotifyValidationStateChanged();
}
}
In OnValidSubmit
I have to re-check:
// check DB if Title already exists
bool exists = await myService.IsPresent(myModel.Title);
if (exists)
{
// do nothing if invalid (error message is displayed by OnValidationRequestedAsync)
return;
}
// ...
2
Answers
I found a possible solution (at least in general) by decorating the property with a custom validation attribute. Just add
to the property of the model class and add the static method in the model class that performs the custom validation and returns an appropriate status
While this approach should work in general, in my particular case it didn't work, because I do not have access to the database context from the static method.
Have you looked at Blazored.Validation? It takes all the pain out of this. You create a validator (or you can use attributes, but for custom validation, I find the validator approach much easier), then simply add the
<FluentValidationValidator />
tag inside your form, and it all just works. Validation is fired as appropriate, messages are shown as expected and youOnValidSubmit
just doesn’t get called if there are validation errors.Hope that helps.