You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Minimal API原生参数校验与OpenAPI文档优化方案咨询

问题背景

我已有可运行的代码,但希望找到更优实现方式。

需求说明

  1. 为ASP.NET Minimal API方法中的原生参数添加注解,该注解需同步至OpenAPI文档,且不会误导后续开发者(RangeAttribute存在误导性);
  2. 实现对原生类型参数的校验。

已实现内容

基于Stack Overflow相关方案,我已完成以下实现:

  • 自定义Validate扩展方法,结合Fluent Validation实现参数校验;
  • 自定义IntRangeValidator校验器,用于整数范围校验;
  • 通过SchemaFilter实现OpenAPI文档中参数的Schema修改。

现有疑问

  1. 是否存在更简洁的实现方案,减少组件依赖与代码复杂度?
  2. 在路由构建流程中,是否有其他方法可直接获取参数信息(名称、类型、自定义属性),替代现有存在位置定位问题的Validate扩展方法?

优化方案建议

针对疑问1:简化实现、减少依赖

可以直接利用ASP.NET Core原生能力完成,无需依赖Fluent Validation,核心是自定义验证属性+OpenAPI元数据扩展二合一:

  1. 自定义明确的验证属性:继承ValidationAttribute,实现整数范围校验逻辑,用直观的命名(比如IntRangeAttribute)避免RangeAttribute的误导性:
    public class IntRangeAttribute : ValidationAttribute, IParameterFilter
    {
        private readonly int _min;
        private readonly int _max;
    
        public IntRangeAttribute(int min, int max)
        {
            _min = min;
            _max = max;
            ErrorMessage = $"值必须在{_min}到{_max}之间";
        }
    
        // 实现参数校验逻辑
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value is int intValue && (intValue < _min || intValue > _max))
            {
                return new ValidationResult(ErrorMessage);
            }
            return ValidationResult.Success;
        }
    
        // 同步更新OpenAPI文档元数据
        public void Apply(OpenApiParameter parameter, ParameterFilterContext context)
        {
            if (parameter.Schema != null)
            {
                parameter.Schema.Minimum = _min;
                parameter.Schema.Maximum = _max;
                parameter.Schema.ExclusiveMinimum = false;
                parameter.Schema.ExclusiveMaximum = false;
            }
        }
    }
    
  2. 使用方式:直接给Minimal API的参数标记该属性即可,同时完成校验和OpenAPI文档同步:
    app.MapGet("/api/items/{id}", ([IntRange(1, 1000)] int id) => Results.Ok(id))
       .WithOpenApi();
    

这套方案完全基于ASP.NET Core原生API,无额外组件依赖,代码复杂度大幅降低。

针对疑问2:路由流程中参数信息的可靠获取方案

推荐使用Minimal API原生的EndpointFilter机制,替代容易出定位问题的扩展方法,能直接、准确地获取参数的完整元数据:

  1. 单端点局部过滤器:
    app.MapGet("/api/items/{id}", ([IntRange(1, 1000)] int id) => Results.Ok(id))
       .AddEndpointFilter(async (context, next) =>
       {
           var parameters = context.MethodInfo.GetParameters();
           foreach (var param in parameters)
           {
               // 获取参数上的所有自定义验证属性
               var validationAttrs = param.GetCustomAttributes<ValidationAttribute>();
               foreach (var attr in validationAttrs)
               {
                   // 根据参数位置获取对应值
                   var paramIndex = Array.IndexOf(parameters, param);
                   var paramValue = context.Arguments[paramIndex];
                   // 执行校验
                   var result = attr.GetValidationResult(paramValue, new ValidationContext(context.HttpContext));
                   if (result != ValidationResult.Success)
                   {
                       return Results.BadRequest(result.ErrorMessage);
                   }
               }
           }
           return await next(context);
       })
       .WithOpenApi();
    
  2. 全局过滤器复用:如果多个端点需要校验,可封装成全局过滤器避免重复代码:
    public class GlobalParamValidationFilter : IEndpointFilter
    {
        public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
        {
            var parameters = context.MethodInfo.GetParameters();
            foreach (var param in parameters)
            {
                foreach (var attr in param.GetCustomAttributes<ValidationAttribute>())
                {
                    var paramValue = context.Arguments[Array.IndexOf(parameters, param)];
                    var result = attr.GetValidationResult(paramValue, new ValidationContext(context.HttpContext));
                    if (result != ValidationResult.Success)
                    {
                        return Results.BadRequest(result.ErrorMessage);
                    }
                }
            }
            return await next(context);
        }
    }
    
    // 注册全局过滤器
    builder.Services.AddScoped<GlobalParamValidationFilter>();
    
    // 使用时直接添加
    app.MapGet("/api/items/{id}", ([IntRange(1, 1000)] int id) => Results.Ok(id))
       .AddEndpointFilter<GlobalParamValidationFilter>()
       .WithOpenApi();
    

这种方式基于Minimal API的原生扩展点,参数定位准确,不会出现位置偏移问题,能直接获取参数的名称、类型、自定义属性等全部元数据。


内容的提问来源于stack exchange,提问作者Stand__Sure

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 06:42:32