In ASP.NET Core-8 Web API, I am implementing Custom Messages with Fluent Validation
DTO:
public class CreateAccountRequestDto
{
public int PreferredClassCode { get; set; }
public DateTime DateOfBirth { get; set; }
}
CreateAccountRequestDtoValidator:
public class CreateAccountRequestDtoValidator : AbstractValidator<CreateAccountRequestDto>
{
private readonly IDbDataAccess _dbDataAccess;
public CreateAccountRequestDtoValidator(
IDbDataAccess dbDataAccess
)
{
_dbDataAccess = dbDataAccess;
}
public CreateAccountRequestDtoValidator()
{
RuleFor(x => x.DateOfBirth)
.MustAsync(async (request, dob, context) => await ValidateDateOfBirth(request, dob, context))
.WithMessage(context => context.MessageFormatter.GetArgument("Message").ToString());
}
private async Task<bool> ValidateDateOfBirth(CreateAccountRequestDto request, DateTime dateOfBirth, ValidationContext<CreateAccountRequestDto> context)
{
int age = DateTime.Today.Year - dateOfBirth.Year;
bool isValid = true;
string message = "";
if (string.IsNullOrWhiteSpace(request.Bvn) && age < 16)
{
message = "Customer must be at least 16 years old without BVN.";
isValid = false;
}
else
{
if (request.PreferredClassCode == 999 || request.PreferredClassCode == 888) // Timeless class
{
if (age < 55)
{
message = "Customer must be at least 55 years old for this class.";
isValid = false;
}
}
else if (request.PreferredClassCode == 357)
{
if (age < 16 || age > 25)
{
message = "Customer must be between 16 and 25 for this class.";
isValid = false;
}
}
}
if (!isValid)
{
context.MessageFormatter.AppendArgument("Message", message);
}
return await Task.FromResult(isValid);
}
}
I got these errors:
Severity Code Description Project File Line Suppression State Error CS1503 Argument 3: cannot convert from 'System.Threading.CancellationToken' to 'FluentValidation.ValidationContext<FlexcubeAcopAccountService.DTOs.Request.CreateAccountRequestDto>'
and
Severity Code Description Project File Line Suppression State Error CS1061 'CreateAccountRequestDto' does not contain a definition for 'MessageFormatter' and no accessible extension method 'MessageFormatter' accepting a first argument of type 'CreateAccountRequestDto' could be found (are you missing a using directive or an assembly reference?)
It highlights:
context in await ValidateDateOfBirth(request, dob, context))
and also
MessageFormatter
in
WithMessage(context => context.MessageFormatter.GetArgument("Message").ToString())
I also used this:
RuleFor(x => x.DateOfBirth)
.MustAsync(async (request, dob, context) =>
{
return await ValidateDateOfBirth(request, dob, context);
})
.WithMessage(context => context.MessageFormatter.GetArgument("Message").ToString());
But still got the same error
Kindly help resolve the error.
In your MustAsync()
, you have to use the function with 4 arguments to obtain the ValidationContext
:
public static IRuleBuilderOptions<T, TProperty> MustAsync<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Func<T, TProperty, ValidationContext<T>, CancellationToken, Task<bool>> predicate)
While retrieving the customized Message
from the ValidateDateOfBirth
method, you just need to apply the "{Message}"
placeholder. (Reference: Custom message placeholders)
public CreateAccountRequestDtoValidator()
{
RuleFor(x => x.DateOfBirth)
.MustAsync(async (request, dob, context, cancellationToken) => await ValidateDateOfBirth(request, dob, context))
.WithMessage("{Message}");
}