85 lines
2.3 KiB
Markdown
85 lines
2.3 KiB
Markdown
|
|
Request.Validation is a lightweight validation library for C#, built around composable validators, fluent rules, and
|
||
|
|
structured validation results.
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
- **Composable validators:** Build validators by inheriting from `Validator<T>` and defining rules with `RuleFor` and
|
||
|
|
`RuleForEach`.
|
||
|
|
- **Built-in and custom rules:** Use helpers like `NotEmpty`, `Length`, `Between`, and `Matches`, or define custom
|
||
|
|
predicates with `Must`.
|
||
|
|
- **Structured validation output:** Each failure is returned as a `Problem` with a property path, message, severity,
|
||
|
|
code, and attempted value.
|
||
|
|
- **Nested validation:** Reuse validators for complex object graphs with `SetValidator`, including DI-based resolution.
|
||
|
|
|
||
|
|
## Getting Started
|
||
|
|
|
||
|
|
### Install the NuGet package:
|
||
|
|
|
||
|
|
```shell
|
||
|
|
dotnet add package Geekeey.Request.Validation
|
||
|
|
```
|
||
|
|
|
||
|
|
You may need to add our NuGet feed to your nuget.config this can be done by running the following command:
|
||
|
|
|
||
|
|
```shell
|
||
|
|
dotnet nuget add source -n geekeey https://code.geekeey.de/api/packages/geekeey/nuget/index.json
|
||
|
|
```
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
using Geekeey.Request.Validation;
|
||
|
|
|
||
|
|
public sealed record Address(string? Street);
|
||
|
|
|
||
|
|
public sealed record CreateUserRequest(
|
||
|
|
string? Name,
|
||
|
|
int Age,
|
||
|
|
Address? Address,
|
||
|
|
IReadOnlyList<string> Tags);
|
||
|
|
|
||
|
|
public sealed class AddressValidator : Validator<Address>
|
||
|
|
{
|
||
|
|
public AddressValidator()
|
||
|
|
{
|
||
|
|
RuleFor(address => address.Street)
|
||
|
|
.NotEmpty();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public sealed class CreateUserRequestValidator : Validator<CreateUserRequest>
|
||
|
|
{
|
||
|
|
public CreateUserRequestValidator()
|
||
|
|
{
|
||
|
|
RuleFor(request => request.Name)
|
||
|
|
.NotEmpty()
|
||
|
|
.Length(2, 100)
|
||
|
|
.WithCode("NAME_INVALID");
|
||
|
|
|
||
|
|
RuleFor(request => request.Age)
|
||
|
|
.Between(18, 120);
|
||
|
|
|
||
|
|
RuleFor(request => request.Address)
|
||
|
|
.SetValidator(new AddressValidator());
|
||
|
|
|
||
|
|
RuleForEach(request => request.Tags)
|
||
|
|
.NotEmpty()
|
||
|
|
.WithSeverity(Severity.Warning);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var validator = new CreateUserRequestValidator();
|
||
|
|
var validation = validator.Validate(new CreateUserRequest(
|
||
|
|
Name: "",
|
||
|
|
Age: 16,
|
||
|
|
Address: new Address(""),
|
||
|
|
Tags: ["", "admin"]));
|
||
|
|
|
||
|
|
foreach (var problem in validation.Problems)
|
||
|
|
{
|
||
|
|
Console.WriteLine($"{problem.PropertyName}: {problem.Message}");
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
The resulting `Problem` entries include full property paths like `Address.Street` and `Tags[0]`, making it easy to
|
||
|
|
surface validation errors back to callers or APIs.
|