Pitasoft.Validation.AspNetCore
1.0.3
dotnet add package Pitasoft.Validation.AspNetCore --version 1.0.3
NuGet\Install-Package Pitasoft.Validation.AspNetCore -Version 1.0.3
<PackageReference Include="Pitasoft.Validation.AspNetCore" Version="1.0.3" />
<PackageVersion Include="Pitasoft.Validation.AspNetCore" Version="1.0.3" />
<PackageReference Include="Pitasoft.Validation.AspNetCore" />
paket add Pitasoft.Validation.AspNetCore --version 1.0.3
#r "nuget: Pitasoft.Validation.AspNetCore, 1.0.3"
#:package Pitasoft.Validation.AspNetCore@1.0.3
#addin nuget:?package=Pitasoft.Validation.AspNetCore&version=1.0.3
#tool nuget:?package=Pitasoft.Validation.AspNetCore&version=1.0.3
Pitasoft.Validation.AspNetCore
English
Pitasoft.Validation.AspNetCore integrates Pitasoft.Validation with ASP.NET Core so invalid request payloads are automatically translated into Result.ValidationError(...) and returned as 400 Bad Request through Pitasoft.Result.AspNetCore.
Validators and checkers can be resolved from the ASP.NET Core dependency injection container, or provided explicitly in Minimal API. MVC / Web API attributes remain DI-based.
Features
- Minimal API integration with
WithValidator<T>(),WithChecker<T>(),WithValidator<T>(instance)andWithChecker<T>(instance) - MVC / Web API integration with
[ValidateRequest<T>]and[CheckRequest<T>] - Automatic support for sync and async validators or checkers
- Shared internal execution helpers to keep Minimal API and MVC behavior aligned
- Response contracts compatible with
Pitasoft.ResultandPitasoft.Client
Installation
dotnet add package Pitasoft.Validation.AspNetCore
Dependency injection
Register your validator or checker in DI before applying the filter:
builder.Services.AddScoped<IValidator<CreateProductRequest>, CreateProductRequestValidator>();
builder.Services.AddScoped<IChecker<CreateProductRequest>, CreateProductRequestChecker>();
If you want a dedicated package to help register validators and checkers, consider using Pitasoft.Validation.DependencyInjectionExtensions.
Example registration with DI:
builder.Services.AddScoped<CreateProductRequestValidator>();
builder.Services.AddScoped<IValidator<CreateProductRequest>>(sp =>
sp.GetRequiredService<CreateProductRequestValidator>());
For Minimal API you can also pass a concrete instance directly:
app.MapPost("/products", (CreateProductRequest request) =>
Result.Ok())
.WithValidator(new CreateProductRequestValidator());
Minimal API example
using Pitasoft.Error;
using Pitasoft.Result;
using Pitasoft.Validation;
using Pitasoft.Validation.AspNetCore.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IValidator<CreateProductRequest>, CreateProductRequestValidator>();
var app = builder.Build();
app.MapPost("/products", (CreateProductRequest request) =>
Result.Ok())
.WithValidator<CreateProductRequest>();
app.MapPost("/products/inline", (CreateProductRequest request) =>
Result.Ok())
.WithValidator(new CreateProductRequestValidator());
app.Run();
public sealed record CreateProductRequest(string? Name, decimal Price);
public sealed class CreateProductRequestValidator : IValidator<CreateProductRequest>
{
public ErrorCollection? ValidateObject(CreateProductRequest? instance)
{
if (instance is null || string.IsNullOrWhiteSpace(instance.Name))
{
return new ErrorCollection(new Dictionary<string, List<string>>
{
["Name"] = ["Name is required."]
});
}
return null;
}
public ErrorCollection? ValidateProperties(CreateProductRequest? instance, IEnumerable<string> propertyNames) =>
ValidateObject(instance);
public ErrorCollection? ValidateProperties(CreateProductRequest? instance, params string[] propertyNames) =>
ValidateObject(instance);
public ErrorCollection? ValidateProperty(CreateProductRequest? instance, string propertyName) =>
ValidateObject(instance);
}
MVC / Web API example
using Microsoft.AspNetCore.Mvc;
using Pitasoft.Result;
using Pitasoft.Validation.AspNetCore.Attributes;
[ApiController]
[Route("api/products")]
public sealed class ProductsController : ControllerBase
{
[HttpPost]
[ValidateRequest<CreateProductRequest>]
public IResult Create([FromBody] CreateProductRequest request)
{
return Result.Ok();
}
}
public sealed record CreateProductRequest(string? Name, decimal Price);
Checker example
builder.Services.AddScoped<IChecker<CreateProductRequest>, CreateProductRequestChecker>();
app.MapPost("/products/check", (CreateProductRequest request) =>
Result.Ok())
.WithChecker<CreateProductRequest>();
app.MapPost("/products/check-inline", (CreateProductRequest request) =>
Result.Ok())
.WithChecker(new CreateProductRequestChecker());
builder.Services.AddScoped<IChecker<CreateProductRequest>, CreateProductRequestChecker>();
[ApiController]
[Route("api/products")]
[HttpPost]
[CheckRequest<CreateProductRequest>]
public IResult Create([FromBody] CreateProductRequest request) => Result.Ok();
MVC / Web API attributes remain DI-based. Inline instances are supported only in Minimal API.
Validation behavior
- Invalid request input →
Result.ValidationError(...) ValidationError→400 Bad Request- Structured validation errors are preserved
ProblemDetailsis not used as the default contract- The first request argument compatible with
Tis validated, including compatible arguments bound asnull - DI-based and inline Minimal API overloads follow the same validation semantics
Internal implementation notes
The package currently centralizes key behavior in:
RequestArgumentResolverRequestValidationExecutorFilterFactoryHelper
This helps keep Minimal API and MVC behavior consistent.
Requirements
- ASP.NET Core 8, 9 or 10
Pitasoft.ValidationPitasoft.Result.AspNetCore
Tests
The solution includes Pitasoft.Validation.AspNetCore.Tests, covering areas such as:
- filter behavior
- route handler extensions
- request argument resolution
- attribute factory creation
Notes
- This package does not replace validation failures with
ProblemDetails - It relies on
Pitasoft.Result.AspNetCoreto generate the HTTP response - It keeps validation payloads aligned with
Pitasoft.Client
Castellano
Pitasoft.Validation.AspNetCore integra Pitasoft.Validation con ASP.NET Core para que las peticiones inválidas se traduzcan automáticamente a Result.ValidationError(...) y se devuelvan como 400 Bad Request mediante Pitasoft.Result.AspNetCore.
Los validadores y checkers pueden resolverse desde el contenedor de inyección de dependencia de ASP.NET Core, o pasarse como instancia explícita en Minimal API. Los atributos de MVC / Web API siguen siendo exclusivamente para DI.
Características
- Integración con Minimal API mediante
WithValidator<T>(),WithChecker<T>(),WithValidator<T>(instancia)yWithChecker<T>(instancia) - Integración con MVC / Web API mediante
[ValidateRequest<T>]y[CheckRequest<T>] - Soporte automático para validadores y checkers síncronos o asíncronos
- Helpers internos compartidos para mantener alineado el comportamiento entre Minimal API y MVC
- Contratos de respuesta compatibles con
Pitasoft.ResultyPitasoft.Client
Instalación
dotnet add package Pitasoft.Validation.AspNetCore
Inyección de dependencia
Registra tu validador o checker en DI antes de aplicar el filtro:
builder.Services.AddScoped<IValidator<CreateProductRequest>, CreateProductRequestValidator>();
builder.Services.AddScoped<IChecker<CreateProductRequest>, CreateProductRequestChecker>();
Si quieres un paquete específico para ayudarte con el registro de validadores y checkers, puedes usar Pitasoft.Validation.DependencyInjectionExtensions.
Ejemplo de registro con DI:
builder.Services.AddScoped<CreateProductRequestValidator>();
builder.Services.AddScoped<IValidator<CreateProductRequest>>(sp =>
sp.GetRequiredService<CreateProductRequestValidator>());
En Minimal API también puedes pasar una instancia concreta directamente:
app.MapPost("/products", (CreateProductRequest request) =>
Result.Ok())
.WithValidator(new CreateProductRequestValidator());
Ejemplo con Minimal API
using Pitasoft.Error;
using Pitasoft.Result;
using Pitasoft.Validation;
using Pitasoft.Validation.AspNetCore.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IValidator<CreateProductRequest>, CreateProductRequestValidator>();
var app = builder.Build();
app.MapPost("/products", (CreateProductRequest request) =>
Result.Ok())
.WithValidator<CreateProductRequest>();
app.MapPost("/products/inline", (CreateProductRequest request) =>
Result.Ok())
.WithValidator(new CreateProductRequestValidator());
app.Run();
public sealed record CreateProductRequest(string? Name, decimal Price);
public sealed class CreateProductRequestValidator : IValidator<CreateProductRequest>
{
public ErrorCollection? ValidateObject(CreateProductRequest? instance)
{
if (instance is null || string.IsNullOrWhiteSpace(instance.Name))
{
return new ErrorCollection(new Dictionary<string, List<string>>
{
["Name"] = ["El nombre es obligatorio."]
});
}
return null;
}
public ErrorCollection? ValidateProperties(CreateProductRequest? instance, IEnumerable<string> propertyNames) =>
ValidateObject(instance);
public ErrorCollection? ValidateProperties(CreateProductRequest? instance, params string[] propertyNames) =>
ValidateObject(instance);
public ErrorCollection? ValidateProperty(CreateProductRequest? instance, string propertyName) =>
ValidateObject(instance);
}
Ejemplo con MVC / Web API
using Microsoft.AspNetCore.Mvc;
using Pitasoft.Result;
using Pitasoft.Validation.AspNetCore.Attributes;
[ApiController]
[Route("api/products")]
public sealed class ProductsController : ControllerBase
{
[HttpPost]
[ValidateRequest<CreateProductRequest>]
public IResult Create([FromBody] CreateProductRequest request)
{
return Result.Ok();
}
}
public sealed record CreateProductRequest(string? Name, decimal Price);
Ejemplo con Checker
builder.Services.AddScoped<IChecker<CreateProductRequest>, CreateProductRequestChecker>();
app.MapPost("/products/check", (CreateProductRequest request) =>
Result.Ok())
.WithChecker<CreateProductRequest>();
app.MapPost("/products/check-inline", (CreateProductRequest request) =>
Result.Ok())
.WithChecker(new CreateProductRequestChecker());
builder.Services.AddScoped<IChecker<CreateProductRequest>, CreateProductRequestChecker>();
[ApiController]
[Route("api/products")]
[HttpPost]
[CheckRequest<CreateProductRequest>]
public IResult Create([FromBody] CreateProductRequest request) => Result.Ok();
Los atributos de MVC / Web API siguen siendo exclusivamente para DI. Las instancias inline solo están soportadas en Minimal API.
Comportamiento de validación
- Entrada inválida →
Result.ValidationError(...) ValidationError→400 Bad Request- Los errores estructurados se conservan
ProblemDetailsno se usa como contrato por defecto- Se valida el primer argumento de petición compatible con
T, incluso si el valor enlazado llega comonull - Los overloads inline y los overloads basados en DI siguen la misma semántica
Notas de implementación interna
Actualmente el paquete centraliza comportamiento importante en:
RequestArgumentResolverRequestValidationExecutorFilterFactoryHelper
Esto ayuda a mantener coherencia entre Minimal API y MVC.
Requisitos
- ASP.NET Core 8, 9 o 10
Pitasoft.ValidationPitasoft.Result.AspNetCore
Tests
La solución incluye Pitasoft.Validation.AspNetCore.Tests, cubriendo áreas como:
- comportamiento de filtros
- extensiones de
RouteHandlerBuilder - resolución de argumentos de petición
- creación de filtros desde atributos
Notas
- Este paquete no sustituye los errores de validación por
ProblemDetails - Usa
Pitasoft.Result.AspNetCorepara generar la respuesta HTTP - Mantiene los payloads de validación alineados con
Pitasoft.Client
Autor
Sebastián Martínez Pérez
Licencia
Copyright © 2026 Pitasoft, S.L.
Licenciado bajo los términos de la LICENSE.txt incluida en este repositorio.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. 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 is compatible. 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 is compatible. 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. |
-
net10.0
- Pitasoft.Result.AspNetCore (>= 2.1.2)
- Pitasoft.Validation (>= 6.0.5)
-
net8.0
- Pitasoft.Result.AspNetCore (>= 2.1.2)
- Pitasoft.Validation (>= 6.0.5)
-
net9.0
- Pitasoft.Result.AspNetCore (>= 2.1.2)
- Pitasoft.Validation (>= 6.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.