Hi,

I'm looking for information on the new Validation Framework in version 5.0. I do not seem to be able to find any documentation on the subject.

Formerly we received the exception we threw ourselves. Now we get a ValidationFailedException.

We aggregate all exceptions in an AggregateException and in the end throw that. Is that stored somewhere else?

Regards Paul Sinnema

asked Sep 09 '14 at 08:55

Paul%20Sinnema's gravatar image

Paul Sinnema
261878896


One Answer:

Hello Paul.

Our validation framework changed a lot. We reworked it, because old validation used PostSharp and in 5.0 we refused PostSharp.

We tried to save some compatibility. But many things changed.

As in old validation, there are validators with same names:

  • EmailConstraint;
  • FutureConstraint;
  • NotEmptyConstraint;
  • NotNullConstraint;
  • NotNullOrEmptyConstraint;
  • PastConstraint;
  • PhoneNumberConstraint;
  • RangeConstraint;
  • RegexConstraint.

As in old framework, all they are attributes.

And we add new validators:

  • EntitySetFieldValidator;
  • StructureFieldValidator;
  • EntityValidator.

They are different kind of validator. They adds to EntitySets, Entities or Structures if descendants of these classes have overload of OnValidate() method.

Each validator, which is descendant of PropertyValidator, has property IsImmediate. If it sets to "true" than field with this constraint will validate directly after change. If you need to validate entity manually than you can use session.Validate() to validate changes of all entities in session or Entity.Validate() to validate concrete entity.

In old validation framework all constraints had a lot of properties. Now build-in constraints have minimal properties. They have only IsImmediate and ConstraintMode, actually. We saved ConstraintMode property for compatibility with old validation framework.

If you need more properties or more complicated logic then you can implement your own validator. For excample, you need different pattern of phone number


public class CustomPhoneNumberConstraint : PropertyValidator
{
  private const string PhoneNumberPattern = "<@Your own pattern of phone number@>"
  private static readonly Regex Validator = new Regex(PhoneNumberPattern);

public override void Configure(Domain domain, TypeInfo type, FieldInfo field) { base.Configure(domain, type, field); if (field.ValueType!=typeof (string)) ThrowConfigurationError(string.Format(Strings.FieldShouldBeOfTypeX, typeof (string).FullName)); }

public override ValidationResult Validate(Entity target, object fieldValue) { var value = (string) fieldValue; var isValid = string.IsNullOrEmpty(value) || Validator.IsMatch(value); return isValid ? Success() : Error("Phone number is incorrect", fieldValue); }

public override IPropertyValidator CreateNew() { return new CustomPhoneNumberConstraint { IsImmediate = IsImmediate, }; } }

Also we changed type of exception when validation failed. In old framework it was AgregateException. This exception included list of exceptions which throws during validation. Now we have ValidationFailedException. This exception orients only on validation, unlike AgregateException, which is used in other places.

ValidationFailedException stores information about all entities and their fields. We have list of EntityErrorInfo. Every instance in this list contains information about concrete entity which failed validation.

EntityErrorInfo contains Target and Errors properties. As you can guess, Target is Entity. Errors is list of validation errors associated with target entity. Each error contains information about

  • validator (see ValidationResult.Source);
  • field (see ValidationResult.Field);
  • value, which not pass validation (see ValidationResullt.Value);
  • error message (see ValidationResult.ErrorMessage).

Let's go forward.

In old validation framework we could override Validate() method of Persistent and implement custom validation of fields. If method threw some exception, then DO caught it and put it to list in AggregateException. It works now too, but now if DO catches exception from Validate() then it puts message of exception to ValidationResult.ErrorMesage. That's how EntitySetFieldValidator, StructureFieldValidator and EntityValidator works. If you need this kind of validation than you can override Validate() method of Persistent or EntitySetBase.

But in this case, in ValidationResult you can have only error message, validator and some times field.

I think it's more or less clear about new validation now.

answered Sep 10 '14 at 05:00

Alexey%20Kulakov's gravatar image

Alexey Kulakov
71715

Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×7

Asked: Sep 09 '14 at 08:55

Seen: 7,575 times

Last updated: Sep 10 '14 at 05:00

powered by OSQA