Skip to content

Validation Attributes Reference

Complete reference for all validation attributes in Pragmatic.Validation.Attributes.

All attributes are in the namespace Pragmatic.Validation.Attributes. They target AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter unless noted otherwise.

  1. Null values pass for all attributes except [Required]. Use [Required] to enforce non-null, then combine with other attributes for format/range checks.
  2. Types must be partial for the source generator to add the Validate() method (diagnostic PRAG0200).
  3. Custom message keys — Every attribute has a MessageKey property to override the default localization key: [Email(MessageKey = "custom.invalid_email")].
  4. Multiple attributes — You can stack multiple attributes on the same property. They are all checked in order.

Validates that a value is not null. For strings, also validates not empty (unless AllowEmptyStrings = true).

PropertyTypeDefaultDescription
AllowEmptyStringsboolfalseWhen true, empty strings are accepted.
MessageKeystring?nullCustom localization key.

Default message key: validation.required

Behavior by type:

  • string: null or empty string fails (unless AllowEmptyStrings = true).
  • Reference types: null fails.
  • Value types: always passes (they cannot be null).
  • required modifier: The SG treats C# required properties as having an implicit [Required] attribute.
[Required]
public string Email { get; init; } = "";
[Required(AllowEmptyStrings = true)]
public string Name { get; init; } = "";
[Required(MessageKey = "custom.email_required")]
public string Email { get; init; } = "";

Validates that a string has length > 0, or a collection has count > 0.

Default message key: validation.notempty

Works with: string, Array, ICollection, IEnumerable.

[Required]
[NotEmpty]
public List<OrderItem> Items { get; init; } = [];

Validates that a string is not null, empty, or whitespace only (spaces, tabs, newlines). Stricter than [Required] for strings — rejects " ".

Default message key: validation.notwhitespace

Non-string values always pass.

[NotWhiteSpace]
public string Content { get; init; } = "";

Validates minimum character count for strings, or minimum element count for collections/arrays.

ConstructorParameters
MinLength(int length)Minimum length/count (must be >= 0).

Default message key: validation.minlength

[MinLength(2)]
public string Name { get; init; } = "";
[MinLength(1)]
public List<string> Tags { get; init; } = [];

Validates maximum character count for strings, or maximum element count for collections/arrays.

ConstructorParameters
MaxLength(int length)Maximum length/count (must be >= 0).

Default message key: validation.maxlength

[MaxLength(100)]
public string Name { get; init; } = "";
[MaxLength(10)]
public List<string> Tags { get; init; } = [];

Combines [MinLength] and [MaxLength] into a single attribute. Validates that length/count is within the range (inclusive).

ConstructorParameters
Length(int minimumLength, int maximumLength)Both must be >= 0, minimum <= maximum.
PropertyTypeDescription
MinimumLengthintMinimum length/count.
MaximumLengthintMaximum length/count.

Default message key: validation.length

[Length(2, 100)]
public string Name { get; init; } = "";

Validates that a string is a valid email address format. Uses a practical regex pattern (not strict RFC 5322). Maximum 254 characters (per RFC). Compiled with a 250ms regex timeout (ReDoS protection).

Has a static IsValidEmail(string?) method used by the SG for inline validation.

Default message key: validation.email

[Required]
[Email]
public string Email { get; init; } = "";

Validates that a string is a valid phone number format. Accepts common formats including international (digits, spaces, hyphens, parentheses, optional leading +). Requires 7-15 digits.

Has a static IsValidPhone(string?) method.

Default message key: validation.phone

[Phone]
public string? PhoneNumber { get; init; }
// Valid: "+1 234 567-8900", "(234) 567-8900", "+39 02 1234567"

Validates that a string is a valid URL.

PropertyTypeDefaultDescription
AllowedSchemesstring[]?["http", "https"]Allowed URI schemes.
RequireAbsolutebooltrueWhether to require absolute URIs.

Has a static IsValidUrl(string?, string[]?, bool) method.

Default message key: validation.url

[Url]
public string? Website { get; init; }
[Url(AllowedSchemes = new[] { "http", "https", "ftp" })]
public string? FileUrl { get; init; }
[Url(RequireAbsolute = false)]
public string? RelativeLink { get; init; }

Validates that a string is a valid credit card number using the Luhn algorithm (ISO/IEC 7812-1). Accepts 13-19 digits. Spaces and hyphens are stripped before validation.

Has a static IsValidCreditCard(string?) method.

Default message key: validation.creditcard

[Required]
[CreditCard]
public string CardNumber { get; init; } = "";

Validates that a string matches a regular expression pattern. The regex is compiled with RegexOptions.Compiled | RegexOptions.CultureInvariant and a 250ms timeout.

Supports AllowMultiple = true — you can apply multiple [Regex] attributes to the same property.

ConstructorParameters
Regex(string pattern)The regex pattern (must not be null or empty).
PropertyTypeDescription
PatternstringThe regex pattern.

Default message key: validation.regex

[Regex(@"^[A-Z]{2}-\d{4}$")]
public string ProductCode { get; init; } = "";
[Regex(@"^\d{5}(-\d{4})?$", MessageKey = "validation.zipcode")]
public string ZipCode { get; init; } = "";

Validates that a string is a valid GUID format. Accepts standard formats: D (with hyphens), N (digits only), B (braces), P (parentheses).

Has a static IsValidGuid(string?) method.

Default message key: validation.guid

[Required]
[Guid]
public string ExternalId { get; init; } = "";

All numeric attributes support: int, long, short, byte, sbyte, uint, ulong, ushort, float, double, decimal.

Validates that a numeric value is within a specified range (inclusive on both ends).

ConstructorParameters
Range(int minimum, int maximum)Integer bounds.
Range(double minimum, double maximum)Double bounds.
PropertyTypeDescription
MinimumobjectMinimum value (inclusive).
MaximumobjectMaximum value (inclusive).

Default message key: validation.range

[Range(0, 100)]
public decimal Price { get; init; }
[Range(1, 1000)]
public int Quantity { get; init; }
[Range(0.0, 1.0)]
public double Percentage { get; init; }

Validates that a numeric value is greater than zero. Zero is NOT considered positive.

Default message key: validation.positive

[Required]
[Positive]
public decimal Amount { get; init; }

Validates that a numeric value is less than zero. Zero is NOT considered negative. Unsigned types always pass (they cannot be negative).

Default message key: validation.negative

[Negative]
public decimal Adjustment { get; init; }

Validates that a numeric value is strictly greater than the specified value.

ConstructorParameters
GreaterThan(int value)Integer bound.
GreaterThan(double value)Double bound.

Default message key: validation.greaterthan

[GreaterThan(0)]
public decimal DiscountPercent { get; init; }

Validates that a numeric value is greater than or equal to the specified value.

ConstructorParameters
GreaterThanOrEqual(int value)Integer bound.
GreaterThanOrEqual(double value)Double bound.

Default message key: validation.greaterthanorequal

[GreaterThanOrEqual(1)]
public int Quantity { get; init; }

Validates that a numeric value is strictly less than the specified value.

ConstructorParameters
LessThan(int value)Integer bound.
LessThan(double value)Double bound.

Default message key: validation.lessthan

[LessThan(150)]
public int Age { get; init; }

Validates that a numeric value is less than or equal to the specified value.

ConstructorParameters
LessThanOrEqual(int value)Integer bound.
LessThanOrEqual(double value)Double bound.

Default message key: validation.lessthanorequal

[LessThanOrEqual(100)]
public decimal DiscountPercent { get; init; }

Validates that a collection has at least the specified number of elements.

ConstructorParameters
MinCount(int count)Minimum element count (must be >= 0).

Works with: Array, ICollection, IEnumerable.

Default message key: validation.mincount

[Required]
[MinCount(1)]
public List<OrderItem> Items { get; init; } = [];

Validates that a collection does not exceed the specified number of elements.

ConstructorParameters
MaxCount(int count)Maximum element count (must be >= 0).

Default message key: validation.maxcount

[MaxCount(10)]
public List<string> Tags { get; init; } = [];

Combines [MinCount] and [MaxCount] into a single attribute.

ConstructorParameters
Count(int minimumCount, int maximumCount)Both must be >= 0, min <= max.
PropertyTypeDescription
MinimumCountintMinimum element count.
MaximumCountintMaximum element count.

Default message key: validation.count

[Required]
[Count(2, 10)]
public List<Guid> TeamMembers { get; init; } = [];

Indicates that each element in a collection should be validated individually. The element type must implement ISyncValidator (it must be a partial type with validation attributes).

This is NOT a ValidationAttribute — it is a standalone Attribute. The SG generates a loop that calls Validate() on each element. Error paths include the index: Items[0].ProductId.

PropertyTypeDefaultDescription
StopOnFirstErrorboolfalseStop at the first invalid element.

Diagnostics:

  • PRAG0204 (Warning): Applied to a non-collection type.
  • PRAG0205 (Error): Element type does not implement ISyncValidator.
public partial class OrderItemRequest
{
[Required]
public Guid ProductId { get; init; }
[Range(1, 100)]
public int Quantity { get; init; }
}
public partial class PlaceOrderRequest
{
[Required]
[NotEmpty]
[ValidateElements]
public List<OrderItemRequest> Items { get; init; } = [];
}
// Error path: "Items[0].ProductId", "Items[2].Quantity"

These attributes compare the decorated property against another property on the same type. They set RequiresInstance = true and use the IsValid(object?, object) overload.

At runtime, PropertyAccessorCache uses compiled expression tree delegates to access the other property’s value — no per-call reflection.

Diagnostic PRAG0203: Emitted as an error when the referenced property does not exist on the type. Diagnostic PRAG0209: Emitted as a warning when the two properties have incompatible types.

Validates that the property value equals another property’s value. Uses object.Equals(). Both null values are considered equal.

Default message key: validation.equalto

public partial class ChangePasswordRequest
{
[Required]
public string NewPassword { get; init; } = "";
[Required]
[EqualTo(nameof(NewPassword))]
public string ConfirmPassword { get; init; } = "";
}

Validates that the property value does NOT equal another property’s value. If either value is null, the comparison passes.

Default message key: validation.notequalto

public partial class ChangePasswordRequest
{
[Required]
public string CurrentPassword { get; init; } = "";
[Required]
[NotEqualTo(nameof(CurrentPassword))]
public string NewPassword { get; init; } = "";
}

Validates that the property value is greater than another property’s value. Both values must implement IComparable. Works with DateTime, DateTimeOffset, and numeric types.

Default message key: validation.greaterthanproperty

public partial class DateRangeRequest
{
[Required]
public DateTime StartDate { get; init; }
[Required]
[GreaterThanProperty(nameof(StartDate))]
public DateTime EndDate { get; init; }
}

Validates that the property value is less than another property’s value.

Default message key: validation.lessthanproperty

public partial class PriceRangeRequest
{
[Required]
[LessThanProperty(nameof(MaxPrice))]
public decimal MinPrice { get; init; }
[Required]
public decimal MaxPrice { get; init; }
}

[RequiredIf(otherPropertyName, expectedValue)]

Section titled “[RequiredIf(otherPropertyName, expectedValue)]”

Makes a property conditionally required when another property equals the expected value.

Supports AllowMultiple = true — multiple [RequiredIf] attributes on the same property.

ConstructorParameters
RequiredIf(string otherPropertyName, object? expectedValue)Property name and trigger value.
PropertyTypeDefaultDescription
OtherPropertyNamestringProperty to check.
ExpectedValueobject?Value that triggers the requirement.
AllowEmptyStringsboolfalseWhether empty strings are valid when required.

Default message key: validation.requiredif

public partial class PaymentRequest
{
[Required]
public PaymentMethod Method { get; init; }
[RequiredIf(nameof(Method), PaymentMethod.CreditCard)]
public string? CardNumber { get; init; }
[RequiredIf(nameof(Method), PaymentMethod.BankTransfer)]
public string? BankAccount { get; init; }
}

[RequiredIfNot(otherPropertyName, excludedValue)]

Section titled “[RequiredIfNot(otherPropertyName, excludedValue)]”

Makes a property conditionally required when another property does NOT equal the specified value.

Supports AllowMultiple = true.

ConstructorParameters
RequiredIfNot(string otherPropertyName, object? excludedValue)Property name and excluded value.
PropertyTypeDefaultDescription
OtherPropertyNamestringProperty to check.
ExcludedValueobject?Value that, when NOT present, triggers the requirement.
AllowEmptyStringsboolfalseWhether empty strings are valid when required.

Default message key: validation.requiredifnot

public partial class ContactRequest
{
public string? Email { get; init; }
// Phone is required when Email is NOT null (i.e., user provided email)
[RequiredIfNot(nameof(Email), null)]
public string? Phone { get; init; }
}
// Or: require Phone when ContactMethod is NOT Email
public partial class ContactRequest2
{
[Required]
public ContactMethod Method { get; init; }
[RequiredIfNot(nameof(Method), ContactMethod.Email)]
public string? Phone { get; init; }
}

Validates that a value is a defined member of an enum type. Prevents invalid values assigned through casting (e.g., (Status)999).

Has a static generic IsValidEnum<TEnum>(TEnum value) method.

Default message key: validation.enum

[Required]
[ValidEnum]
public OrderStatus Status { get; init; }

Validates that a value is one of a fixed set of allowed values. Uses object.Equals() for comparison.

ConstructorParameters
OneOf(params object[] allowedValues)The set of allowed values.
PropertyTypeDescription
AllowedValuesobject[]The allowed values.

Default message key: validation.oneof

[Required]
[OneOf("draft", "published", "archived")]
public string Status { get; init; } = "";

Validates that a DateTime or DateTimeOffset is in the future. Compares against DateTime.UtcNow / DateTimeOffset.UtcNow.

Default message key: validation.future_date

Note: Uses DateTime.UtcNow directly because ValidationAttribute.IsValid() does not support dependency injection. The generated code has the same limitation.

[Required]
[FutureDate]
public DateTimeOffset StartDate { get; init; }

Validates that a DateTime or DateTimeOffset is in the past.

Default message key: validation.past_date

Same DateTime.UtcNow limitation as [FutureDate].

[Required]
[PastDate]
public DateTime BirthDate { get; init; }

Marks a class as an async validator for DI auto-registration. Targets AttributeTargets.Class only.

PropertyTypeDefaultDescription
LifetimeServiceLifetimeScopedDI service lifetime.

The class must implement IAsyncValidator<T>. If it does not, diagnostic PRAG0201 is emitted.

[Validator]
public class CreateUserValidator : IAsyncValidator<CreateUserRequest> { ... }
[Validator(Lifetime = ServiceLifetime.Transient)]
public class ExpensiveValidator : IAsyncValidator<ComplexRequest> { ... }

Binds an async validator to a property or entity for change-aware invocation. Targets AttributeTargets.Property | AttributeTargets.Class. Supports AllowMultiple = true.

When applied to a property: the validator fires only when that property is modified. When applied to a class: the validator fires on any entity modification.

The SG generates IAsyncValidatorBindings<T> from these bindings.

// Property-level binding
public partial class User
{
[AsyncValidate<EmailUniquenessValidator>]
public string Email { get; private set; }
}
// Entity-level binding
[AsyncValidate<UserConsistencyValidator>]
public partial class User { ... }

CategoryAttributeParametersDefault Message Key
Presence[Required]AllowEmptyStringsvalidation.required
[NotEmpty]validation.notempty
[NotWhiteSpace]validation.notwhitespace
String[MinLength(n)]int lengthvalidation.minlength
[MaxLength(n)]int lengthvalidation.maxlength
[Length(min, max)]int min, int maxvalidation.length
Format[Email]validation.email
[Phone]validation.phone
[Url]AllowedSchemes, RequireAbsolutevalidation.url
[CreditCard]validation.creditcard
[Regex(pattern)]string patternvalidation.regex
[Guid]validation.guid
Numeric[Range(min, max)]int/double min, maxvalidation.range
[Positive]validation.positive
[Negative]validation.negative
[GreaterThan(n)]int/double valuevalidation.greaterthan
[GreaterThanOrEqual(n)]int/double valuevalidation.greaterthanorequal
[LessThan(n)]int/double valuevalidation.lessthan
[LessThanOrEqual(n)]int/double valuevalidation.lessthanorequal
Collection[MinCount(n)]int countvalidation.mincount
[MaxCount(n)]int countvalidation.maxcount
[Count(min, max)]int min, int maxvalidation.count
[ValidateElements]StopOnFirstErrorN/A
Comparison[EqualTo(prop)]string otherPropertyNamevalidation.equalto
[NotEqualTo(prop)]string otherPropertyNamevalidation.notequalto
[GreaterThanProperty(prop)]string otherPropertyNamevalidation.greaterthanproperty
[LessThanProperty(prop)]string otherPropertyNamevalidation.lessthanproperty
Conditional[RequiredIf(prop, value)]string prop, object? valuevalidation.requiredif
[RequiredIfNot(prop, value)]string prop, object? valuevalidation.requiredifnot
Extended[ValidEnum]validation.enum
[OneOf(values)]params object[] valuesvalidation.oneof
[FutureDate]validation.future_date
[PastDate]validation.past_date
DI[Validator]LifetimeN/A
Binding[AsyncValidate<T>]N/A