Home > Back-end >  FluentValidator and select element
FluentValidator and select element

Time:05-18

I use Razor pages and want to specify a rule, when at least one selectItem should be selected for multiply select element.

I have the following rule:

public class MailRangeValidator : AbstractValidator<MailsRangeModel>
{
    public MailRangeValidator()
    {
        RuleFor(x => x.SelectedFolders)
            .Must(x => x.Count() > 0)
            //.Must(coll => coll.Any(item => !string.IsNullOrWhiteSpace(item)))
            .WithMessage("At least one folder should be selected");
    }
}

and the following strings in the Program.cs:

builder.Services.AddFluentValidation();
builder.Services.AddTransient<IValidator<MailsRangeModel>, MailRangeValidator>();

property SelectedFolders is declared as:

    [BindProperty]
    public string[] SelectedFolders { get; set; }

and the following select element:

    <select asp-for="SelectedFolders" asp-items="Model.Folders" size="10"></select>

when I don't select any element (leave select as empty), on my OnPostShowDataAsync:

    public async Task<IActionResult> OnPostShowDataAsync()
    {
        if (!ModelState.IsValid)
        {
            return new PageResult();
        }

ModelState.IsValid is true. Why and how to fix it?

CodePudding user response:

AddFluentValidation must be called directly after calling AddMvc.

AddFluentValidation extension method inside the ConfigureServices method (which requires a using FluentValidation.AspNetCore). This method must be called directly after calling AddMvc.

builder.Services.AddMvc().AddFluentValidation();
builder.Services.AddTransient<IValidator<MailsRangeModel>, MailRangeValidator>();

CodePudding user response:

from documentation https://docs.fluentvalidation.net/en/latest/aspnet.html:

Configuration for use with ASP.NET Razor Pages and PageModels is exactly the same as with MVC above, but with the limitation that you can’t define a validator for the whole page-model, only for models exposed as properties on the page model.

so, problem is solved by the following way:

    private List<string> Validate()
    {
        MailRangeValidator validator = new MailRangeValidator();
        var result = validator.TestValidate(this);

        return result.Errors.Select(a => a.ErrorMessage).ToList();
    }

after it we check whether Errors exists, push it to ModelState and return to client:

        var errors = Validate();
        if (errors.Count > 0)
        {
            foreach (var error in errors)
            {
                ModelState.AddModelError("", error);
            }

            await FillDataAsync();
            return Page();
        }
  • Related