Does Radzen support fluentvalidation?
We are not familiar with fluentvalidation and how it works - you can check our validator components if you need validation.
using System;
using FluentValidation.Results;
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// A validator component which compares a component value with a specified value.
/// Must be placed inside a <see cref="RadzenTemplateForm{TItem}" />
/// </summary>
/// </example>
public class RadzenFluentValidator : ValidatorBase
{
private ValidationResult validator;
/// <summary>
/// Gets or sets the message displayed when the component is invalid. Set to <c>"Value should match"</c> by default.
/// </summary>
[Parameter]
public override string Text { get; set; } = "Value should match";
/// <summary>
/// Specifies the function which validates the component value. Must return <c>true</c> if the component is valid.
/// </summary>
[Parameter]
public ValidationResult Validator
{
get => validator;
set
{
validator = value;
// If there is at least one error, override Text with the first error message
if (validator?.Errors?.Any() == true)
{
Text = string.Join(" ", validator.Errors.Select(e => e.ErrorMessage));
}
else
{
Text = "Value should match";
}
}
}
/// <inheritdoc />
protected override bool Validate(IRadzenFormComponent component)
{
return validator.IsValid;
}
}
}
I think that is what I was looking for. But I'm not sure to understand how to use it.
I guess I have to put the RadzenFluentValidator
like any other Radzen validator.
But when/where/how do I execute the FluentValidator and set the validation result in RadzenFluentValidator
?
Thanks for your message, it was not full code. Here is full example of use:
<RadzenLabel Text="Name" />
<RadzenTextBox @bind-Value="employee.Name" Name="Name" Style="width:100%" />
<RadzenFluentValidator Component="Name" Popup="false" Validator="validator.ValidateSingle(employee, x => x.Name)" />
@code{
private EmployeeDtoValidator validator = new ();
private EmployeeDto employee = new ();
}
public class EmployeeDtoValidator : BaseDtoValidator<EmployeeDto>
{
public EmployeeDtoValidator()
{
RuleFor(x => x.Name)
.NameRule();
}
}
public static class EmploteeDtoValidationExtensions
{
public static IRuleBuilderOptions<T, string> NameRule<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder
.NotEmpty()
.WithMessage("Name is required.")
.MaximumLength(100)
.WithMessage("Name must not exceed 100 characters.");
}
}
public class EmployeeDto
{
public string Name { get; set; }
}
public class BaseDtoValidator<T> : AbstractValidator<T>
{
public ValidationResult ValidateSingle(
T dto,
Expression<Func<T, object>> propertySelector)
{
return this.Validate(dto, options => options.IncludeProperties(propertySelector));
}
}
Thank you very much.
It's not yet totally working for me. Validation is triggered, the Text property in RadzenFluentValidator is set, but message is not displayed. I will debug to find out why.
Hi,
I've found why it doesn't work. Validate
method is called before Validator
is set.
I have made a few change to get it work. Here is my version of the validator :
public class RadzenFluentValidator : ValidatorBase
{
private const string DefaultErrorMessage = "Value must match";
[Parameter]
public override string Text { get; set; } = DefaultErrorMessage;
[Parameter, EditorRequired]
public Func<ValidationResult> ValidationResult { get; set; } = () => new ValidationResult();
/// <inheritdoc />
protected override bool Validate(IRadzenFormComponent component)
{
ValidationResult result = ValidationResult();
Text = result.Errors?.Count > 0 ? string.Join(" ", result.Errors.Select(e => e.ErrorMessage)) : DefaultErrorMessage;
return result.IsValid;
}
}
and the call :
<RadzenFluentValidator Component="Name" ValidationResult="@(() => validator.ValidateSingle(model, x => x.Name))" />
And here is a generic version that avoids the need to specify the validation expression
public class RadzenFluentValidatorGeneric<TModel> : ValidatorBase
{
private const string DefaultErrorMessage = "Value must match";
[Parameter]
public override string Text { get; set; } = DefaultErrorMessage;
[Parameter, EditorRequired]
public BaseValidator<TModel> FluentValidator { get; set; } = new();
[Parameter, EditorRequired]
public TModel Model { get; set; } = default!;
[Parameter, EditorRequired]
public Expression<Func<TModel, object>> PropertySelector { get; set; } = null!;
protected override bool Validate(IRadzenFormComponent component)
{
ValidationResult result = FluentValidator.ValidateSingle(Model, PropertySelector);
Text = result.Errors?.Count > 0 ? string.Join(" ", result.Errors.Select(e => e.ErrorMessage)) : DefaultErrorMessage;
return result.IsValid;
}
}
the call :
<RadzenFluentValidatorGeneric Component="Name" Model="model" FluentValidator="validator" PropertySelector="x => x.Name" />