Validated.Primitives
1.1.28
See the version list below for details.
dotnet add package Validated.Primitives --version 1.1.28
NuGet\Install-Package Validated.Primitives -Version 1.1.28
<PackageReference Include="Validated.Primitives" Version="1.1.28" />
<PackageVersion Include="Validated.Primitives" Version="1.1.28" />
<PackageReference Include="Validated.Primitives" />
paket add Validated.Primitives --version 1.1.28
#r "nuget: Validated.Primitives, 1.1.28"
#:package Validated.Primitives@1.1.28
#addin nuget:?package=Validated.Primitives&version=1.1.28
#tool nuget:?package=Validated.Primitives&version=1.1.28
Validated Primitives
A .NET library that provides strongly-typed, self-validating primitive value objects to eliminate primitive obsession and enforce domain constraints at compile-time.
Packages
This repository contains two NuGet packages:
📦 Validated.Primitives (Core)
The foundation library providing low-level validated primitive value objects.
dotnet add package Validated.Primitives
What it provides:
- Email addresses, phone numbers, URLs, IP addresses
- Postal codes with country-specific validation (30+ countries)
- Date/time value objects (DateOfBirth, FutureDate, date ranges)
- Financial primitives (Money, Percentage, CurrencyCode)
- Credit card primitives (CreditCardNumber, CreditCardSecurityNumber, CreditCardExpiration)
- Text primitives (HumanName, AddressLine, City, StateProvince)
- Validation framework and error handling
- JSON serialization support
📦 Validated.Primitives.Domain (Composition)
Higher-level domain models composed from validated primitives.
dotnet add package Validated.Primitives.Domain
What it provides:
- PersonName - Complete human name (first, last, middle) with computed properties (FullName, FormalName, Initials)
- Address - Physical mailing address with country-specific postal code validation
- ContactInformation - Email, primary/secondary phone, optional website
- CreditCardDetails - Complete payment card (number, CVV, expiration) with masking and expiration checking
Think of it as:
Validated.Primitives= LEGO bricks (EmailAddress, PhoneNumber, PostalCode)Validated.Primitives.Domain= Complete LEGO models (Address, PersonName, ContactInformation)
What are Validated Primitives?
Validated Primitives are value objects that encapsulate primitive types (strings, dates, numbers) with built-in validation rules. Instead of passing raw strings or dates throughout your application, you use strongly-typed objects that guarantee their validity.
The Problem: Primitive Obsession
// ❌ Traditional approach - primitive obsession
public class User
{
public string Email { get; set; } // Could be null, empty, or invalid
public string PhoneNumber { get; set; } // No format validation
public DateTime DateOfBirth { get; set; } // Could be in the future!
public string PostalCode { get; set; } // No country-specific validation
}
// Validation logic scattered everywhere
if (string.IsNullOrWhiteSpace(user.Email) || !IsValidEmail(user.Email))
{
throw new ArgumentException("Invalid email");
}
The Solution: Validated Primitives
// ✅ With Validated Primitives
public class User
{
public EmailAddress Email { get; set; } // Always valid or null
public PhoneNumber PhoneNumber { get; set; } // Always properly formatted
public DateOfBirth DateOfBirth { get; set; } // Always in the past
public PostalCode PostalCode { get; set; } // Country-specific validation
}
// Validation happens at creation - guaranteed valid everywhere else
var (result, email) = EmailAddress.TryCreate(userInput);
if (!result.IsValid)
{
// Handle validation errors
Console.WriteLine(result.ToBulletList());
return;
}
// email is guaranteed to be valid here
user.Email = email;
Key Benefits
- Type Safety: Compiler prevents mixing up different string types
- Self-Validating: Validation logic lives with the data
- Immutable: Value objects are records - thread-safe by default
- Explicit Intent: Code clearly communicates business rules
- Centralized Validation: No scattered validation logic
- Rich Error Messages: Detailed validation feedback
Installation
dotnet add package Validated.Primitives
Available Value Objects
📧 Email & Communication
EmailAddress- RFC 5322 compliant email format, max 256 charactersPhoneNumber- International phone number validation with country code supportWebsiteUrl- Valid HTTP/HTTPS URLs with proper scheme validation
📍 Location & Geography
PostalCode- Country-specific postal code validation for 30+ countriesCity- City names, max 100 characters, letters/spaces/hyphens/apostrophesStateProvince- State or province names, max 100 charactersAddressLine- Street address lines, max 200 characters
🌐 Network
IpAddress- Valid IPv4 or IPv6 addresses
📅 Date & Time
DateOfBirth- Must be in the past, cannot be future dateFutureDate- Must be in the future, cannot be past dateBetweenDatesSelection- Date within a specified rangeDateRange- Represents a range between two DateTimes with duration calculationDateOnlyRange- Represents a range between two DateOnly valuesTimeOnlyRange- Represents a range between two TimeOnly values
💳 Financial & Payment
Money- Monetary amounts with currency codes and precision validationSmallUnitMoney- Monetary amounts in smallest currency unit (e.g., cents)Percentage- Percentage values with configurable decimal placesCurrencyCode- ISO 4217 currency codes (USD, EUR, GBP, etc.)CreditCardNumber- Luhn-validated card numbers, 13-19 digits, rejects all-same-digit patternsCreditCardSecurityNumber- CVV/CVC security codes, 3-4 digitsCreditCardExpiration- Card expiration date with automatic 2-digit year normalization
👤 Personal Information
HumanName- Individual name parts (first, middle, last), 1-50 characters, letters/hyphens/apostrophes/spaces
API Integration Example
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
[HttpPost]
public IActionResult CreateUser([FromBody] CreateUserRequest request)
{
var (emailResult, email) = EmailAddress.TryCreate(request.Email, nameof(request.Email));
if (!emailResult.IsValid)
{
return BadRequest(emailResult.ToDictionary());
}
var (phoneResult, phone) = PhoneNumber.TryCreate(request.Phone, nameof(request.Phone));
if (!phoneResult.IsValid)
{
return BadRequest(phoneResult.ToDictionary());
}
var (postalResult, postalCode) = PostalCode.TryCreate(
request.CountryCode,
request.PostalCode,
nameof(request.PostalCode)
);
if (!postalResult.IsValid)
{
return BadRequest(postalResult.ToDictionary());
}
// Create user with validated primitives
var user = new User
{
Email = email,
Phone = phone,
PostalCode = postalCode
};
// Save user...
return Ok(user);
}
}
Using Validated.Primitives.Domain
For more complex scenarios, use the Validated.Primitives.Domain package which provides pre-built domain aggregates:
Complete User Profile Example
using Validated.Primitives.Domain;
using Validated.Primitives.ValueObjects;
// Create a complete address
var (addressResult, address) = Address.TryCreate(
street: "123 Main Street",
addressLine2: "Apt 4B",
city: "New York",
country: CountryCode.UnitedStates,
postalCode: "10001",
stateProvince: "NY"
);
// Create a person name
var (nameResult, personName) = PersonName.TryCreate(
firstName: "John",
lastName: "Doe",
middleName: "Michael"
);
// Create contact information
var (contactResult, contact) = ContactInformation.TryCreate(
countryCode: CountryCode.UnitedStates,
email: "john.doe@example.com",
primaryPhone: "+1-555-123-4567",
secondaryPhone: null,
website: "https://johndoe.com"
);
// Create credit card details
var (cardResult, card) = CreditCardDetails.TryCreate(
cardNumber: "4111 1111 1111 1111",
securityNumber: "123",
expirationMonth: 12,
expirationYear: 2025
);
if (addressResult.IsValid && nameResult.IsValid &&
contactResult.IsValid && cardResult.IsValid)
{
Console.WriteLine($"Name: {personName.FullName}");
Console.WriteLine($"Formal: {personName.FormalName}");
Console.WriteLine($"Initials: {personName.Initials}");
Console.WriteLine($"\nAddress: {address}");
Console.WriteLine($"\nContact: {contact.Email.Value}");
Console.WriteLine($"Phone: {contact.PrimaryPhone.Value}");
Console.WriteLine($"\nCard: {card.GetMaskedCardNumber()}");
Console.WriteLine($"Expires: {card.Expiration}");
Console.WriteLine($"Is Expired: {card.IsExpired()}");
}
Benefits of Domain Models
- Grouped Validation - Validate all related fields in one call
- Rich Behavior -
FullName,FormalName,Initials,GetMaskedCardNumber(),IsExpired() - Cohesive APIs - Pass
ContactInformationinstead of Email + Phone + Website separately - Guaranteed Consistency - If you have an
Address, all its parts are valid
Domain Models Available:
PersonName- FirstName + LastName + MiddleName with computed propertiesAddress- Complete mailing address with country-specific validationContactInformation- Email + Phones + WebsiteCreditCardDetails- CardNumber + CVV + Expiration with masking
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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. |
-
net8.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Validated.Primitives:
| Package | Downloads |
|---|---|
|
Validated.Primitives.Domain
Domain models and complex types built from Validated.Primitives value objects. Provides strongly-typed, self-validating domain entities for common use cases like Address, ContactInformation, PersonName, and CreditCardDetails. |
|
|
Mayordomo.Web.Extractor
Small, modular .NET 10 library to extract article content, images and metadata from web pages. |
|
|
ReadableWeb
ReadableWeb extracts readable article content, images and metadata from HTML. Small, modular .NET 10 library for article extraction and readability parsing. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Validated primitives including EmailAddress, PhoneNumber, WebsiteUrl, IpAddress, DateOfBirth, FutureDate, BetweenDatesSelection, DateRange, DateOnlyRange, TimeOnlyRange, and PostalCode.