zoukankan      html  css  js  c++  java
  • .NET Core 使用ModelBinder去掉所有参数的空格

    一.前言

      通过各种姿势搜索都没搜到这方面的,唯一找到一个比较符合的,但是只适合简单类型,而且代码还没贴全,心累。。

    然后查看官网和源码之后,发现继承并实现 IModelBinder和IModelBinderProvider 即可。

    我这里是WebApi,所以要区分绑定属性[FromBody]、[FromForm]等。不同的绑定方法要实现不同的IModelBinder。

    二:正文

      api主要设计到的就是[FromBody]和[FromQuery],我这里也只实现了这两种,其余的方式没测试过。

    public class StringTrimModelBinderProvider : IModelBinderProvider
        {
            private readonly IList<IInputFormatter> _formatters;
    
            public StringTrimModelBinderProvider(IList<IInputFormatter> formatters)
            {
                _formatters = formatters;
            }
    
            public IModelBinder GetBinder(ModelBinderProviderContext context)
            {
                if (context == null)
                    throw new ArgumentNullException(nameof(context));
    
                if (!context.Metadata.IsComplexType && context.Metadata.ModelType == typeof(string))
                {
                    //简单类型
                    var loggerFactory = (ILoggerFactory)context.Services.GetService(typeof(ILoggerFactory));
                    return new SimpleStringTrimModelBinder(context.Metadata.ModelType);
                }
                else if (context.BindingInfo.BindingSource != null &&
                    context.BindingInfo.BindingSource.CanAcceptDataFrom(BindingSource.Body))
                {
                    //通过[FromBody]绑定的
                    return new BodyStringTrimModelBinder(_formatters, context.Services.GetRequiredService<IHttpRequestStreamReaderFactory>());
                }
                //else
                //if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
                //{
                //    //复杂类型
                //    var propertyBinders = context.Metadata.Properties
                //        .ToDictionary(modelProperty => modelProperty, modelProperty => context.CreateBinder(modelProperty));
                //    var loggerFactory = (ILoggerFactory)context.Services.GetService(typeof(ILoggerFactory));
                //    return new AComplexTypeModelBinder(propertyBinders);
                //}
    
                return null;
            }
        }

    下面的是实现IModelBinder

    public class SimpleStringTrimModelBinder : IModelBinder
        {
            private readonly Type _type;
    
            public SimpleStringTrimModelBinder(Type type)
            {
                _type = type;
            }
    
            public Task BindModelAsync(ModelBindingContext bindingContext)
            {
                if (bindingContext == null)
                {
                    throw new ArgumentNullException(nameof(bindingContext));
                }
                var valueProvider = bindingContext.ValueProvider;
                var modelName = bindingContext.ModelName;
                var valueProviderResult = valueProvider.GetValue(modelName);
    
                if (valueProviderResult == ValueProviderResult.None)
                {
                    return Task.CompletedTask;
                }
                string value = valueProviderResult.FirstValue.Trim();
                //bindingContext.ModelState.SetModelValue(modelName, new ValueProviderResult(value));
                //替换原有ValueProvider
                bindingContext.ValueProvider = new CompositeValueProvider
                    {
                        new ElementalValueProvider(modelName, value, valueProviderResult.Culture),
                        bindingContext.ValueProvider
                    };
                //调用默认系统绑定
                SimpleTypeModelBinder simpleTypeModelBinder = new SimpleTypeModelBinder(_type, (ILoggerFactory)bindingContext.HttpContext.RequestServices.GetService(typeof(ILoggerFactory)));
                simpleTypeModelBinder.BindModelAsync(bindingContext);
                //bindingContext.Result = ModelBindingResult.Success(value);
                return Task.CompletedTask;
            }
        }
    public class BodyStringTrimModelBinder : IModelBinder
        {
            private readonly BodyModelBinder bodyModelBinder;
    
            public BodyStringTrimModelBinder(IList<IInputFormatter> formatters, IHttpRequestStreamReaderFactory readerFactory)
            {
                bodyModelBinder = new BodyModelBinder(formatters,readerFactory);
            }
    
            public Task BindModelAsync(ModelBindingContext bindingContext)
            {
                if (bindingContext == null)
                {
                    throw new ArgumentNullException(nameof(bindingContext));
                }
                //调用原始body绑定数据
                bodyModelBinder.BindModelAsync(bindingContext);
                //判断是否设置了值
                if (!bindingContext.Result.IsModelSet)
                {
                    return Task.CompletedTask;
                }
                //获取绑定对象
                var model = bindingContext.Result.Model;
    
                /*通过反射修改值,
                也可以实现 IInputFormatter接口里面的ReadAsync方法,自己从Request.Body里面获取数据进行处理,但是那样考虑的比较多也比较复杂,原谅我能力有限。。*/
                var stringPropertyInfo = model.GetType().GetProperties().Where(c=>c.PropertyType == typeof(string));
                foreach (PropertyInfo property in stringPropertyInfo)
                {
                    string value = property.GetValue(model)?.ToString()?.Trim();
                    property.SetValue(model, value);
                }
                //bindingContext.Result = ModelBindingResult.Success(value);
                return Task.CompletedTask;
            }
        }

    最后,需要将我们自定义的在Startup注册进去,

    services.AddMvc(options =>
                {
                    //需要插入到第一条,内置默认是匹配到合适的Provider就不会在向下继续绑定;如果添加到末尾,即不会调用到我们实现的
                    options.ModelBinderProviders.Insert(0,new StringTrimModelBinderProvider(options.InputFormatters));
                })

    记录成长中的点点滴滴。。

  • 相关阅读:
    POJ 1328 Radar Installation
    POJ 1700 Crossing River
    POJ 1700 Crossing River
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3069 Saruman's Army(贪心)
    poj 3069 Saruman's Army(贪心)
    Redis 笔记与总结2 String 类型和 Hash 类型
    数据分析方法有哪些_数据分析方法
    数据分析方法有哪些_数据分析方法
  • 原文地址:https://www.cnblogs.com/FateHuli/p/11328764.html
Copyright © 2011-2022 走看看