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
                    
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="Pitasoft.Validation.AspNetCore" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Pitasoft.Validation.AspNetCore" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Pitasoft.Validation.AspNetCore" />
                    
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 Pitasoft.Validation.AspNetCore --version 1.0.3
                    
#r "nuget: Pitasoft.Validation.AspNetCore, 1.0.3"
                    
#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 Pitasoft.Validation.AspNetCore@1.0.3
                    
#: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=Pitasoft.Validation.AspNetCore&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Pitasoft.Validation.AspNetCore&version=1.0.3
                    
Install as a Cake Tool

Pitasoft.Validation.AspNetCore

NuGet NuGet Downloads License Pitasoft.Validation Pitasoft.Validation.DependencyInjectionExtensions Pitasoft.Result.AspNetCore


English | Castellano


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) and WithChecker<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.Result and Pitasoft.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(...)
  • ValidationError400 Bad Request
  • Structured validation errors are preserved
  • ProblemDetails is not used as the default contract
  • The first request argument compatible with T is validated, including compatible arguments bound as null
  • DI-based and inline Minimal API overloads follow the same validation semantics

Internal implementation notes

The package currently centralizes key behavior in:

  • RequestArgumentResolver
  • RequestValidationExecutor
  • FilterFactoryHelper

This helps keep Minimal API and MVC behavior consistent.

Requirements

  • ASP.NET Core 8, 9 or 10
  • Pitasoft.Validation
  • Pitasoft.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.AspNetCore to 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) y WithChecker<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.Result y Pitasoft.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(...)
  • ValidationError400 Bad Request
  • Los errores estructurados se conservan
  • ProblemDetails no se usa como contrato por defecto
  • Se valida el primer argumento de petición compatible con T, incluso si el valor enlazado llega como null
  • 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:

  • RequestArgumentResolver
  • RequestValidationExecutor
  • FilterFactoryHelper

Esto ayuda a mantener coherencia entre Minimal API y MVC.

Requisitos

  • ASP.NET Core 8, 9 o 10
  • Pitasoft.Validation
  • Pitasoft.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.AspNetCore para 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.3 117 4/3/2026
1.0.2 116 4/2/2026
1.0.1 109 4/1/2026