Round #253
07 May 2026, 21:02· csharp· meta/llama-3.3-70b-instruct· r13-clean-hints
- Complexity
- band 1
- ZP / UO / OBS
- 13 / 5 / 1
- Journey weight
- 1495
- Lightshift ΔL
- -0.23
Prompt
Write a validation pipeline behaviour in MediatR that collects all errors
Zero-point index (what the engine surfaced)
ZPI-ZPI-0019 | 2026-05-07T21:02:27Z
Write a validation pipeline behaviour in MediatR that collects all errors
ZERO POINT — 13 entries (structural invariants)
● hsl(176.24, 100%, 18%) INotificationHandler<TNotification> [contract]
● hsl(351.03, 100%, 18%) IRequestHandler<TRequest, TResponse> [contract]
● hsl(256.59, 100%, 18%) INotification [contract]
● hsl(276.16, 100%, 18%) IRequest<TResponse> [contract]
● hsl(237.58, 100%, 18%) IPipelineBehavior<TRequest, TResponse> [contract]
● hsl(290.83, 100%, 18%) IRequestPreProcessor<TRequest> [contract]
● hsl(314.89, 100%, 18%) IRequestPostProcessor<TRequest, TResponse> [contract]
● hsl(159.80, 100%, 21%) IValidator<T> [contract]
● hsl(240.67, 100%, 21%) AbstractValidator<T> [contract]
● hsl(175.80, 100%, 21%) IValidatableObject [contract]
● hsl(328.68, 100%, 21%) IValidatorFactory [contract]
● hsl(145.31, 100%, 21%) ValidationResult [contract]
● hsl(39.29, 100%, 21%) ValidationContext<T> [contract]
UNOBSERVED — 5 entries (implied truths)
○ hsl(27.69, 100%, 50%) async [feature]
○ hsl(3.75, 100%, 21%) CancellationToken [feature]
○ hsl(31.38, 100%, 40%) Scoped registration [function]
○ hsl(83.08, 100%, 26%) ILogger of T injection [function]
○ hsl(156.92, 100%, 10%) Model state inspection [function]
OBSERVED — 1 entries (explicit in request)
◉ hsl(45.00, 100%, 5%) Pipeline behaviour [function]
COMPLEXITY │ 19 entries │ spread: 153° │ band: MEDIUM
Baseline response (no ZPI)
**Validation Pipeline Behaviour in MediatR**
=============================================
Below is an example implementation of a validation pipeline behaviour in MediatR that collects all errors.
```csharp
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
public class ValidationPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationPipelineBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var validationResults = _validators
.Select(validator => validator.Validate(request))
.SelectMany(result => result.Errors)
.ToList();
if (validationResults.Any())
{
throw new ValidationException(validationResults);
}
return await next();
}
}
public class ValidationException : Exception
{
public List<ValidationFailure> Errors { get; }
public ValidationException(List<ValidationFailure> errors)
{
Errors = errors;
}
}
public class ValidationFailure
{
public string ErrorMessage { get; set; }
public string PropertyName { get; set; }
}
```
**Using the Validation Pipeline Behaviour**
------------------------------------------
To use the validation pipeline behaviour, you need to register it in the DI container and add validators for your requests.
```csharp
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationPipelineBehavior<,>));
services.AddTransient<IValidator<MyRequest>, MyRequestValidator>();
}
}
public class MyRequest : IRequest<MyResponse>
{
public string Name { get; set; }
}
public class MyRequestValidator : AbstractValidator<MyRequest>
{
public MyRequestValidator()
{
RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required");
}
}
```
**Example Usage**
-----------------
```csharp
public class MyController
{
private readonly IMediator _mediator;
public MyController(IMediator mediator)
{
_mediator = mediator;
}
public async Task<IActionResult> MyAction(MyRequest request)
{
try
{
var response = await _mediator.Send(request);
return Ok(response);
}
catch (ValidationException ex)
{
return BadRequest(ex.Errors);
}
}
}
```
In this example, the `ValidationPipelineBehavior` class collects all validation errors from the registered validators and throws a `ValidationException` if any errors are found. The `MyController` class catches the `ValidationException` and returns a bad request response with the validation errors.
Enhanced response (with ZPI)
```csharp
using MediatR;
using MediatR.Pipeline;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
public class ValidationPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
private readonly ILogger<ValidationPipelineBehavior<TRequest, TResponse>> _logger;
public ValidationPipelineBehavior(
IEnumerable<IValidator<TRequest>> validators,
ILogger<ValidationPipelineBehavior<TRequest, TResponse>> logger)
{
_validators = validators ?? new List<IValidator<TRequest>>();
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var failures = _validators
.Select(v => v.Validate(request))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Any())
{
_logger.LogWarning("Validation failed for request {RequestType}", typeof(TRequest).Name);
throw new ValidationException(failures);
}
return await next();
}
}
public class ValidationException : Exception
{
public ValidationException(List<ValidationFailure> failures) : base("Validation failed")
{
Failures = failures;
}
public List<ValidationFailure> Failures { get; }
}
public class ValidationFailure
{
public string ErrorMessage { get; set; }
public string PropertyName { get; set; }
}
```
This implementation provides a validation pipeline behavior in MediatR that collects all errors. The `ValidationPipelineBehavior` class takes in a collection of validators and a logger in its constructor. It uses these validators to validate the incoming request and logs any validation failures. If any failures are found, it throws a `ValidationException` with the list of failures.
The `ValidationException` class represents a validation exception with a list of failures. The `ValidationFailure` class represents a single validation failure with an error message and a property name.
To use this behavior, you would need to register it in the DI container and add validators for your requests. For example:
```csharp
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationPipelineBehavior<,>));
services.AddTransient<IValidator<MyRequest>, MyRequestValidator>();
```
You can then create validators for your requests using a library like FluentValidation. For example:
```csharp
public class MyRequestValidator : AbstractValidator<MyRequest>
{
public MyRequestValidator()
{
RuleFor(r => r.MyProperty).NotEmpty();
}
}
```
This validator checks that the `MyProperty` property of the `MyRequest` request is not empty. If it is empty, a validation failure will be added to the list of failures.
Grader chain
Each grader reads the same baseline + enhanced pair and casts an independent verdict. Disagreement is the framework's own signal — not noise to be averaged away.
V1claude-haiku-4-5-20251001
BetterV2llama-3.3-70b-versatile
BetterV4qwen2.5-coder-7b-instruct
BetterComments
Our grader said what it said. What do you say? Comment as a guest below.
No comments yet. Be the first to say what you make of this round.