• .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));
                })

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

  • 相关阅读:
    用OKR让你的员工嗨起来
    用数据让我们的OKR变得“冷酷”却更有价值
    好的想法只是OKR的开始创业者谨记
    “OKR播种机”JOHN DOERR–目标是对抗纷乱思绪的一针疫苗
    用OKR提升员工的执行力
    OKR的两个基本原则
    《OKR工作法》| 一次说太多等于什么都没说
    《OKR工作法》–让所有人承担自己的职责
    《OKR工作法》——打造一支专一的团队
    Oracle wm_concat()函数的实际运用
  • 原文地址:https://www.cnblogs.com/FateHuli/p/11328764.html
Copyright © 2020-2023  润新知