【问题标题】:ASP.NET Web API Core: complex data model binder to trim stringsASP.NET Web API Core:用于修剪字符串的复杂数据模型绑定器
【发布时间】:2017-11-02 16:07:19
【问题描述】:

有人可以阐明如何为复杂类型实现模型绑定器吗? 我希望修剪所有字符串属性。我尝试了以下但 永远不会调用“SetProperty”方法。

public class TrimmingModelBinder : ComplexTypeModelBinder  
{
    public TrimmingModelBinder(IDictionary propertyBinders) : base(propertyBinders)
    {
    }

    protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
    {
        if(result.Model is string)
        {
            string resultStr = (result.Model as string).Trim();
            result = ModelBindingResult.Success(resultStr);
        }

        base.SetProperty(bindingContext, modelName, propertyMetadata, result);
    }
}

public class TrimmingModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
        {
            var propertyBinders = context.Metadata.Properties.ToDictionary(p => p, context.CreateBinder);
            return new TrimmingModelBinder(propertyBinders);
        }

        return null;
    }
}

【问题讨论】:

标签: c# asp.net asp.net-web-api


【解决方案1】:

我们是这样做的。

一个简单的辅助扩展方法:

static class NormalizeString
{
    public static string TrimAndNullIfWhiteSpace(this string text) =>
       string.IsNullOrWhiteSpace(text)
       ? null
       : text.Trim();
}

为字符串创建自定义 ModelBinder:

public class StringModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var modelName = bindingContext.ModelName;
        if (modelName == NullOrWhiteSpace)
            return Task.CompletedTask;

        var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
        if(valueProviderResult == ValueProviderResult.None)
            return Task.CompletedTask;

        bindingContext.Result = ModelBindingResult.Success(
            valueProviderResult.FirstValue.TrimAndNullIfWhiteSpace());

        return Task.CompletedTask;
    }
}

创建一个引用自定义 ModelBinder 的自定义 ModelBinderProvider:

public class ModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        if (context.Metadata.ModelType == typeof(string))
            return new BinderTypeModelBinder(typeof(StringModelBinder));

        return null;
    }
}

最后,在 Startup 的 ConfigureServices 中注册客户 ModelBinderProvider:

    services
        .AddMvc(o =>
        {
            o.ModelBinderProviders.Insert(0, new ModelBinderProvider());
        })

【讨论】:

  • 我已经实现了这个,到目前为止它似乎有预期的结果,所以谢谢,但是在你的 ModelBinderProvider 类中为什么不只是 return new StringModelBinder() 而不是将它包装在 BinderTypeModelBinder 类中;这样做有什么好处吗?
  • @ChristopherKing 已经好几年了,很抱歉我不记得了。当您尝试不使用 BinderTypeModelBinder 时会发生什么?
猜你喜欢
  • 2018-12-28
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
  • 2020-09-28
相关资源
最近更新 更多