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

在.NET中读取名称含冒号的Query参数并验证后缀的实现方法

实现方案

1. 定义基础结构

先定义参数接收类和允许的操作符范围:

// 时间查询参数接收类
public class EventDateTimeFilter
{
    public DateTimeOffset Time { get; set; }
    // 操作符,无后缀时默认值为eq
    public string Operator { get; set; } = "eq";
}

允许的操作符可以定义为常量数组,后续绑定校验时直接使用:

private static readonly string[] _allowedOperators = new[] { "eq", "gte", "lte", "gt", "lt", "neq" };

2. 实现自定义模型绑定器

这个方案的核心是通过自定义模型绑定器遍历查询字符串,匹配对应前缀的参数并解析后缀:

using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Globalization;

public class EventDateTimeBinder : IModelBinder
{
    private const string _paramPrefix = "eventCreatedDateTime";
    private static readonly string[] _allowedOperators = new[] { "eq", "gte", "lte", "gt", "lt", "neq" };

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext));

        // 遍历所有查询参数键匹配目标参数
        foreach (var queryKey in bindingContext.HttpContext.Request.Query.Keys)
        {
            if (!queryKey.StartsWith(_paramPrefix, StringComparison.OrdinalIgnoreCase))
                continue;

            string op = null;
            // 解析带操作符的后缀
            if (queryKey.Contains(':'))
            {
                var keyParts = queryKey.Split(':', StringSplitOptions.RemoveEmptyEntries);
                if (keyParts.Length != 2)
                {
                    bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "参数格式错误,正确格式为:eventCreatedDateTime[:操作符]");
                    return Task.CompletedTask;
                }
                op = keyParts[1].ToLower().Trim();
                // 校验操作符合法性
                if (!_allowedOperators.Contains(op))
                {
                    bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, $"不支持的操作符 {op},允许值为:{string.Join("、", _allowedOperators)}");
                    return Task.CompletedTask;
                }
            }

            // 提取并解析时间值
            var valueResult = bindingContext.ValueProvider.GetValue(queryKey);
            if (!DateTimeOffset.TryParse(valueResult.FirstValue, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out var time))
            {
                bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "时间格式无效,请使用ISO 8601标准格式");
                return Task.CompletedTask;
            }

            // 返回绑定结果
            var filter = new EventDateTimeFilter
            {
                Time = time,
                Operator = op ?? "eq"
            };
            bindingContext.Result = ModelBindingResult.Success(filter);
            return Task.CompletedTask;
        }

        // 未传该参数时返回空
        bindingContext.Result = ModelBindingResult.Success(null);
        return Task.CompletedTask;
    }
}

3. 接口中使用绑定器

直接在接口参数上指定绑定器即可:

[ApiController]
[Route("api/[controller]")]
public class MyController : ControllerBase
{
    [HttpGet]
    public IActionResult Query(
        [FromQuery] string param1,
        [FromQuery] string param2,
        [FromQuery, ModelBinder(BinderType = typeof(EventDateTimeBinder))] EventDateTimeFilter eventCreatedDateTime,
        [FromQuery] string param4)
    {
        // 业务逻辑直接使用 eventCreatedDateTime.Operator 和 eventCreatedDateTime.Time 即可
        return Ok();
    }
}

4. Swagger兼容处理

默认Swagger无法识别带后缀的参数格式,需要添加操作过滤器自定义参数描述:

using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

public class EventDateTimeSwaggerFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var targetParam = context.MethodInfo.GetParameters().FirstOrDefault(p => p.ParameterType == typeof(EventDateTimeFilter));
        if (targetParam == null) return;

        // 移除默认生成的错误参数
        var defaultParam = operation.Parameters.FirstOrDefault(p => p.Name.Equals("eventCreatedDateTime", StringComparison.OrdinalIgnoreCase));
        if (defaultParam != null) operation.Parameters.Remove(defaultParam);

        // 添加自定义参数说明
        operation.Parameters.Add(new OpenApiParameter
        {
            Name = "eventCreatedDateTime[:op]",
            In = ParameterLocation.Query,
            Description = "时间查询参数,可选操作符后缀支持eq/gte/lte/gt/lt/neq,默认eq,示例:eventCreatedDateTime:gte=2021-04-01T14:12:56+01:00",
            Required = false,
            Schema = new OpenApiSchema { Type = "string", Format = "date-time" }
        });
    }
}

在Program.cs中注册过滤器:

builder.Services.AddSwaggerGen(opt =>
{
    opt.OperationFilter<EventDateTimeSwaggerFilter>();
});

如果有多个同类型参数需要支持这种后缀格式,可以将绑定器改造为通用版本,把参数前缀、允许操作符列表改为可配置项即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:45:05