@@ -382,6 +382,84 @@ public sealed class MigrationConfig
382382}
383383```
384384
385+ ### 8. Collection Validation - ValidateEach with LINQ Support
386+
387+ ** Demonstrates:** Validating each item in a collection, including LINQ filtering support
388+
389+ ``` csharp
390+ builder .Services .AddConfigKit <ServerConfig >(" Servers" )
391+ .InRange (c => c .MaxRetries , 0 , 10 , " Max retries must be between 0 and 10" )
392+ .InRange (c => c .TimeoutSeconds , 1 , 300 , " Timeout must be between 1 and 300 seconds" )
393+ .ValidateEach (c => c .Endpoints ,
394+ itemBuilder => itemBuilder
395+ .NotEmpty (e => e .Name , " Endpoint name is required" )
396+ .NotEmpty (e => e .Url , " Endpoint URL is required" )
397+ .InRange (e => e .Port , 1 , 65535 , " Port must be between 1 and 65535" )
398+ .InRange (e => e .HealthCheckIntervalSeconds , 5 , 3600 , " Health check interval must be between 5 and 3600 seconds" ),
399+ minCount : 1 ,
400+ emptyMessage : " At least one endpoint must be configured" )
401+ .ValidateEach (c => c .Endpoints .Where (e => e .Enabled ),
402+ itemBuilder => itemBuilder
403+ .GreaterThan (e => e .HealthCheckIntervalSeconds , 0 , " Enabled endpoints must have positive health check interval" ),
404+ minCount : 1 ,
405+ emptyMessage : " At least one enabled endpoint is required" )
406+ .ValidateOnStartup ();
407+ ```
408+
409+ ** Configuration class:**
410+
411+ ``` csharp
412+ public sealed class ServerConfig
413+ {
414+ public List <ServerEndpoint > Endpoints { get ; set ; } = [];
415+ public int MaxRetries { get ; set ; }
416+ public int TimeoutSeconds { get ; set ; }
417+ }
418+
419+ public sealed class ServerEndpoint
420+ {
421+ public string Name { get ; set ; } = string .Empty ;
422+ public string Url { get ; set ; } = string .Empty ;
423+ public int Port { get ; set ; }
424+ public bool Enabled { get ; set ; }
425+ public int HealthCheckIntervalSeconds { get ; set ; }
426+ }
427+ ```
428+
429+ ** appsettings.json:**
430+
431+ ``` json
432+ {
433+ "Servers" : {
434+ "MaxRetries" : 3 ,
435+ "TimeoutSeconds" : 30 ,
436+ "Endpoints" : [
437+ {
438+ "Name" : " Primary API" ,
439+ "Url" : " https://api.primary.example.com" ,
440+ "Port" : 443 ,
441+ "Enabled" : true ,
442+ "HealthCheckIntervalSeconds" : 60
443+ },
444+ {
445+ "Name" : " Secondary API" ,
446+ "Url" : " https://api.secondary.example.com" ,
447+ "Port" : 443 ,
448+ "Enabled" : true ,
449+ "HealthCheckIntervalSeconds" : 120
450+ },
451+ {
452+ "Name" : " Backup API" ,
453+ "Url" : " https://api.backup.example.com" ,
454+ "Port" : 8443 ,
455+ "Enabled" : false ,
456+ "HealthCheckIntervalSeconds" : 0
457+ }
458+ ]
459+ }
460+ }
461+ ```
462+
385463## 🌐 API Endpoints
386464
387465| Endpoint | Description |
@@ -393,6 +471,7 @@ public sealed class MigrationConfig
393471| ` GET /api/configuration/security ` | View security configuration |
394472| ` GET /api/configuration/campaign ` | View campaign configuration |
395473| ` GET /api/configuration/migration ` | View migration configuration with property comparison |
474+ | ` GET /api/configuration/servers ` | View server endpoints configuration |
396475| ` GET /api/configuration/all ` | View summary of all configurations |
397476
398477## ⚡ Fail-Fast Behavior
@@ -490,6 +569,7 @@ Unhandled exception. Microsoft.Extensions.Options.OptionsValidationException:
490569| ** DateTime Validation** | ` Minimum ` for campaign dates, ` GreaterThan ` for future dates |
491570| ** TimeSpan Validation** | ` GreaterThan ` for positive intervals, ` Maximum ` for durations |
492571| ** Property Comparison** | ` GreaterThanProperty ` , ` LessThanProperty ` , ` MinimumProperty ` , ` MaximumProperty ` |
572+ | ** Collection Validation** | ` ValidateEach ` for endpoint lists with LINQ filtering |
493573| ** File System** | ` DirectoryExists ` , ` FileExists ` |
494574| ** Network** | ` UrlReachable ` |
495575| ** Security** | ` NoPlainTextSecrets ` |
0 commit comments