ASP.NET Web API Core:用于修剪字符串的复杂数据模型绑定器

时间:2017-11-02 16:07:19

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

有人可以了解如何为复杂类型实现模型绑定器吗? 我想要修剪所有字符串属性。我试过以下但是 "的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;
    }
}

1 个答案:

答案 0 :(得分: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());
        })