Search code examples
c#asp.net-mvcviewmodelfluentvalidation

Add child property failure to child


I'm new with FluentValidation.

I have two classes

public class A
{
    public B Prop { get; set; }
}

public class B 
{
    public decimal? Example { get; set; }
    public decimal? Example2 { get; set; }
}

And, i'm trying to validate B property inside A class.

If any property of Prop has validation error, i want set the first of the errors to prop object.

I'm trying some like this.

public class A : AbstractValidator<A>{    
    public A()
    {
        RuleFor(x => x.Prop.Example).NotEmpty();
        RuleFor(x => x.Prop.Example2).NotEmpty();
        RuleFor(x => x.Prop).Custom((obj,context) => {
            if(/* obj.Example or obj.Example2 has validation error */){
                context.AddFailure("message of any Example or Example2 errors");
            }
        });
    }
}

Edit: some example of my view

<div class="col-12 col-lg-6">
    @Html.LabelFor(x => x.Prop, new { @class = "col-form-label" })
    <div class="input-group mb-3">
        @Html.EditorFor(x => x.Prop.Example, new { htmlAttributes = new { @class = "form-control" } })
        <div class="input-group-append">
            <span class="input-group-text">%</span>
            <span class="input-group-text">@@</span>
        </div>
        @Html.EditorFor(x => x.Prop.Example2, new { htmlAttributes = new { @class = "form-control" } })
        <div class="input-group-append">
            <span class="input-group-text">KVA</span>
        </div>
        <div class="invalid-feedback">@Html.ValidationMessageFor(x => x.Prop)</div>
    </div>
</div>

It should display some like this

enter image description here

Where the left input is Example, and the right one is Example 2.

So, if any of that both fail, the error message should be seen down (ValidationMessageFor)

I dont know how to validate Prop property errors inside a RuleFor

Is it possible this way? How can i do it?


Solution

  • You could probably get this working, but you might have an easier time by creating a validator for class B and then putting both validation messages in the UI right next to each other:

    <div class="col-12 col-lg-6">
        @Html.LabelFor(x => x.Prop, new { @class = "col-form-label" })
        <div class="input-group mb-3">
            @Html.EditorFor(x => x.Prop.Example, new { htmlAttributes = new { @class = "form-control" } })
            <div class="input-group-append">
                <span class="input-group-text">%</span>
                <span class="input-group-text">@@</span>
            </div>
            @Html.EditorFor(x => x.Prop.Example2, new { htmlAttributes = new { @class = "form-control" } })
            <div class="input-group-append">
                <span class="input-group-text">KVA</span>
            </div>
            <div class="invalid-feedback">
                @* Validation messages for both properties of class "B" *@
                @Html.ValidationMessageFor(x => x.Prop.Example)
                @Html.ValidationMessageFor(x => x.Prop.Example2)
            </div>
        </div>
    </div>