Skip to main content

String Methods

This page covers all string-related methods available in ValiFlow<T>. They are defined in StringExpression<TBuilder, T> and accessible directly from your ValiFlow<T> builder instance.

Examples: ValiFlow · Evaluators


Length

MinLength

Passes when the string has at least N characters. Returns false for null.

var rule = new ValiFlow<User>()
.MinLength(x => x.Name, 3);

MaxLength

Passes when the string has at most N characters. Returns true for null.

var rule = new ValiFlow<User>()
.MaxLength(x => x.Name, 100);

LengthBetween

Passes when the string length falls within the inclusive range [min, max].

var rule = new ValiFlow<User>()
.LengthBetween(x => x.Name, 3, 100);

ExactLength

Passes when the string is exactly N characters long.

var rule = new ValiFlow<Order>()
.ExactLength(x => x.PostalCode, 5);

Null / Empty / Whitespace

IsNullOrEmpty

Passes when the value is null or an empty string ("").

var rule = new ValiFlow<User>()
.IsNullOrEmpty(x => x.Description);

IsNotNullOrEmpty

Passes when the value is neither null nor "".

var rule = new ValiFlow<User>()
.IsNotNullOrEmpty(x => x.Name);

IsNullOrWhiteSpace

Passes when the value is null, "", or consists solely of whitespace characters.

var rule = new ValiFlow<Product>()
.IsNullOrWhiteSpace(x => x.Code);

IsNotNullOrWhiteSpace

Passes when the value contains at least one non-whitespace character.

var rule = new ValiFlow<Product>()
.IsNotNullOrWhiteSpace(x => x.Code);

IsTrimmed

Passes when the value has no leading or trailing whitespace (equivalent to value == value.Trim()). Returns true for null.

var rule = new ValiFlow<User>()
.IsTrimmed(x => x.Name);

Content

Contains (single selector)

Passes when the string contains the given substring. Defaults to StringComparison.OrdinalIgnoreCase.

// Case-insensitive (default)
var rule = new ValiFlow<Product>()
.Contains(x => x.Name, "test");

// Explicit comparison
var rule = new ValiFlow<Product>()
.Contains(x => x.Name, "test", StringComparison.Ordinal);

Note: string.Contains(string, StringComparison) is not EF Core translatable.

Contains (multi-selector)

Passes when the substring is found in any of the specified string properties (OR semantics). Uses ToLower() + single-argument Contains internally.

var rule = new ValiFlow<Product>()
.Contains("widget", x => x.Name, x => x.Description, x => x.Tags);

Note: In-memory only — not EF Core translatable.

StartsWith

Passes when the string begins with the given prefix. Uses OrdinalIgnoreCase by default.

var rule = new ValiFlow<Order>()
.StartsWith(x => x.Reference, "ORD");

EndsWith

Passes when the string ends with the given suffix. Uses OrdinalIgnoreCase by default.

var rule = new ValiFlow<User>()
.EndsWith(x => x.Email, ".com");

EqualsIgnoreCase

Passes when the string equals the target value, ignoring case (StringComparison.OrdinalIgnoreCase).

var rule = new ValiFlow<Product>()
.EqualsIgnoreCase(x => x.Code, "ABC");

IsUpperCase

Passes when every alphabetic character in the string is uppercase.

var rule = new ValiFlow<Product>()
.IsUpperCase(x => x.Code);

IsLowerCase

Passes when every alphabetic character in the string is lowercase.

var rule = new ValiFlow<Product>()
.IsLowerCase(x => x.Slug);

HasOnlyDigits

Passes when the string is non-empty and contains only digit characters (09).

var rule = new ValiFlow<User>()
.HasOnlyDigits(x => x.Pin);

HasOnlyLetters

Passes when the string is non-empty and contains only letter characters.

var rule = new ValiFlow<User>()
.HasOnlyLetters(x => x.Name);

HasLettersAndNumbers

Passes when the string contains at least one letter and at least one digit.

var rule = new ValiFlow<User>()
.HasLettersAndNumbers(x => x.Password);

HasSpecialCharacters

Passes when the string contains at least one character that is neither a letter nor a digit.


Mini Examples

1) Basic email + domain guard

var rule = new ValiFlow<User>()
.IsEmail(u => u.Email)
.EndsWith(u => u.Email, "@company.com");

2) Search across multiple fields (in-memory)

var rule = new ValiFlow<Product>()
.Contains("wireless", x => x.Name, x => x.Description, x => x.Tags);
var rule = new ValiFlow<User>()
.HasSpecialCharacters(x => x.Password);

Format Validators

⚠️ Timeout: All format validator methods use compiled Regex internally and will throw RegexMatchTimeoutException if the input causes catastrophic backtracking. Predefined pattern methods (IsEmail, IsUrl, etc.) have a 5-second timeout; RegexMatch has a 10-second timeout for user-supplied patterns. Wrap calls in try/catch if validating untrusted input.

All format validators use compiled regex patterns defined in RegularExpressions/RegularExpression.cs. They are evaluated in-memory.

IsEmail

Passes when the value matches a standard email format.

var rule = new ValiFlow<User>()
.IsEmail(x => x.Email);

IsUrl

Passes when the value is a valid HTTP/HTTPS URL.

var rule = new ValiFlow<User>()
.IsUrl(x => x.Website);

IsGuid

Passes when the value is a valid GUID string (with or without hyphens).

var rule = new ValiFlow<Order>()
.IsGuid(x => x.ExternalId);

IsPhoneNumber

Passes when the value matches an international or local phone number pattern.

var rule = new ValiFlow<User>()
.IsPhoneNumber(x => x.Phone);

IsJson

Passes when the value appears to be a valid JSON object or array (structural pattern check, not full parse).

var rule = new ValiFlow<Order>()
.IsJson(x => x.Payload);

NotJson

Passes when the value does not match the JSON pattern.

var rule = new ValiFlow<Order>()
.NotJson(x => x.Value);

IsBase64

Passes when the value is a valid Base64-encoded string.

var rule = new ValiFlow<User>()
.IsBase64(x => x.Token);

NotBase64

Passes when the value is not a valid Base64-encoded string.

var rule = new ValiFlow<Order>()
.NotBase64(x => x.Value);

IsCreditCard

Passes when the value matches a Luhn-compatible credit card number pattern (digits, optional spaces/hyphens).

var rule = new ValiFlow<Order>()
.IsCreditCard(x => x.CardNumber);

IsIPv4

Passes when the value is a valid IPv4 address (e.g., 192.168.1.1).

var rule = new ValiFlow<Order>()
.IsIPv4(x => x.IpAddress);

IsIPv6

Passes when the value is a valid IPv6 address.

var rule = new ValiFlow<Order>()
.IsIPv6(x => x.IpAddress);

IsHexColor

Passes when the value is a valid CSS hex color in #RGB or #RRGGBB format.

var rule = new ValiFlow<Product>()
.IsHexColor(x => x.Color);

IsSlug

Passes when the value contains only lowercase letters, digits, and hyphens (URL slug format).

var rule = new ValiFlow<Product>()
.IsSlug(x => x.UrlSlug);

Pattern Matching

RegexMatch

Passes when the value matches the provided regular expression pattern.

var rule = new ValiFlow<Order>()
.RegexMatch(x => x.PostalCode, @"^\d{5}$");

MatchesWildcard

Passes when the value matches a wildcard pattern where * means any sequence of characters and ? means exactly one character.

var rule = new ValiFlow<Order>()
.MatchesWildcard(x => x.FileName, "report_*.pdf");

Note: In-memory only — not EF Core translatable.

IsOneOf

Passes when the value exactly matches one of the entries in the provided list. An optional StringComparison parameter controls case sensitivity (defaults to OrdinalIgnoreCase).

var rule = new ValiFlow<User>()
.IsOneOf(x => x.Status, ["active", "inactive", "pending"]);

// Case-sensitive
var rule = new ValiFlow<User>()
.IsOneOf(x => x.Role, ["Admin", "Editor"], StringComparison.Ordinal);

Note: In-memory only — not EF Core translatable.


Combined Example

The following rule validates a User entity covering the most common string requirements:

var rule = new ValiFlow<User>()
.IsNotNullOrWhiteSpace(x => x.Name)
.MinLength(x => x.Name, 2)
.MaxLength(x => x.Name, 100)
.IsEmail(x => x.Email)
.IsOneOf(x => x.Role, ["admin", "editor", "viewer"])
.MinLength(x => x.Password, 8)
.HasLettersAndNumbers(x => x.Password);

bool isValid = rule.Evaluate(user);

// Or build the expression tree for use with LINQ
Expression<Func<User, bool>> expr = rule.Build();
var validUsers = dbContext.Users.Where(expr).ToList(); // only non-in-memory methods