Skip to content

Validation codes ​

Every error has a Code. The built-in codes are constants on ValidationCodes, and they are part of the public API, so application logic and translations can depend on them.

Built-in codes ​

ConstantValueReported by
ValidationCodes.Requiredrequired[Required], Require, RequireAllowingEmpty
ValidationCodes.StringLengthstring_length[StringLength], Length, and [MinLength], [MaxLength] and [Length] on strings
ValidationCodes.ArrayBoundsarray_bounds[ItemCount], Count, and [MinLength], [MaxLength] and [Length] on collections
ValidationCodes.Rangerange[Range], Range, RangeAtLeast, RangeAtMost
ValidationCodes.MultipleOfmultiple_of[MultipleOf], MultipleOf
ValidationCodes.Patternpattern[Pattern], Pattern, [RegularExpression]
ValidationCodes.Enumenum[AllowedValues], [DeniedValues], [EnumDefined], AllowedValues
ValidationCodes.UniqueItemsunique_items[UniqueItems], Unique
ValidationCodes.Emailemail[EmailAddress]
ValidationCodes.Phonephone[Phone]
ValidationCodes.Urlurl[Url]
ValidationCodes.CreditCardcredit_card[CreditCard]
ValidationCodes.Base64base64[Base64String]
ValidationCodes.FileExtensionfile_extension[FileExtensions]
ValidationCodes.CustomcustomA CustomConstraintAttribute or IConstraintFor<T> attribute without its own code, a custom DataAnnotations ValidationAttribute, [CustomValidation], and IValidatableObject
ValidationCodes.PredicatepredicateAn Ensure whose condition yields no code of its own
ValidationCodes.InvalidinvalidNothing in this library. It is reserved for a value that could not be converted to the property's type, such as text in a number field, when a request binder reports it.

The same attributes in ValidationModules.Constraints and in System.ComponentModel.DataAnnotations report the same codes. A Report helper, such as ReportRange, reports the code of its check unless it is given a code: argument.

Codes from Ensure ​

An Ensure in a rules class without code: gets a code derived from its condition. The members are written in snake_case from their C# names, so a [JsonPropertyName] changes the message of an Ensure and not its code. The operators are written as words:

ConditionCode
x.Start < x.Endstart_less_than_end
x.End > x.Startend_greater_than_start
x.Age >= 18age_greater_than_or_equal_18
x.Paid && x.Shippedpaid_and_shipped
!x.Cancellednot_cancelled
x.Name != nullname_is_not_null
!string.IsNullOrEmpty(x.Name)name_is_not_null_or_empty
x.Items.Count > 0items_is_not_empty
x.Status == "active"status_equal_active
x.Total - x.Paid > 0total_minus_paid_greater_than_0

Changing the condition changes the code. A local variable in the condition appears in the code under its own name, so renaming the variable changes the code too. In a generic fragment, a type parameter appears under its own name as well, as in typeof(T).Name, so every type the fragment is expanded for reports the same code. The generator reports each derived code as VM3103, an informational diagnostic. Pass code: to fix the code when clients depend on it. When nothing can be derived, the code is predicate.

The rules for deriving codes are versioned in the runtime, and they change only in a major release. An update to the library does not change the code of a condition you have not edited.

Your own codes ​

Code on a constraint attribute, code: on Ensure, and the code argument of a Report call or helper set your own codes. Language packs can translate them like built-in codes.

ValidationModules_CodeNamespace adds a prefix to the codes the generator sees: Code on a built-in attribute, a CustomConstraintAttribute or an IConstraintFor<T> attribute, the DefaultCode of a CustomConstraintAttribute, and the code of an Ensure, set or derived. Codes passed to Report calls, in a hand-written validator, an IConstraintFor<T> attribute's own Validate or through rules.Context, are not prefixed.

xml
<PropertyGroup>
  <ValidationModules_CodeNamespace>shop</ValidationModules_CodeNamespace>
</PropertyGroup>

With this setting, code: "stay_order" reports shop.stay_order. Built-in codes are never prefixed.

Released under the MIT License.