Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I force a validation summary to appear with FluentValidation?

I've got FluentValidation set up in my ASP.Net MVC 3 project. I have a form which has two inputs. Either can be blank, but not both.

Here's what I have:

RuleFor(x => x.username)
    .NotEmpty()
    .When(x => string.IsNullOrEmpty(x.email) == true)
    .WithMessage("Please enter either a username or email address")

This correctly puts the error directly above my username field. However, when both fields are left blank I'd prefer the Validation Summary to show the message

Is there a way to do this? I've been thinking I could create an unused field in the model and put the error on that (if the other two are blank),

RuleFor(x => x.unused_field)
    .NotEmpty()
    .When(x => string.IsNullOrEmpty(x.email) == true && string.IsNullOrEmpty(x.username) == true)
    .WithMessage("Please enter either a username or email address")

but this feels like an awkward way to do it. Is there a way I can just add a message to the validation summary?

like image 367
roryok Avatar asked Feb 15 '23 17:02

roryok


2 Answers

The only reference I could find was this.

Now if your model is that simple and this rule is the only one then this rule should be enough:

RuleFor(x => x)
        .Must(x => !string.IsNullOrWhiteSpace(x.Email) || !string.IsNullOrWhiteSpace(x.UserName))
        .WithName(".") // This adds error message to MVC validation summary
        .WithMessage("Please enter either a username or email address");

Just add @Html.ValidationSummary() to your view and you're good to go.

But if you're going to put more rules on your model then to my knowledge there is only one 'hacky' way I could think of:
in your controller action add this:

if (!ModelState.IsValid)
{
    if (ModelState["."].Errors.Any())
    {
        ModelState.AddModelError(string.Empty, ModelState["."].Errors.First().ErrorMessage);
    }
    // ...
}

This will add first error message from "." property to model property (adapt it to your needs). Also you will have to do a @Html.ValidationSummary(true) to show only model level errors in validation summary.

Third option: add rule(s) to unused_property and use @Html.ValidationSummaryFor(x => x.unused_property) as a validation summary

like image 142
Ramunas Avatar answered Apr 27 '23 00:04

Ramunas


Your issue can be solved with FluentValidation AbstractValidator.Custom:

Custom(m => String.IsNullOrEmpty(m.Username) && String.IsNullOrEmpty(m.Email)
    ? new ValidationFailure("", "Enter either a username or email address.")
    : null);

Empty string in ValidationFailure constructor assures validation message is not bound to any input field so it appears in validation summary like

ModelState.AddModelError("", "Enter either a username or email address.")

would.

like image 45
Robertas Avatar answered Apr 27 '23 00:04

Robertas