question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SetValidator inherited rulesets behavior

See original GitHub issue

Documentation explains the following:

Validating a specific ruleset with SetValidator Previously, if you defined a child validator with SetValidator, then whichever ruleset you invoked on the parent validator will cascade to the child validator. Now you can explicitly define which ruleset will run on the child:

RuleFor(x => x.Address).SetValidator(new AddressValidator(), "myRuleset");

From what I’ve just experienced, if I don’t explicitly set a ruleset when calling SetValidator(), the newly created validator (like AddressValidator in that example), will not contemplate any ruleset at all… This poses me a problem, because the previous behavior that “automatically inherited” the parent validator ruleset allowed me to not having to worry about passing any extra stuff if it wasn’t any different… How can I achieve the same functionality? As far as I can see, I can’t pass the current ruleset that my validator got passed from above so any new validator I create inside it, infers or inherits the same.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:12 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
JeremySkinnercommented, Sep 9, 2020

Would be great if I could have some context data that indicates the current ruleset it’s running

This is already present inside the ValidationContext, but this is only available when validation is executed, not at the point when rules are defined, so this wouldn’t really make sense. At the point the rules are defined, you haven’t invoked validate yet so the validator has no idea what you’re planning to execute.

If I explicitly set “RuleSet1” while instancing Validator3, it will always run under that ruleset when called from Validator2, no matter if Validator2 is being instanced by Validator1 or by some other validator (which it will, hence the problem).

That’s correct, but you can just define the call to SetValidator multiple times if you need to, depending on the scenario.

However, personally I think your setup is too complicated and hard to follow using rulesets like this (as illustrated by this discussion). I’d suggest you consider splitting these into separate classes and then being very explicit about what you’re running in each scenario. Ruleset cascade is complicated and it only gets more-so when you’re trying to customise it and override the default behaviour at multiple levels deep. This feels like it’s going to cause a huge maintenance headache if you continue down this route.

1reaction
JeremySkinnercommented, Aug 28, 2020

From my Controller, I’m invoking with no ruleset.

Well, that’s why. The rule for Field2 in Validator3 is explicitly wrapped in “RuleSet1”, but you’ve not included RuleSet1 for execution for validator3. The ruleset cascade only works if you’re actually triggering a ruleset. In your case you’re not running a ruleset, so the process runs like this:

  • No rulesets are included for execution, so only rules not in a ruleset will be run by default.
  • Validator1.Rule1 is encountered. This rule is not in a ruleset, so it will be executed.
    • Normally, only rules in Validator2 not in a ruleset will be run (as you haven’t specified a ruleset to execute)
    • However, as Validator2 has been instantiated with “RuleSet1” in the call to SetValidator, RuleSet1 will be invoked instead.
      • Validator2.Field1 is inside “RuleSet1”, so it will be executed
      • Validator2.Field2 is not inside a ruleset, so it won’t be executed
      • Validator2.Field3 is inside the wildcard ruleset, so it will be executed
        • Validator3 has been instantiated without a ruleset parameter, so only rules not in a ruleset will run.
          • Validator3.Field1 is not in a ruleset, so it will execute
          • Validator3.Field3 is in ruleset “RuleSet1” so it won’t execute

Because

If you want Validator3’s “RuleSet1” to execute, you need to specify it in the call to SetValidator, in the same way you did for the root validator. The cascading/automatic propogation of selected rulesets only applies if you’re actually executing a specific ruleset, which you’re not.

Essentially, because you’re not invoking a ruleset at the root level, only rules not in a ruleset will ever execute unless you override this in the SetValidator call, which you’re not doing for Validator3. I think you need to change it to this:

 RuleSet("*", () => {
    RuleForEach(x => x.Collection1)
       .SetValidator(new Validator3(), "RuleSet1");
    }
  }

If you do that, RuleSet1 will always be executed inside Validator3.

If you’re still having trouble understanding, please put together some runnable unit tests, and their expected result, and I will run them and show you what you need to change

Read more comments on GitHub >

github_iconTop Results From Across the Web

RuleSets have unexpected behavior for Sub-Validators #951
I've ran into some unexpected behavior while setting up some inherited validators. The issues are down in the BarValidator:.
Read more >
FluentValidation SetCollectionValidator for derived types
You can use conditional wrapping of rules to validate collection, which contains objects of different derived types.
Read more >
Creating your first validator
To define a set of validation rules for a particular object, you will need to create a class that inherits from AbstractValidator<T> ,...
Read more >
ValidatorAttribute Class
A ruleset can be specified for the attribute, as well as message overrides (either literal or resource based). Inheritance Hierarchy. System.
Read more >
MethodValidationConfiguration (Hibernate Validator 8.0.1. ...
These properties modify the behavior of the Validator with respect to the Jakarta Bean Validation specification section 5.6.5. In particular:
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found