Rocket.Libraries.Validation 1.1.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package Rocket.Libraries.Validation --version 1.1.4
NuGet\Install-Package Rocket.Libraries.Validation -Version 1.1.4
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Rocket.Libraries.Validation" Version="1.1.4" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Rocket.Libraries.Validation --version 1.1.4
#r "nuget: Rocket.Libraries.Validation, 1.1.4"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Rocket.Libraries.Validation as a Cake Addin
#addin nuget:?package=Rocket.Libraries.Validation&version=1.1.4

// Install Rocket.Libraries.Validation as a Cake Tool
#tool nuget:?package=Rocket.Libraries.Validation&version=1.1.4

Rocket.Libraries.Validation

A Functional C# validation library

What It Is

This is a simple library that allows you to organize validation rules and then evaluate the rules during runtime with an exception getting thrown if any of the rules, fails.

Why Use a Library?

I found myself writing a forest of if-elseif-else or switch blocks to handle validation.

While these conditional blocks work, they tend to get more unreadable and more unmaintainable with the number of checks required.

Worse still while working in a team, there wasn't a consistent way of that team members were using to validate and hence checks were peppered all over code in various flavours.

What this validation library allows you to do, is to collapse what would be branch statements into inline statements, for more manageable code.

Package

Installation, grab the package from nuget https://www.nuget.org/packages/Rocket.Libraries.Validation/

Example Usage

Single Condition Evaluation

You may for example wish to check that an object isn't null before you proceed to use it. In such cases, it is common to write code similar to below.


public void DoStuff(User user)
{
    if(user == null)
    {
        throw new Exception("User was not supplied");
    }
    else
    {
        //Do stuff with the user object
    }
}

With Rocket Validation, you can reduce the complexity of the above code by re-writing it as below.


private DataValidator _validator = new DataValidator();

public void DoStuff(User user)
{
    _validator
        .EvaluateImmediate(() => user == null, "User was not supplied");
    //Do stuff with the user object
}

The inline EvaluateImmediate method takes in a boolean function as its first parameter, which if evaluated to true, causes an exception to be thrown. The thrown exceptions's message is the string passed as the second parameter to EvaluateImmediate

The second code snippet that uses the library is more readable, enforces more structure and introduces less code complexity.

Multiple/Chained Condition Evaluation

In this example, we'll check that a User object is not null and that the property Username is not empty and that the length of the Username property is not less than 6 characters. Without the library, we can handle that validation as shown below.

public bool ValidateUserName(User user)
{
  const int minLength = 6;
  if(user != null)
  {
    if(!string.IsNullOrEmpty(user.Username))
    {
      if(user.Username.length < minLength)
      {
        throw new Exception($"Username '{user.Username}' is too short. At least {minLength} characters are required");
      }
      else
      {
        return true;
      }
    }
    else
    {
      throw new Exception("Username was not supplied. Usernames are mandatory");
    }
  }
  else
  {
    throw new Exception("No user was supplied");
  }
 }
}

With the validation library, we're able collapse the above code to something similar to the following:


private DataValidator _validator = new DataValidator();


public bool ValidateUserName(User user)
{
 const int minLength = 6;
 _validator
    .AddFailureCondition(() => user == null, "User was not supplied", true)
    .AddFailureCondition(() => string.IsNullOrEmpty(user.Username), "Username was not supplied. Usernames are mandatory", false)
    .AddFailureCondition(() => user.Username.Length < minLength, $"Username '{user.Username}' is too short. At least {minLength} characters are required", false)
    .ThrowExceptionOnInvalidRules();
}

The AddFailureCondition method also take in a Func<bool> as its first parameter, which should evaluate to true to indicate a failing validation. As a second paramter, it takes in a string which serves as the error message for the failing condition, and finally it takes a bool parameter to indicate whether or not a rule is critical, i.e does the failing of a rule make validation of follow-up rules unnecessary.

An example of a critical rule is whether our user object is null, as if the object is indeed null, then it follows that trying to check whether user.Username is empty would result in a NullPointerException being thrown by the runtime.

Again, using the library greatly reduces code complexity and also as an bonus inlining allows error messages to live next to the rule they belong to.

In opposition to inlining, the snippet without the library has rule in the if part of the clause and the error message in the else. A practise that makes it harder to follow what the code is doing as rules increase especially if the if/else blocks get nested too deeply.

Not only does the Rocket Validation Library reduce the lines of code required, but it enforces structured validation, and also increases code readabililty which will result in easier to troubleshoot code, thats more maintainable.

Validation Results

IncorrectDataException

ONLY in cases where a validation rules fails, whether it be via the single rule method EvaluateImmediate or the chained rule method AddFailureCondition (or its async relative AddFailureConditionAsync) is an exception of type IncorrectDataException is thrown. If no rule(s) fail, then no exception is thrown.

The IncorrectDataException is a simple sub-class of the Exception object, with the main addition being the property Errors, which is a list that contains all the error messages from the failing rule(s).

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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. 
.NET Core netcoreapp2.2 is compatible.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETCoreApp 2.2

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Rocket.Libraries.Validation:

Package Downloads
Rocket.Libraries.QBuilder

Helper library for querying databases from C#

Rocket.Libraries.Emailing

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.0.2 1,071 2/28/2020
2.0.0-beta05 1,719 10/29/2019
2.0.0-beta02 318 9/4/2019
2.0.0-beta01 323 9/3/2019
1.1.8 499 9/2/2019
1.1.7 440 9/2/2019
1.1.5-beta10 335 7/30/2019
1.1.5-beta02 347 7/24/2019
1.1.4 444 7/21/2019