我正在研究.NET Core 2 API项目,并且一直在尝试实现通用的字符串修剪模型绑定程序,该绑定程序将修剪提供的请求参数和字段值的所有字符串值。到目前为止,我取得了好坏参半的结果,并且正在努力寻找可以为我指明正确方向的可行例子。我一直在尝试实现与this相同的模型活页夹。
对于通过直接参数(例如public IActionResult Profile(string username)
)传递到控制器动作的所有字符串值,此模型绑定程序都适用,但是对于复杂对象中的字符串字段,{{1}的BindModelAsync
方法}类永远不会被调用。我的控制器中的HttpPost操作示例为TrimmingModelBinder
。模型绑定器似乎没有检查复杂模型的字段。对于字符串列表的字段,它也不起作用。
我记得在.NET Core之前,指定字符串修剪模型绑定程序将递归检查复杂模型的每个字段,甚至是复杂模型中的模型。 .NET Core中似乎并非如此,但我可能是错的。我的项目的目标是public IActionResult Profile([FormBody] ProfileLookupModel model)
框架。
我很好奇是否有人和我有同样的问题,并且可能找到解决方案。
注意:我尚未发布任何示例代码,因为它与所引用文章中的代码相同。
答案 0 :(得分:1)
我在这里加2美分。我没有使用某种模型绑定挂钩,而是去了一个动作过滤器。优点之一是开发人员可以选择要使用的操作,而不是对所有请求和模型绑定进行此处理(不是这样做应该对性能产生太大影响)。 Btw动作过滤器也可以全局应用。
这是我的代码,首先创建一个动作过滤器。
public class TrimInputStringsAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
foreach (var arg in context.ActionArguments)
{
if (arg.Value is string)
{
string val = arg.Value as string;
if (!string.IsNullOrEmpty(val))
{
context.ActionArguments[arg.Key] = val.Trim();
}
continue;
}
Type argType = arg.Value.GetType();
if (!argType.IsClass)
{
continue;
}
TrimAllStringsInObject(arg.Value, argType);
}
}
private void TrimAllStringsInObject(object arg, Type argType)
{
var stringProperties = argType.GetProperties()
.Where(p => p.PropertyType == typeof(string));
foreach (var stringProperty in stringProperties)
{
string currentValue = stringProperty.GetValue(arg, null) as string;
if (!string.IsNullOrEmpty(currentValue))
{
stringProperty.SetValue(arg, currentValue.Trim(), null);
}
}
}
}
要使用它,请注册为全局过滤器,或使用TrimInputStrings属性装饰您的操作。
[TrimInputStrings]
public IActionResult Register(RegisterViewModel registerModel)
{
// Some business logic...
return Ok();
}
答案 1 :(得分:0)
TrimmingModelBinder
本质上仅配置为字符串,如果失败则默认返回SimpleTypeModelBinder
或配置其他绑定器。因此,如果您的实现与TrimmingModelBinder
中的实现基本相同,那么它肯定仅适用于字符串。
对于复杂类型,我建议创建一个新的活页夹及其相应的提供程序,该提供程序将必须检查模型类型中的所有字符串属性并在绑定之前修剪值。然后将该活页夹注册到索引0,以便在尝试任何其他活页夹之前先检查其第一个活页夹。
services.AddMvc(options => option.ModelBinderProviders.Insert(0, new MyComplexTypeModelBinderProvider());