asp.net minimal API, validation of a primitive parameter, and OpenAPI documentation

39 Views Asked by At

I have working code but am hoping there is a better way...

Problem:

  • annotate a parameter in a method used in a minimal API in a way that informs OpenAPI (but does not mislead a future developer -- RangeAttribute is misleading)
  • do validation of a primitive type

Based on this Using DataAnnotation Model Validation in Minimal Api, I have the following validator

public static RouteHandlerBuilder Validate<T>(this RouteHandlerBuilder builder, IValidator<T?> validator, int? position = null)
{
    builder.AddEndpointFilter(RouteHandlerFilter);

    return builder;

    async ValueTask<object?> RouteHandlerFilter(EndpointFilterInvocationContext invocationContext, EndpointFilterDelegate next)
    {
        T? argument = position.HasValue ? invocationContext.GetArgument<T>(position.Value) : invocationContext.Arguments.OfType<T>().FirstOrDefault();
            
        ValidationResult? validationResult = await validator.ValidateAsync(argument).ConfigureAwait(false);

        return validationResult.IsValid ? await next(invocationContext) : TypedResults.ValidationProblem(validationResult.ToDictionary());
    }
}

which is using a Fluent Validations validator

internal class IntRangeValidator : AbstractValidator<int?>
{
    public IntRangeValidator(int min = int.MinValue, int max = int.MaxValue)
    {
        this.RuleFor(i => i).NotNull().InclusiveBetween(min, max);
    }
}

which is added to the route via

// IEndpointRouteBuilder app
app.MapGet( /* ... */ ).Validate(new IntRangeValidator(1));

Since .WithOpenApi(operation => { /* ... */ }) is unable to modify the schema of the parameter, the following is used

internal class PositiveSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.ParameterInfo?.GetCustomAttribute<PositiveAttribute>() != null)
        {
            schema.Minimum = 1;
        }
    }
}
// SwaggerGenOptions options
options.SchemaFilter<PositiveSchemaFilter>();

Questions:

  1. Does anyone have a more compact approach that doesn't need as many moving parts?
  2. Is there some other "magic" method in the route building process that allows access to the parameter info (name, type, custom attributes) that could be used in lieu of the Validate extension method (and without its positional weirdness)?
0

There are 0 best solutions below