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

ASP.NET Web API控制器输入值预处理:自定义属性替换*为%可行吗?

实现输入参数预处理的可行方案

一、自定义[ProcessForSql]属性方案(你的预期方案完全可行)

你可以通过自定义模型绑定器+标记属性的组合实现这个需求,具体步骤如下:

1. 定义标记属性

[AttributeUsage(AttributeTargets.Parameter)]
public class ProcessForSqlAttribute : Attribute
{
}

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

负责实际的参数替换逻辑:

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

        // 获取客户端传入的原始参数值
        var rawValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).FirstValue;
        if (string.IsNullOrEmpty(rawValue))
        {
            bindingContext.Result = ModelBindingResult.Success(rawValue);
            return Task.CompletedTask;
        }

        // 执行替换逻辑:* 替换为 %
        var processedValue = rawValue.Replace('*', '%');
        bindingContext.Result = ModelBindingResult.Success(processedValue);
        return Task.CompletedTask;
    }
}

3. 关联属性与绑定器

有两种方式完成关联:

  • 方式一:让属性直接指定绑定器
    修改属性类,继承ModelBinderAttribute:
[AttributeUsage(AttributeTargets.Parameter)]
public class ProcessForSqlAttribute : ModelBinderAttribute
{
    public ProcessForSqlAttribute()
    {
        BinderType = typeof(ProcessForSqlModelBinder);
    }
}
  • 方式二:全局注册绑定规则
    在Program.cs中添加全局绑定器提供器,自动识别带标记的参数:
builder.Services.AddControllers(options =>
{
    options.ModelBinderProviders.Insert(0, new ProcessForSqlBinderProvider());
});

// 自定义绑定器提供器
public class ProcessForSqlBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        // 检查参数是否带有ProcessForSqlAttribute标记
        if (context.ParameterInfo?.GetCustomAttribute<ProcessForSqlAttribute>() != null)
        {
            return new ProcessForSqlModelBinder();
        }
        return null;
    }
}

4. 在控制器中使用

直接给参数标记属性即可:

[HttpGet]
public IList<string> Search([ProcessForSql] string pattern)
{
    // 此处的pattern已完成替换:客户端传Jo*,这里拿到的是Jo%
    // 业务逻辑实现
    return new List<string>();
}

二、其他更简洁的替代方案

1. 方法内直接处理(适合单个方法场景)

如果只有这一处需要预处理,直接在方法内替换是最省事的:

[HttpGet]
public IList<string> Search(string pattern)
{
    if (!string.IsNullOrEmpty(pattern))
    {
        pattern = pattern.Replace('*', '%');
    }
    // 业务逻辑
    return new List<string>();
}

2. 动作过滤器(适合批量处理多个方法)

通过过滤器在方法执行前统一修改参数:

public class ProcessForSqlFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.ActionArguments.TryGetValue("pattern", out var value) && value is string rawPattern)
        {
            if (!string.IsNullOrEmpty(rawPattern))
            {
                context.ActionArguments["pattern"] = rawPattern.Replace('*', '%');
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) { }
}

注册过滤器(全局或局部):

// 全局注册
builder.Services.AddControllers(options =>
{
    options.Filters.Add<ProcessForSqlFilter>();
});

// 局部注册(控制器或方法上)
[ServiceFilter(typeof(ProcessForSqlFilter))]
public class YourController : ControllerBase
{
    // ...
}

总结

  • 若需复用预处理逻辑到多个参数/方法,自定义属性+模型绑定器的方案最符合你的预期,也最优雅;
  • 单一场景下,方法内直接替换是最简洁的选择;
  • 批量处理多个方法的相同参数时,动作过滤器更高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 17:20:26