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
相关产品推荐
相关产品推荐

