Business Foundation Validators
First off, what is Business Foundation (BF)?
BF is basically a meta system where you can define an entity type and its properties. But it doesn’t stop there, the main differences between BF and the “regular” meta system in Commerce are that you can define relations between your meta classes, and that there’s a management UI you can extend and modify without changing any code. Sounds easy, but unfortunately not very well documented.
The management UI basically consists of views for displaying the data and forms for editing the data. Whenever an entity is saved, using the UI or using the api’s, the data is validated using a set of configurable properties and validators. So why implement you custom validation when it's right there in front of you, and used both by CM and all your application code.
Every meta class is represented in the mcmd_MetaClass table where the class level data is stored.
The field XSValidators contains XML data defining how the fields in a meta class should be validated. For each field you may define the validator implementation to use along with some validator specific properties.
Below is a partial sample from the Contact meta class.
<ArrayOfValidator xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Validator TypeName="Mediachase.BusinessFoundation.Data.GuidFieldValidator, Mediachase.BusinessFoundation.Data">
<Params FieldName="ContactId" AllowNull="False" />
<Validator TypeName="Mediachase.BusinessFoundation.Data.DateTimeFieldValidator, Mediachase.BusinessFoundation.Data">
<Params FieldName="Created" AllowNull="False" />
<Validator TypeName="Mediachase.BusinessFoundation.Data.StringFieldValidator, Mediachase.BusinessFoundation.Data">
<Params FieldName="FullName" AllowNull="False" MaxLength="200" />
<Validator TypeName="Mediachase.BusinessFoundation.Data.EnumFieldValidator, Mediachase.BusinessFoundation.Data">
<Params FieldName="CustomerGroup" AllowNull="True" EnumTypeName="ContactGroup" />
<Validator TypeName="Mediachase.BusinessFoundation.Data.ReferenceFieldValidator, Mediachase.BusinessFoundation.Data">
<Params FieldName="PreferredShippingAddressId" AllowNull="True" />
<Validator TypeName="Mediachase.BusinessFoundation.Data.BooleanFieldValidator, Mediachase.BusinessFoundation.Data">
<Params FieldName="MyCustomBool" AllowNull="True" />
As you see there are a variety of validator types, and not all properties can be managed in the Business Foundation management UI. Also, when setting up a large e-commerce project which might need deployments to several different environments we'd like to automate the setup of these validators but that's another story.
A validator is defined using ntype names and assemblies making it possible to create custom validators implementing IFieldValidator and IValidator. Yay :)
But first, let's take a look at the existing validators.
AllowNull is a parameter used in most validators and defines whether or not to accept a null value.
This validator is used to validate a string input.
Maxlength defines the maximum char length that may be input. Note that this is just a validator, make sure not to allow a string longer than you can actually store.
RegexPattern is a nifty property where you can define a regular expression to validate the input against.
For example, if you create a string field in the BF management UI and select the format "e-mail" the RegexPattern would be set to \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* which is in my opinion far too basic. Just pop in a new regex and you're all set :)
Other use cases could be to validate phone numbers, postal codes, allowed chars for name fields and so on. Also, there is no MinValue property so you could easily use the regex property for validating your minimum string length.
This validator is used to validate if the input is a valid guid. If the value can be parsed to a guid it's valid.
Validates if the value is of boolean type.
Validates if the value is of DateTime type, and checks the below properties if present.
MinValue - can be used to set the lowest allowed value
MaxValue - can be used to set the highest allowed value
For birth dates MinValue and MaxValue could be used to limit how young or old contacts that may be created, or if we would store for example a member date we wouldn't want to have dates from before the member system was created. If you would like to disallow dates in the future you could create your own validator and add a property for enabling/disabling future date validation.
Validates if the value is of decimal type. Not sure why it's been named CurrencyFieldValidator since it's just a basic decimal validator.
Works the same as the CurrencyFieldValidator but also has MinValue and MaxValue properties to limit the minimum and maximum value that may be entered.
Works the same as for decimal but validates if the value type is double. Also accepts MinValue and MaxValue.
Works the same as for decimal but validates if the value type is integer. Also accepts MinValue and MaxValue.
Validates if the value maps to a value in an enum meta field.
EnumTypeName is used to define which meta field to compare the input value with.
IsMultiValue defines whether or not multiple values may be input. If not accepting multiple values correct input type would be int or string, and for multiple values input types would be int and string
Validates if the value is of type FileInfo.
ValidationExpression property allows you to specify a regex to validate the file name againts.
This validator is a bit weird, it validates if the value is of type MetaIdentifierValue or of type string.
If the type is string any value is valid which makes me confused of the use case.
Validates if the value is a PrimaryKeyId