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

ASP.NET 6+中如何让[FromQuery]支持多格式参数名匹配?

在ASP.NET 6+中实现[FromQuery]参数名的自动兼容(下划线/连字符)

完全可以在参数匹配的早期管道阶段介入处理,通过自定义值提供器(ValueProvider)或者中间件两种方式,让[FromQuery] bool testValue自动匹配testValue、test-value、test_value三种查询参数格式。

方案一:自定义QueryStringValueProvider(推荐)

这种方式仅在模型绑定阶段生效,不会修改原始请求的查询字符串,更符合ASP.NET的设计规范。

1. 实现自定义值提供器

继承QueryStringValueProvider,重写GetValue方法,同时检查原始参数名、kebab-case(连字符分隔)、snake_case(下划线分隔)三种格式的查询键:

public class FlexibleQueryStringValueProvider : QueryStringValueProvider
{
    public FlexibleQueryStringValueProvider(BindingSource bindingSource, QueryString queryString, CultureInfo culture)
        : base(bindingSource, queryString, culture)
    {
    }

    public override ValueProviderResult GetValue(string key)
    {
        // 优先匹配原始参数名
        var result = base.GetValue(key);
        if (result != ValueProviderResult.None)
            return result;

        // 转换为kebab-case格式匹配(如testValue → test-value)
        var kebabKey = string.Concat(key.Select((c, i) => 
            i > 0 && char.IsUpper(c) ? $"-{char.ToLower(c)}" : c.ToString()));
        result = base.GetValue(kebabKey);
        if (result != ValueProviderResult.None)
            return result;

        // 转换为snake_case格式匹配(如testValue → test_value)
        var snakeKey = string.Concat(key.Select((c, i) => 
            i > 0 && char.IsUpper(c) ? $"_{char.ToLower(c)}" : c.ToString()));
        return base.GetValue(snakeKey);
    }
}

2. 实现值提供器工厂

创建工厂类用于生成自定义值提供器:

public class FlexibleQueryStringValueProviderFactory : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        var query = context.ActionContext.HttpContext.Request.Query;
        if (!query.Any())
            return Task.CompletedTask;

        var valueProvider = new FlexibleQueryStringValueProvider(
            BindingSource.Query,
            query,
            CultureInfo.CurrentCulture);

        context.ValueProviders.Add(valueProvider);
        return Task.CompletedTask;
    }
}

3. 替换默认值提供器

在Program.cs中注册自定义工厂,替换默认的查询字符串值提供器:

builder.Services.AddControllers(options =>
{
    // 移除默认的QueryStringValueProviderFactory
    var defaultFactory = options.ValueProviderFactories
        .FirstOrDefault(f => f is QueryStringValueProviderFactory);
    if (defaultFactory != null)
    {
        options.ValueProviderFactories.Remove(defaultFactory);
    }
    // 添加自定义工厂
    options.ValueProviderFactories.Add(new FlexibleQueryStringValueProviderFactory());
});

方案二:使用中间件重写查询字符串

这种方式在请求管道的更早阶段修改查询字符串,将所有带-和_的键转换为驼峰格式,让默认的模型绑定器直接匹配:

1. 实现中间件

public class QueryStringNormalizationMiddleware
{
    private readonly RequestDelegate _next;

    public QueryStringNormalizationMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var queryBuilder = new QueryBuilder();
        foreach (var (key, values) in context.Request.Query)
        {
            // 将test-value、test_value转换为testValue
            var normalizedKey = NormalizeQueryKey(key);
            queryBuilder.Add(normalizedKey, values.ToArray());
        }

        // 替换原始查询字符串
        context.Request.QueryString = queryBuilder.ToQueryString();

        await _next(context);
    }

    private string NormalizeQueryKey(string key)
    {
        var sb = new StringBuilder();
        bool capitalizeNext = false;
        foreach (var c in key)
        {
            if (c == '-' || c == '_')
            {
                capitalizeNext = true;
                continue;
            }
            sb.Append(capitalizeNext ? char.ToUpper(c) : c);
            capitalizeNext = false;
        }
        return sb.ToString();
    }
}

2. 注册中间件

在Program.cs中添加中间件(注意要放在UseRouting之前):

app.UseMiddleware<QueryStringNormalizationMiddleware>();
app.UseRouting();

两种方案都能实现需求,其中方案一的侵入性更低,仅针对模型绑定逻辑生效,更推荐在生产环境使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 12:31:03