Common.NET-Validation-Framework
2.0.2
dotnet add package Common.NET-Validation-Framework --version 2.0.2
NuGet\Install-Package Common.NET-Validation-Framework -Version 2.0.2
<PackageReference Include="Common.NET-Validation-Framework" Version="2.0.2" />
<PackageVersion Include="Common.NET-Validation-Framework" Version="2.0.2" />
<PackageReference Include="Common.NET-Validation-Framework" />
paket add Common.NET-Validation-Framework --version 2.0.2
#r "nuget: Common.NET-Validation-Framework, 2.0.2"
#:package Common.NET-Validation-Framework@2.0.2
#addin nuget:?package=Common.NET-Validation-Framework&version=2.0.2
#tool nuget:?package=Common.NET-Validation-Framework&version=2.0.2
C# Simple Validation Framework
A lightweight, flexible, and extensible validation framework for .NET applications. This framework provides a clean and intuitive way to validate various data types with customizable rules and detailed error reporting.
What's New in Version 2.0
- โจ Async Validation Support: New
AsyncValidator<T>class withAddAsyncRulemethod for asynchronous validation - ๐ New Validators: Added 50+ new built-in validators covering common scenarios:
- Identifiers: GUID, UUID, SSN, CVV, Credit Card Expiry
- Network: IP Address (IPv4/IPv6), Domain, URL, JWT, API Key
- Files: File Extension, MIME Type
- Versioning: Semantic Version
- Codes: Currency Code, Language Code, Country Code, Postal Code
- Location: Latitude, Longitude, Coordinates, Time Zone
- Text: Letters Only (with Unicode support), Slug
- Security: Strong Password (customizable requirements)
- Colors: Color codes (Hex, RGB, RGBA, HSL, HSLA)
- International: International Phone, Postal Codes by Country
- ๐ Improved CI/CD: Updated GitHub Actions workflow to .NET 9.0 with automatic NuGet package generation
- ๐ฆ Better Packaging: Enhanced NuGet package configuration with symbols and source link support
- ๐งช More Tests: Comprehensive test coverage for all new features (100+ tests)
Table of Contents
- What's New in Version 2.0
- Documentation
- Features
- Installation
- Quick Start
- Usage Examples
- Async Validation
- .NET Ecosystem Compatibility
- Built-in Validators
- Additional Validators
- Creating Custom Validators
- Validation Results
- Advanced Usage
- Best Practices
- Contributing
- License
Features
- โจ Fluent API for building validation rules
- ๐ฏ Type-safe validation
- ๐ Detailed error reporting
- ๐ง Easily extensible
- ๐๏ธ 70+ built-in validators for common scenarios
- ๐ Chainable validation rules
- ๐ Field-specific error tracking
- โก Async validation support with
AsyncValidator<T> - ๐งฉ Full .NET Ecosystem Compatibility: ASP.NET Core, WPF, Windows Forms, Blazor, and .NET MAUI
- ๐จ Clean and maintainable code structure
- ๐งช Comprehensive test coverage (120+ tests)
- ๐ฆ NuGet package ready
Documentation
Comprehensive documentation is available for this framework:
๐ Online Documentation
- Documentation Site - Complete documentation with API reference (deployed via GitHub Pages)
- API Reference - Auto-generated API documentation
๐ Documentation Generation
This project uses DocFX (Microsoft's documentation generator) for automatic documentation generation:
- XML Documentation: Built-in .NET feature, generates IntelliSense docs
- DocFX: Generates static documentation website
- GitHub Actions: Automatically builds and deploys documentation
- GitHub Pages: Hosts the live documentation site
To generate documentation locally:
# Install DocFX
dotnet tool install -g docfx
# Build project (generates XML docs)
dotnet build ValidationFramework/ValidationFramework.csproj -c Release
# Generate documentation
docfx docfx.json
# View locally
docfx docfx.json --serve
Documentation Structure:
๐ docs/
โโโ index.md # Home page
โโโ toc.yml # Table of contents
โโโ docfx.json # DocFX configuration
โโโ articles/ # Conceptual documentation
โโโ overview.md
โโโ installation.md
โโโ quick-start.md
โโโ ...
See DOCS.md for detailed documentation setup information.
Installation
- Clone the repository or copy the
ValidationFrameworknamespace files into your project. - Add the following using statement to your code:
using ValidationFramework;
NuGet Package
Install via NuGet Package Manager:
Install-Package Common.NET-Validation-Framework
Or via .NET CLI:
dotnet add package Common.NET-Validation-Framework
Source Code
Alternatively, include the source files directly in your project:
- Copy all files from
ValidationFramework/directory - Add to your project
- Ensure
ValidationFramework.csprojsettings are applied
Quick Start
Here's a simple example to get you started:
// Create a validator for an email field
var emailValidator = CommonValidators.EmailValidator();
// Validate an email
var result = emailValidator.Validate("john.doe@example.com");
if (result.IsValid)
{
Console.WriteLine("Email is valid!");
}
else
{
foreach (var error in result.Errors)
{
Console.WriteLine($"Error: {error}");
}
}
Usage Examples
Basic Field Validation
// Email validation
var emailValidator = CommonValidators.EmailValidator();
var emailResult = emailValidator.Validate("john.doe@example.com");
// Name validation
var nameValidator = CommonValidators.NameValidator(minLength: 2, maxLength: 50);
var nameResult = nameValidator.Validate("John");
// Phone validation
var phoneValidator = CommonValidators.PhoneValidator(requiredLength: 10);
var phoneResult = phoneValidator.Validate("1234567890");
WinForms (ErrorProvider)
var result = validator.ValidateProfile(profile);
errorProvider.SetError(emailTextBox, result.GetFirstFieldError("Email") ?? string.Empty);
WPF (INotifyDataErrorInfo)
var result = validator.ValidateProfile(profile);
var emailErrors = result.GetFieldErrors(nameof(UserProfile.Email));
ASP.NET Core (ModelState)
var result = validator.ValidateProfile(profile);
foreach (var entry in result.ToErrorDictionary())
{
foreach (var error in entry.Value)
{
ModelState.AddModelError(entry.Key, error);
}
}
Complex Object Validation
public class UserProfile
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string Password { get; set; }
public string Website { get; set; }
public DateTime DateOfBirth { get; set; }
public decimal Salary { get; set; }
}
var validator = new UserProfileValidator();
var profile = new UserProfile
{
Email = "john.doe@example.com",
FirstName = "John",
LastName = "Doe",
PhoneNumber = "1234567890",
Password = "Secure@123",
Website = "https://example.com",
DateOfBirth = new DateTime(1990, 1, 1),
Salary = 50000.00m
};
var result = validator.ValidateProfile(profile);
Built-in Validators
RequiredValidator
var required = CommonValidators.RequiredValidator(fieldName: "DisplayName");
// Validates:
// - Required field
LengthValidator
var length = CommonValidators.LengthValidator(minLength: 3, maxLength: 20, fieldName: "DisplayName");
// Validates:
// - Minimum length (empty values are invalid when minLength > 0)
// - Maximum length (optional)
// - Use RequiredValidator for required fields when minLength is 0
RegexValidator
var regex = CommonValidators.RegexValidator(@"^\d{3}$", "Must be 3 digits", "Code");
// Validates:
// - Regex pattern match (skips empty values)
RangeValidator
var range = CommonValidators.RangeValidator(minValue: 1, maxValue: 10, fieldName: "Rating");
// Validates:
// - Value range
EmailValidator
var emailValidator = CommonValidators.EmailValidator();
// Validates:
// - Required field
// - Email format
NameValidator
var nameValidator = CommonValidators.NameValidator(
minLength: 2,
maxLength: 50,
fieldName: "FirstName"
);
// Validates:
// - Required field
// - Length constraints
// - Valid characters (letters, spaces, hyphens, apostrophes)
PhoneValidator
var phoneValidator = CommonValidators.PhoneValidator(
requiredLength: 10,
fieldName: "Phone"
);
// Validates:
// - Required field
// - Numeric characters only
// - Exact length
PasswordValidator
var passwordValidator = CommonValidators.PasswordValidator();
// Validates:
// - Minimum length (8 characters)
// - Contains uppercase letter
// - Contains lowercase letter
// - Contains number
// - Contains special character
UrlValidator
var urlValidator = CommonValidators.UrlValidator();
// Validates:
// - Required field
// - Valid URL format
DateValidator
var dateValidator = CommonValidators.DateValidator(
minDate: DateTime.Now.AddYears(-120),
maxDate: DateTime.Now.AddYears(-18)
);
// Validates:
// - Date range
CurrencyValidator
var currencyValidator = CommonValidators.CurrencyValidator(
minValue: 0,
maxValue: 1000000
);
// Validates:
// - Non-negative amounts
// - Maximum 2 decimal places
// - Value range
ZipCodeValidator
var zipValidator = CommonValidators.ZipCodeValidator();
// Validates:
// - US ZIP code format (12345 or 12345-6789)
// - Required field
AlphanumericValidator
var alphanumericValidator = CommonValidators.AlphanumericValidator(
minLength: 3,
maxLength: 20
);
// Validates:
// - Letters and numbers only
// - Length constraints
// - Required field
IpAddressValidator
var ipValidator = CommonValidators.IpAddressValidator();
// Validates:
// - IPv4 address format
// - Required field
UsernameValidator
var usernameValidator = CommonValidators.UsernameValidator(
minLength: 3,
maxLength: 20
);
// Validates:
// - Must start with a letter
// - Letters, numbers, underscores, hyphens allowed
// - Length constraints
// - Required field
CreditCardValidator
var cardValidator = CommonValidators.CreditCardValidator();
// Validates:
// - Credit card number format (13-19 digits)
// - Luhn algorithm checksum
// - Accepts spaces and hyphens
// - Required field
PostalCodeValidator
var postalValidator = CommonValidators.PostalCodeValidator();
// Validates:
// - Canadian postal code format (A1A 1A1)
// - Required field
HexColorValidator
var colorValidator = CommonValidators.HexColorValidator();
// Validates:
// - Hexadecimal color code format (#RRGGBB or #RGB)
// - Required field
Additional Validators
GuidValidator
var guidValidator = CommonValidators.GuidValidator();
// Validates:
// - GUID is not empty
GuidStringValidator
var guidStringValidator = CommonValidators.GuidStringValidator();
// Validates:
// - String is a valid GUID format
// - Required field
EnumValidator
// With explicit values
var enumValidator = CommonValidators.EnumValidator(new[] { "A", "B", "C" });
// With actual enum type
var colorValidator = CommonValidators.EnumValidator<ConsoleColor>();
// Validates:
// - Value is one of the allowed enum values
UuidValidator
var uuidValidator = CommonValidators.UuidValidator();
// Validates:
// - String is a valid UUID (version 1-5)
// - Required field
IsbnValidator
var isbnValidator = CommonValidators.IsbnValidator();
// Validates:
// - ISBN-10 or ISBN-13 format
// - Required field
MacAddressValidator
var macValidator = CommonValidators.MacAddressValidator();
// Validates:
// - MAC address format (00:1A:2B:3C:4D:5E or 00-1A-2B-3C-4D-5E)
// - Required field
TimeValidator
var timeValidator = CommonValidators.TimeValidator();
// Validates:
// - Time format (HH:mm or HH:mm:ss)
// - Required field
JsonValidator
var jsonValidator = CommonValidators.JsonValidator();
// Validates:
// - Valid JSON format
// - Required field
Base64Validator
var base64Validator = CommonValidators.Base64Validator();
// Validates:
// - Valid Base64 encoded string
// - Required field
FilePathValidator
var filePathValidator = CommonValidators.FilePathValidator();
// Validates:
// - Valid file path (no invalid characters)
// - Required field
NullValidator / NotNullValidator
var nullValidator = CommonValidators.NullValidator<string>();
var notNullValidator = CommonValidators.NotNullValidator<string>();
// Validates:
// - Value is null (or not null)
ConfirmValidator
var confirmValidator = CommonValidators.ConfirmValidator(originalValue, "Confirmation");
// Validates:
// - Value matches the original value
// - Required field
EmptyValidator / NotEmptyValidator
var emptyValidator = CommonValidators.EmptyValidator();
var notEmptyValidator = CommonValidators.NotEmptyValidator();
// Validates:
// - Value is empty (or not empty)
Network Validators
InternationalPhoneValidator
var phoneValidator = CommonValidators.InternationalPhoneValidator(allowCountryCode: true);
// Validates:
// - International phone numbers with or without country code
// - Format: +1-555-123-4567 or 5551234567
IpAddressValidator
// Validate IPv4 only
var ipv4Validator = CommonValidators.IpAddressValidator(allowIPv4: true, allowIPv6: false);
// Validate IPv6 only
var ipv6Validator = CommonValidators.IpAddressValidator(allowIPv4: false, allowIPv6: true);
// Validate either
var ipValidator = CommonValidators.IpAddressValidator();
// Validates:
// - IPv4 addresses (e.g., 192.168.1.1)
// - IPv6 addresses (e.g., 2001:0db8:85a3:0000:0000:8a2e:0370:7334)
DomainValidator
var domainValidator = CommonValidators.DomainValidator(allowSubdomains: true, requireTld: true);
// Validates:
// - Domain names (e.g., example.com)
// - Optional subdomains (e.g., www.example.com)
// - Optional TLD requirement
StrictUrlValidator
var urlValidator = CommonValidators.StrictUrlValidator(requireHttps: true, allowLocalhost: false);
// Validates:
// - Absolute URLs
// - Optional HTTPS requirement
// - Optional localhost allowance
// - Valid TLD requirement
JwtValidator
var jwtValidator = CommonValidators.JwtValidator(validateExpiry: false);
// Validates:
// - JWT format (header.payload.signature)
// - Optional expiry validation
ApiKeyValidator
var apiKeyValidator = CommonValidators.ApiKeyValidator(minLength: 32, maxLength: 128);
// Validates:
// - API key length constraints
// - Alphanumeric characters, hyphens, underscores, and periods
Identifier Validators
SsnValidator
var ssnValidator = CommonValidators.SsnValidator();
// Validates:
// - US Social Security Number format
// - Formats: XXX-XX-XXXX, XXX XX XXXX, or XXXXXXXXX
CvvValidator
var cvvValidator = CommonValidators.CvvValidator(CreditCardType.AmericanExpress);
// Validates:
// - Credit card CVV/CVC codes
// - Card-type specific length requirements (Amex: 4 digits, others: 3-4 digits)
CreditCardExpiryValidator
var expiryValidator = CommonValidators.CreditCardExpiryValidator();
// Validates:
// - Credit card expiration dates
// - Formats: MM/YY, MM/YYYY, MM-YY, MM-YYYY
// - Ensures date is in the future
File Validators
FileExtensionValidator
var extValidator = CommonValidators.FileExtensionValidator(new[] { "jpg", "png", "gif" }, caseSensitive: false);
// Validates:
// - File has one of the allowed extensions
// - Optional case sensitivity
MimeTypeValidator
var mimeValidator = CommonValidators.MimeTypeValidator();
// Validates:
// - MIME type format (type/subtype)
// - Examples: text/plain, image/jpeg, application/json
Versioning Validators
SemanticVersionValidator
var semverValidator = CommonValidators.SemanticVersionValidator();
// Validates:
// - Semantic version format (Major.Minor.Patch)
// - Optional prerelease and build metadata
// - Examples: 1.0.0, 1.2.3-beta.1, 2.0.0+build.123
Code Validators
CurrencyCodeValidator
var currencyValidator = CommonValidators.CurrencyCodeValidator();
// Validates:
// - ISO 4217 currency codes
// - Format: 3 uppercase letters (e.g., USD, EUR, GBP)
LanguageCodeValidator
var langValidator = CommonValidators.LanguageCodeValidator();
// Validates:
// - ISO 639-1 language codes
// - Formats: 2-letter code (e.g., en, fr) or with region (e.g., en-US, fr-FR)
CountryCodeValidator
var countryValidator = CommonValidators.CountryCodeValidator(allowAlpha3: true);
// Validates:
// - ISO 3166-1 country codes
// - 2-letter (e.g., US, GB) or 3-letter (e.g., USA, GBR) codes
PostalCodeValidator
var postalValidator = CommonValidators.PostalCodeValidator("US");
// Validates:
// - Country-specific postal code formats
// - Supports: US, CA, GB, DE, FR, IT, AU, NL, ES, SE, CH, JP, IN, BR, RU, CN, MX, AR, ZA, NZ
// - Generic validation for unsupported countries
Location Validators
LatitudeValidator
var latValidator = CommonValidators.LatitudeValidator();
// Validates:
// - Latitude coordinates between -90 and 90
// - Supports decimal degrees
LongitudeValidator
var lonValidator = CommonValidators.LongitudeValidator();
// Validates:
// - Longitude coordinates between -180 and 180
// - Supports decimal degrees
CoordinatesValidator
var coordsValidator = CommonValidators.CoordinatesValidator(", ");
// Validates:
// - Coordinate pairs (latitude, longitude)
// - Customizable separator
// - Example: "40.7128, -74.0060"
TimeZoneValidator
var tzValidator = CommonValidators.TimeZoneValidator();
// Validates:
// - Time zone identifiers
// - Formats: UTC offset (e.g., UTC-5, GMT+3) or IANA (e.g., America/New_York)
Text Validators
LettersOnlyValidator
var lettersValidator = CommonValidators.LettersOnlyValidator(
allowSpaces: true,
allowHyphens: true,
allowApostrophes: true);
// Validates:
// - Strings containing only Unicode letters
// - Optional spaces, hyphens, and apostrophes
// - Supports accented characters (e.g., Cafรฉ, O'Brien)
SlugValidator
var slugValidator = CommonValidators.SlugValidator(maxLength: 100, allowUnderscores: false);
// Validates:
// - URL-friendly slugs
// - Lowercase letters, numbers, and hyphens
// - Optional underscores
// - Optional maximum length
Security Validators
StrongPasswordValidator
var strongPasswordValidator = CommonValidators.StrongPasswordValidator(
minLength: 8,
requireUppercase: true,
requireLowercase: true,
requireNumber: true,
requireSpecial: true,
maxConsecutiveChars: 2);
// Validates:
// - Minimum length
// - Character type requirements (uppercase, lowercase, numbers, special)
// - Maximum consecutive identical characters
// - Fully customizable requirements
Color Validators
ColorValidator
var colorValidator = CommonValidators.ColorValidator();
// Validates:
// - Hex colors: #RRGGBB or #RGB
// - RGB: rgb(255, 255, 255)
// - RGBA: rgba(255, 255, 255, 0.5)
// - HSL: hsl(120, 50%, 50%)
// - HSLA: hsla(120, 50%, 50%, 0.5)
Creating Custom Validators
You can create custom validators by extending the base Validator<T> class:
public static Validator<string> CustomValidator()
{
return new Validator<string>("CustomField")
.AddRule(value => !string.IsNullOrEmpty(value), "Value is required")
.AddRule(value => // your custom rule, "Your error message");
}
Validation Results
The ValidationResult class provides detailed information about validation results:
public class ValidationResult
{
public bool IsValid { get; set; }
public List<string> Errors { get; }
public Dictionary<string, List<string>> FieldErrors { get; }
}
Helper methods are available for UI integration:
var errors = result.GetFieldErrors("Email");
var firstError = result.GetFirstFieldError("Email");
Handling Validation Results
var result = validator.ValidateProfile(profile);
if (!result.IsValid)
{
// Access general errors
foreach (var error in result.Errors)
{
Console.WriteLine($"Error: {error}");
}
// Access field-specific errors
foreach (var fieldErrors in result.FieldErrors)
{
Console.WriteLine($"Field: {fieldErrors.Key}");
foreach (var error in fieldErrors.Value)
{
Console.WriteLine($" - {error}");
}
}
}
Async Validation
The framework now supports asynchronous validation with the AsyncValidator<T> class. This is useful when you need to perform async operations like database lookups, API calls, or file system checks during validation.
Basic Async Validation
// Create an async validator
var validator = new AsyncValidator<string>("Username")
.AddRule(value => !string.IsNullOrEmpty(value), "Username is required")
.AddAsyncRule(async value => await IsUsernameAvailableAsync(value), "Username is already taken");
// Validate asynchronously
var result = await validator.ValidateAsync("john_doe");
if (result.IsValid)
{
Console.WriteLine("Username is available!");
}
// Helper async method
private async Task<bool> IsUsernameAvailableAsync(string username)
{
// Simulate async database check
await Task.Delay(100);
return username != "admin";
}
Mixed Sync and Async Rules
var validator = new AsyncValidator<string>("Email")
.AddRule(value => !string.IsNullOrEmpty(value), "Email is required")
.AddRule(value => value.Contains("@"), "Invalid email format")
.AddAsyncRule(async value => await IsEmailAvailableAsync(value), "Email is already registered");
var result = await validator.ValidateAsync("john@example.com");
Merging Async Validation Results
var emailResult = await emailValidator.ValidateAsync(email);
var usernameResult = await usernameValidator.ValidateAsync(username);
var combinedResult = await emailResult.MergeAsync(usernameResult);
// Or merge multiple async results at once
var allResults = await AsyncValidationExtensions.MergeAsync(
new[] { emailResult, usernameResult, passwordResult });
.NET Ecosystem Compatibility
The framework provides seamless integration with all major .NET UI platforms, making it easy to use validation across your entire application stack.
ASP.NET Core Integration
The framework integrates with ASP.NET Core's ModelState system for seamless validation in web applications.
// In your controller
var validator = new UserValidator();
var result = validator.Validate(userModel);
// Add errors to ModelState
result.AddToModelState(ModelState);
// Or return a BadRequest with validation errors
return result.ToBadRequest();
// With custom message
return result.ToBadRequest("Validation failed");
// Check validity and add to ModelState
if (!result.EnsureValid(ModelState))
{
return BadRequest(ModelState);
}
// Using the ValidateModelAttribute for automatic validation
[ValidateModel]
public IActionResult Create(UserModel model)
{
// ModelState is automatically populated with validation errors
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok();
}
// Base class for validatable models
public class UserModel : ValidatableModel
{
public string Email { get; set; }
public string Password { get; set; }
public override ValidationResult Validate()
{
var validator = new Validator<UserModel>("User");
validator.AddRule(m => !string.IsNullOrEmpty(m.Email), "Email is required", nameof(Email));
validator.AddRule(m => CommonValidators.EmailValidator().Validate(m.Email).IsValid, "Invalid email", nameof(Email));
return validator.Validate(this);
}
}
WPF Integration
The framework integrates with WPF's validation system and INotifyDataErrorInfo interface.
// Extension methods for WPF controls
textBox.SetValidationError(result, nameof(User.Email));
textBox.SetFirstValidationError(result, nameof(User.Email));
textBox.ClearValidationError();
// Apply validation to multiple controls
var controlMappings = new Dictionary<string, Control>
{
{ nameof(User.Email), emailTextBox },
{ nameof(User.Name), nameTextBox }
};
result.ApplyToControls(controlMappings);
// Base class for validatable ViewModels
public class UserViewModel : ValidatableViewModel
{
private string _email;
public string Email
{
get => _email;
set => SetProperty(ref _email, value);
}
public override ValidationResult Validate()
{
var validator = new Validator<UserViewModel>("User");
validator.AddRule(vm => !string.IsNullOrEmpty(vm.Email), "Email is required", nameof(Email));
validator.AddRule(vm => CommonValidators.EmailValidator().Validate(vm.Email).IsValid, "Invalid email", nameof(Email));
return validator.Validate(this);
}
}
// WPF ValidationRule for XAML
public class EmailValidationRule : WpfValidationRule<string>
{
protected override ValidationResult Validate(string value, CultureInfo cultureInfo)
{
return CommonValidators.EmailValidator().Validate(value);
}
}
// In XAML
<TextBox Text="{Binding Email, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}">
<TextBox.ValidationRules>
<local:EmailValidationRule />
</TextBox.ValidationRules>
</TextBox>
// Attached property for validation
<TextBox local:ValidationBehavior.Validator="{Binding EmailValidator}"
local:ValidationBehavior.FieldName="Email" />
Windows Forms Integration
The framework integrates with Windows Forms ErrorProvider for displaying validation errors.
// Extension methods for WinForms controls
errorProvider.SetValidationError(textBox, result, nameof(User.Email));
errorProvider.SetAllValidationErrors(this, result);
errorProvider.ClearValidationError(textBox);
// Apply validation to multiple controls
var controlMappings = new Dictionary<string, Control>
{
{ nameof(User.Email), emailTextBox },
{ nameof(User.Name), nameTextBox }
};
result.ApplyToControls(controlMappings);
// Validate a control
errorProvider.ValidateControl(emailTextBox, emailValidator, nameof(User.Email));
// Validate entire form
errorProvider.ValidateForm(this, userValidator);
// Base class for validatable forms
public class UserForm : ValidatableForm
{
public UserForm()
{
// ErrorProvider is automatically created
}
protected override ValidationResult OnValidate()
{
var validator = new Validator<User>("User");
validator.AddRule(u => !string.IsNullOrEmpty(u.Email), "Email is required", nameof(User.Email));
return validator.Validate(GetUserFromForm());
}
}
// Validatable controls
<local:ValidatableTextBox Validator="{emailValidator}" FieldName="Email" />
<local:ValidatableComboBox Validator="{countryValidator}" FieldName="Country" />
Blazor Integration
The framework integrates with Blazor's EditContext for form validation.
// Extension methods for Blazor EditContext
result.AddToEditContext(EditContext);
result.EnsureValid(EditContext);
// Convert to error dictionary
errors = result.ToBlazorErrorDictionary();
// Convert to error list
errorMessages = result.ToErrorList();
// Base class for validatable components
public class UserComponent : ValidatableComponentBase
{
[Parameter]
public User User { get; set; }
protected override ValidationResult OnValidate()
{
var validator = new Validator<User>("User");
validator.AddRule(u => !string.IsNullOrEmpty(u.Email), "Email is required", nameof(User.Email));
return validator.Validate(User);
}
}
// Validatable input component
<ValidatableInput @bind-Value="User.Email"
Validator="emailValidator"
FieldName="Email" />
// Validatable form
<ValidatableForm Model="User" Validator="userValidator"
ValidationResultChanged="OnValidationChanged">
<ChildContent>
<ValidatableInput @bind-Value="User.Email" FieldName="Email" />
<ValidationMessage FieldName="Email" />
<ValidationSummary />
</ChildContent>
</ValidatableForm>
// Validation message component
<ValidationMessage ValidationResult="ValidationResult" FieldName="Email" />
// Validation summary component
<ValidationSummary ValidationResult="ValidationResult" />
// Validation state component
<ValidationState EditContext="EditContext" ValidationResult="ValidationResult">
<ValidContent>Form is valid!</ValidContent>
<InvalidContent>Please fix the errors</InvalidContent>
</ValidationState>
.NET MAUI Integration
The framework integrates with .NET MAUI's VisualElement system for mobile and desktop applications.
// Extension methods for MAUI VisualElements
entry.SetValidationError(result, nameof(User.Email));
entry.SetFirstValidationError(result, nameof(User.Email));
entry.ClearValidationError();
// Apply validation to multiple elements
var elementMappings = new Dictionary<string, VisualElement>
{
{ nameof(User.Email), emailEntry },
{ nameof(User.Name), nameEntry }
};
result.ApplyToElements(elementMappings);
// Convert to MAUI error dictionary
errors = result.ToMauiErrorDictionary();
// Convert to MAUI error list
errorMessages = result.ToMauiErrorList();
// Check validity and display errors
result.EnsureValid(page); // Shows alert with errors
// Base class for validatable ViewModels
public class UserViewModel : ValidatableViewModel
{
private string _email;
public string Email
{
get => _email;
set => SetProperty(ref _email, value);
}
public override ValidationResult Validate()
{
var validator = new Validator<UserViewModel>("User");
validator.AddRule(vm => !string.IsNullOrEmpty(vm.Email), "Email is required", nameof(Email));
return validator.Validate(this);
}
}
// Validatable Entry control
<local:ValidatableEntry Text="{Binding Email}"
Validator="{Binding EmailValidator}"
FieldName="Email" />
// Validatable Editor control
<local:ValidatableEditor Text="{Binding Description}"
Validator="{Binding DescriptionValidator}"
FieldName="Description" />
// Validatable ContentPage
public class UserPage : ValidatableContentPage
{
public UserPage(UserViewModel viewModel)
{
BindingContext = viewModel;
Validator = viewModel;
}
private async void OnSaveClicked(object sender, EventArgs e)
{
await ValidateAsync();
if (IsValid)
{
await DisplayAlert("Success", "User saved!", "OK");
}
else
{
await DisplayValidationErrorsAsync();
}
}
}
// Attached properties for validation
<Entry local:ValidationBehavior.Validator="{Binding EmailValidator}"
local:ValidationBehavior.FieldName="Email" />
// Model binding with validation
emailEntry.BindWithValidation(User, nameof(User.Email), emailValidator);
Advanced Usage
Using ValidationBuilder
var builder = new ValidationBuilder<UserProfile>()
.AddValidation("Email", p => CommonValidators.EmailValidator().Validate(p.Email))
.AddValidation("FirstName", p => CommonValidators.NameValidator().Validate(p.FirstName));
var result = builder.Validate(userProfile);
Merging Validation Results
var result1 = emailValidator.Validate(email);
var result2 = nameValidator.Validate(name);
var combinedResult = result1.Merge(result2);
Best Practices
- Field Names: Always provide meaningful field names for better error messages
var validator = CommonValidators.EmailValidator(fieldName: "Work Email");
- Custom Validation Rules: Keep rules simple and focused
.AddRule(value => value.Length > 0, "Value is required")
- Error Messages: Write clear, actionable error messages
"Password must contain at least one uppercase letter"
- Validation Groups: Organize related validations using ValidationBuilder
var builder = new ValidationBuilder<UserProfile>()
.AddValidation("PersonalInfo", ValidatePersonalInfo)
.AddValidation("ContactInfo", ValidateContactInfo);
Contributing
Contributions are welcome! Feel free to:
- Fork the repository
- Create a feature branch
- Submit a pull request
Please ensure your code follows the existing style and includes appropriate tests.
License
This project is licensed under the MIT License - see the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.2 | 139 | 6/20/2026 |
Version 2.0.1: Added async validation support (AsyncValidator, AsyncValidationRule), new validators (Guid, UUID, ISBN, MAC Address, JSON, Base64, Enum, etc.), improved CI/CD pipeline, enhanced error handling, and NuGet Trusted Publishing deployment.