Phema.Validation 3.0.8

C# strongly typed validation library for .NET

There is a newer version of this package available.
See the version list below for details.
Install-Package Phema.Validation -Version 3.0.8
dotnet add package Phema.Validation --version 3.0.8
<PackageReference Include="Phema.Validation" Version="3.0.8" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Phema.Validation --version 3.0.8
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

Phema.Validation

Build Status
Nuget
Nuget

Strongly typed expression-based validation library for .NET built on top of extension methods and full of latest C# features
Can be used anywhere with Microsoft.Extensions.DependencyInjection package support

Installation

$> dotnet add package Phema.Validation

Usage (ASP.NET Core, HostedService examples)

// Add `IValidationContext` as scoped service
services.AddValidation(options => ...);

// Get or inject
var validationContext = serviceProvider.GetRequiredService<IValidationContext>();

// Validation key will be `Name` using default validation part provider
validationContext.When(person, p => p.Name)
  .Is(name => name == null)
  .AddError("Name must be set");

// Validation key will be `Address.Locations[0].Latitude` using default validation part provider
validationContext.When(person, p => p.Address.Locations[0].Latitude)
  .Is(latitude => ...custom check...)
  .AddError("Some custom check failed");

Validation conditions

  • Monads are not composable, so Is and IsNot, IsNull and IsNotNull... duplication
// Check for Phema.Validation.Conditions namespace
validationContext.When(person, p => p.Name)
  .IsNullOrWhitespace()
  .AddError("Name must be set");

// Use multiple conditions (joined with OR)
validationContext.When(person, p => p.Name)
  .IsNull()
  .HasLengthGreater(20)
  // .IsNotNull()
  // .IsEqual()
  // .IsMatch(regex)
  .AddError("Name is invalid");

Validation details

// Null if valid
var validationDetails = validationContext.When(person, p => p.Age)
  // Validation condition is valid
  .Is(() => false)
  .AddError("Age must be set");

// Use deconstruction
var (key, message) = validationContext.When(person, p => p.Age)
  .IsNull()
  .AddError("Age must be set");

// More deconstruction
var (key, message, severity) = validationContext.When(person, p => p.Age)
  .IsNull()
  .AddError("Age must be set");

Check validation

// Override default ValidationSeverity
validationContext.ValidationSeverity = ValidationSeverity.Warning;

// Throw exception when details severity greater than ValidationContext.ValidationSeverity
validationContext.When(person, p => p.Address)
  .IsNull()
  .AddFatal("Address is not presented!!!"); // If invalid throw ValidationConditionException

// Check if context is valid
validationContext.IsValid();
validationContext.EnsureIsValid(); // If invalid throw ValidationContextException

// Check concrete validation details
validationContext.IsValid(person, p => p.Age);
validationContext.EnsureIsValid(person, p => p.Age);

Compose and reuse validation rules

  • Call is allocation free
  • Static checks
  • Extensible as a IValidators and IValidationComponents
// Extensions
public static void ValidateCustomer(this IValidationContext validationContext, Customer customer)
{
  // Some checks
}

validationContext.ValidateCustomer(customer);

Validation part providers

  • ValidationPartResolver is a delegate, trying to get valdiation part from MemberInfo
  • Where are 2 built-in validation part providers
    • Default - just get MemberInfo.Name
    • DataMemberOrDefault - Try to get DataMemberAttribute.Name or use default implementation
// Configure DataMember validation part provider
services.AddValidation(options =>
  options.ValidationPartResolver = ValidationDefaults.DataMemberOrDefaultValidationPartResolver);

// Override validation parts with `DataMemberAttribute`
[DataMember(Name = "name")]
public string Name { get; set; }

Validation scopes

  • Use scopes when you need to have:
    • Same nested validation path multiple times
    • Empty validation details collection (syncing with parent context/scope)
    • ValidationSeverity override
// Validation key will be `Child.*ValidationPart*`
ValidateChild(validationContext.CreateScope(parent, p => p.Child))

// Validation key will be `Address.Locations[0].*ValidationPart*`
ValidateLocation(validationContext.CreateScope(person, p => p.Address.Locations[0]))

// Override local scope ValidationSeverity
using (var scope = validationContext.CreateScope(person, p => p.Address))
{
  scope.ValidationSeverity = ValidationSeverity.Warning;

  // Some scope validation checks syncing with validationContext
}

High performance with non-expression constructions

validationContext.When("key", value)
  .IsNull()
  .AddError("Value is null");

validationContext.CreateScope("key");

validationContext.IsValid("key");
validationContext.EnsureIsValid("key");

Phema.Validation

Build Status
Nuget
Nuget

Strongly typed expression-based validation library for .NET built on top of extension methods and full of latest C# features
Can be used anywhere with Microsoft.Extensions.DependencyInjection package support

Installation

$> dotnet add package Phema.Validation

Usage (ASP.NET Core, HostedService examples)

// Add `IValidationContext` as scoped service
services.AddValidation(options => ...);

// Get or inject
var validationContext = serviceProvider.GetRequiredService<IValidationContext>();

// Validation key will be `Name` using default validation part provider
validationContext.When(person, p => p.Name)
  .Is(name => name == null)
  .AddError("Name must be set");

// Validation key will be `Address.Locations[0].Latitude` using default validation part provider
validationContext.When(person, p => p.Address.Locations[0].Latitude)
  .Is(latitude => ...custom check...)
  .AddError("Some custom check failed");

Validation conditions

  • Monads are not composable, so Is and IsNot, IsNull and IsNotNull... duplication
// Check for Phema.Validation.Conditions namespace
validationContext.When(person, p => p.Name)
  .IsNullOrWhitespace()
  .AddError("Name must be set");

// Use multiple conditions (joined with OR)
validationContext.When(person, p => p.Name)
  .IsNull()
  .HasLengthGreater(20)
  // .IsNotNull()
  // .IsEqual()
  // .IsMatch(regex)
  .AddError("Name is invalid");

Validation details

// Null if valid
var validationDetails = validationContext.When(person, p => p.Age)
  // Validation condition is valid
  .Is(() => false)
  .AddError("Age must be set");

// Use deconstruction
var (key, message) = validationContext.When(person, p => p.Age)
  .IsNull()
  .AddError("Age must be set");

// More deconstruction
var (key, message, severity) = validationContext.When(person, p => p.Age)
  .IsNull()
  .AddError("Age must be set");

Check validation

// Override default ValidationSeverity
validationContext.ValidationSeverity = ValidationSeverity.Warning;

// Throw exception when details severity greater than ValidationContext.ValidationSeverity
validationContext.When(person, p => p.Address)
  .IsNull()
  .AddFatal("Address is not presented!!!"); // If invalid throw ValidationConditionException

// Check if context is valid
validationContext.IsValid();
validationContext.EnsureIsValid(); // If invalid throw ValidationContextException

// Check concrete validation details
validationContext.IsValid(person, p => p.Age);
validationContext.EnsureIsValid(person, p => p.Age);

Compose and reuse validation rules

  • Call is allocation free
  • Static checks
  • Extensible as a IValidators and IValidationComponents
// Extensions
public static void ValidateCustomer(this IValidationContext validationContext, Customer customer)
{
  // Some checks
}

validationContext.ValidateCustomer(customer);

Validation part providers

  • ValidationPartResolver is a delegate, trying to get valdiation part from MemberInfo
  • Where are 2 built-in validation part providers
    • Default - just get MemberInfo.Name
    • DataMemberOrDefault - Try to get DataMemberAttribute.Name or use default implementation
// Configure DataMember validation part provider
services.AddValidation(options =>
  options.ValidationPartResolver = ValidationDefaults.DataMemberOrDefaultValidationPartResolver);

// Override validation parts with `DataMemberAttribute`
[DataMember(Name = "name")]
public string Name { get; set; }

Validation scopes

  • Use scopes when you need to have:
    • Same nested validation path multiple times
    • Empty validation details collection (syncing with parent context/scope)
    • ValidationSeverity override
// Validation key will be `Child.*ValidationPart*`
ValidateChild(validationContext.CreateScope(parent, p => p.Child))

// Validation key will be `Address.Locations[0].*ValidationPart*`
ValidateLocation(validationContext.CreateScope(person, p => p.Address.Locations[0]))

// Override local scope ValidationSeverity
using (var scope = validationContext.CreateScope(person, p => p.Address))
{
  scope.ValidationSeverity = ValidationSeverity.Warning;

  // Some scope validation checks syncing with validationContext
}

High performance with non-expression constructions

validationContext.When("key", value)
  .IsNull()
  .AddError("Value is null");

validationContext.CreateScope("key");

validationContext.IsValid("key");
validationContext.EnsureIsValid("key");

GitHub repositories (0)

This package is not used by any popular GitHub repositories.

Version History

Version Downloads Last updated
3.1.10 122 10/12/2019
3.1.9 187 9/27/2019
3.1.8 157 9/25/2019
3.1.7 126 9/15/2019
3.1.6 86 9/8/2019
3.1.5 72 9/7/2019
3.1.4 72 9/7/2019
3.1.3 93 9/7/2019
3.1.2 73 8/25/2019
3.1.1 72 8/24/2019
3.1.0 72 8/23/2019
3.0.9 73 8/23/2019
3.0.8 74 8/22/2019
3.0.7 75 8/16/2019
3.0.6 68 7/30/2019
3.0.5 72 7/29/2019
3.0.4 75 7/29/2019
3.0.3 74 7/28/2019
3.0.2 72 7/21/2019
Show less