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 (0–9).

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