RecursiveDataAnnotationsValidation 2.3.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package RecursiveDataAnnotationsValidation --version 2.3.1
                    
NuGet\Install-Package RecursiveDataAnnotationsValidation -Version 2.3.1
                    
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="RecursiveDataAnnotationsValidation" Version="2.3.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RecursiveDataAnnotationsValidation" Version="2.3.1" />
                    
Directory.Packages.props
<PackageReference Include="RecursiveDataAnnotationsValidation" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RecursiveDataAnnotationsValidation --version 2.3.1
                    
#r "nuget: RecursiveDataAnnotationsValidation, 2.3.1"
                    
#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.
#:package RecursiveDataAnnotationsValidation@2.3.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RecursiveDataAnnotationsValidation&version=2.3.1
                    
Install as a Cake Addin
#tool nuget:?package=RecursiveDataAnnotationsValidation&version=2.3.1
                    
Install as a Cake Tool

RecursiveDataAnnotationsValidation

Allows recursive validation of sub-objects in a class when using DataAnnotations validation (also known as Attribute Validation). The current version of .NET Core's attribute validation does not handle objects within objects (or collections of objects). Therefore it is necessary to add some glue code to recurse through the object graph.

Installation

.NET Core

$ dotnet add package RecursiveDataAnnotationsValidation

Package Manager

PM> Install-Package RecursiveDataAnnotationsValidation

Usage

Usage of the recursive validation is nearly identical to using the standard validator.

var validator = new RecursiveDataAnnotationValidator();
var validationResults = new List<ValidationResult>();
var result = validator.TryValidateObjectRecursive(sut, validationResults);

There are more examples in the example and test projects.

SkipRecursiveValidationAttribute

The [SkipRecursiveValidation] attribute can be used on properties where you do not want to recursively validate. An example of this can be seen in SkippedChildrenExample.cs.

Shared objects, cycles and computed properties

  • Each object is validated once, even when several properties point to it. This also stops cycles, such as a child that points back to its parent.
  • Objects are compared by reference. Two separate objects that are Equals to each other, such as records with the same values or entities with the same Id, are each validated.
  • Public static properties are walked, as well as instance properties.
  • A property that builds a new object on each read, such as public Money Zero => new Money(0), could make the walk go on forever. So when an object's type overrides Equals, and the object equals an object of the same type, a base type or a derived type on its own path from the root, the validator checks that object's own attributes but does not walk into its properties. An invalid object below it is not reached.
  • For a type that does not override Equals, mark such a property with [SkipRecursiveValidation]. Otherwise the walk overflows the stack, which ends the process.
  • Two records that reference each other can also overflow the stack. A record's generated Equals compares properties in declaration order, so it follows the reference forever if it reaches it before a property that differs. This happens when the records have equal values, or when the reference is declared first. On .NET Framework it always happens, because the framework's Validator calls the record's generated GetHashCode, which follows the reference too. Marking the reference with [SkipRecursiveValidation] avoids the walk, but not the GetHashCode call on .NET Framework. There, override GetHashCode so it does not include the reference.

Framework types that are not walked

The validator does not walk the properties that these framework types declare: Type and other MemberInfo types, Assembly, Module, delegates, Uri, and FileSystemInfo, which covers DirectoryInfo and FileInfo. Reading those properties throws or never ends, for example Uri.Segments on a relative Uri, and they carry no validation attributes.

An object of one of these types is still validated. Attributes on the property that holds it, such as [Required] on a Uri property, still run. A subclass of your own, such as a class derived from Uri, is validated too, and the properties it adds are walked.

Other framework types are walked, so your objects inside them are validated. Examples are tuples, KeyValuePair items of a dictionary, and collections.

Build Status

.NET Core

Nuget Page

https://www.nuget.org/packages/RecursiveDataAnnotationsValidation/

History and attribution

This package grew out of a need to recursively validate POCOs used for the .NET Core options pattern. It is based on the DataAnnotationsValidatorRecursive project by Mike Reust. After a lot of experimentation, I forked that project. My goals at the time were to make minor improvements, port it to .NET Standard, and experiment with GitHub Actions. The two projects have since evolved independently.

Mike Reust's original copyright is retained in the LICENSE.

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.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (7)

Showing the top 5 NuGet packages that depend on RecursiveDataAnnotationsValidation:

Package Downloads
CUSTIS.NetCore.AppHost

Инструменты для хостинга приложения

OptionsPatternValidation

Package Description

Smino.Bcf.Toolkit

This C# NuGet library allows you to easily build up and convert data into BCF files. It gives you a straightforward API to build your BCF objects exactly how you want in your order.

Dacier.Scheduler.Entities

The Dacier.Scheduler.Entities package defines entities for the Dacier Scheduler.

MasterX.Core

Integrated part of master-X.NetCore

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.3.3 456 10/2/2026
2.3.2 90 10/2/2026
2.3.1 89 10/2/2026
2.3.0 182 10/1/2026
2.2.4 234 10/1/2026
2.2.3 309 9/30/2026
2.2.1 105 9/30/2026
2.2.0 42,021 3/29/2026
2.1.1 508 3/28/2026
2.1.0 373 3/28/2026
2.0.0 827,098 11/18/2022
1.1.1 150,962 6/23/2022
1.1.0 156,639 1/10/2022
1.0.0 371,049 3/11/2020
0.9.1 1,186 3/11/2020
0.9.0 1,337 3/11/2020