If you're using the MVC integration, then it takes place during the final stage of model binding after all the property values have been set, during System.Web.Mvc.DefaultModelBinder's OnModelUpdated method.
Jeremy
If you're using the MVC integration, then it takes place during the final stage of model binding after all the property values have been set, during System.Web.Mvc.DefaultModelBinder's OnModelUpdated method.
Jeremy
Hi
Although the top-level When method isn't available in FluentValidation 2.0, you can still call When as part of a rule chain. It just means you'd have to specify the condition multiple times.
Jeremy
Thanks for getting back, you're right, i figured it out but forgot to update the thread. Thanks for the response tho!
Thanks for the answer.
I want to return more than one error from custom validation. I'm using VS 2010 and MVC2. I'm calling Custom method from c'tor. It has different rules. If any one is broken it returns error. So far so good.
But, when there are 2 rules broken, user know only after two round trips. In first trip, 1st error message is displayed on the control and in 2nd trip second rule is displayed on the 2nd control. Because Custom method must exit with FluentValidation.Results.ValidationFailure on any rule broken. How to detect more than one error and display in the same round trip?
This issue with non sequential indices has bitten me again. It appears that the issue comes from the code in FluentValidation.Validators.ChildCollectionValidatorAdaptor.cs, lines 56-65.
When a child element is null it will attempt to slap an integer index on it disregarding the fact that this child could be using non sequential indices. As a result an error name will not match the data-valmsg-for attribute on the validation message span.
Even though I'm sure this is where the issue comes from, I'm not sure how to solve it. Jeremy, any ideas?
I'd like to be able to use chained validators, like this:
public class PersonValidator : AbstractValidator<Person> { public PersonValidator() { RuleFor(x => x.Forename).NotNull(); RuleFor(x => x.Address.Postcode).NotNull(); RuleFor(x => x.Address.Country.Name).NotNull(); RuleFor(x => x.Address.Line1).NotNull().When(x => x.Address.Line2 != null); } }
This mirrors the rules in the ComplexValidationTester unit tests. The reasons I want to do this aren't simply syntax, I have a few cases where there are multiple people in different "roles" as children of a common object and they have different validation based on their roles. There are enough of these that creating a new validator and using SetValidator for every role would be cumbersome. We already have about 110 validators in our application. This is really a great library, it's become a central part of our application framework.
While for the most part these chained validators work well, there are a couple of subtle problems I've found:
I'd like to send a pull request for these once I get them cleaned up and unit tests created.
The only problem I still have with how these chained rules work is the null checking. The SetValidator approach handles that very well, and I'd like this to look as clean, without having to put When(x => x.Address != null) on the above rules.
I appreciate any thoughts you might have.
Yes, I'm afraid I simply haven't had a chance to investigate this - I've not had time to do much with FluentValidation recently. The adaptor needs rewriting in order to support non-sequential indicies but I'm not going to be able to get around to this anytime soon. If you'd like to have a go at doing this yourself, please feel free to send me a pull request, otherwise it'll have to wait until next month at the earliest, sorry.
Jeremy
Hi,
Yes, please feel free to send a pull request for this. For the null checking, I'd prefer it left as-is - I like the null check to be explicit here, as it mirrors the behaviour of what would happen if you accessed the object instances directly (ie you'd have to check for nulls before accessing the member).
Jeremy
I am sure you are occupied with writing another super hit that will help us all tremendously. so can't complain. By the way, I'm really curious what you are working on this time. If it's not a secret, could you share?
I'll definitely give it a try to patch or rewrite ChildCollectionValidatorAdaptor, but not sure how much of a success I'll have there. I'll keep you posted in any case though.
Nothing open-source related I'm afraid...things at work and my personal life mean that I'm not spending as much time doing work on OSS projects anymore.
I would like the ability to create a class library that has generic rule structures that work on types like strings and business types like addresses etc that can then be added to a strongly typed fluentvalidator.
So if I have several classes that have 3 strings for Addresses I can inject those into classes that have address fields (which may be different names). That way I don't write the same code for address validation for example.
ufff, I'm really lost in the chain of events in FV. I understand that the only way to get info about indices is from ModelState. However ChildCollectionValidatorAdaptor does not have access to it and I'm not sure what actually triggers that Validate() method inside of it and how would I pass ModelState to it and whether I actually need to do it.. to summarize, I'm lost :)
If you find time, could you give me a very very general idea on what actually needs to be modified?
You're correct - the adaptor itself has no knowledge of ModelState (the core of FluentValidation is not coupled to MVC at all). I'd suggest starting by looking at FluentValidation's support for MVC Validation Interceptors: http://www.jeremyskinner.co.uk/2011/04/28/fluentvalidation-v3-asp-net-mvc-validation-interceptors/
These allow you to access the ControllerContext just prior to validation occuring. You might be able to use this to pass the modelstate to a custom adaptor.
Jeremy
Hello,
I have a case when I need to check whether a collection in view model has any objects in it. When validation fails I would like to display a model level error much like using
ModelState.AddModelError(string.Empty, "Big bad error")
instead of
ModelState.AddModelError("PropertyName", "Another error")
Quick look at documentation did not shed any light on this matter.
Hi
FluentValidation always associates error messages with properties (unless you're using the Custom method). Simplest thing to do would be to just add the message to ModelState manually.
Jeremy
Pull request sent.
For the null checking, I discovered the version of When that takes a lambda with multiple rules, so that cleans the syntax up quite a bit.
Thanks,
Dave
Is there a way to validate a rule set and specify properties?
I can see that you can do one or the other, but not both.
Hi
You should be able to write a custom validator selector that can do this. Example:
public class CompositeValidatorSelector : IValidatorSelector { readonly IValidatorSelector[] selectors; public CompositeValidatorSelector(params IValidatorSelector[] selectors) { this.selectors = selectors; } public bool CanExecute(IValidationRule rule, string propertyPath, ValidationContext context) { return selectors.Any(x => x.CanExecute(rule, propertyPath, context)); } }
...which could then be used like this:
var validator = new TestValidator(); validator.Validate(new Person(), selector: new CompositeValidatorSelector(new MemberNameValidatorSelector(new[] { "Property1", "Property2" }), new RulesetValidatorSelector("MyRuleSet")));
This isn't tested, but hopefully gives you a starting point.
Jeremy