博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.NET Core 使用ModelBinder去掉所有参数的空格
阅读量:4498 次
发布时间:2019-06-08

本文共 5270 字,大约阅读时间需要 17 分钟。

一.前言

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

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

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

二:正文

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

 

public class StringTrimModelBinderProvider : IModelBinderProvider    {        private readonly IList
_formatters; public StringTrimModelBinderProvider(IList
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
()); } //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
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));            })

 

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

 

转载于:https://www.cnblogs.com/FateHuli/p/11328764.html

你可能感兴趣的文章
C++ 通过对象方式 、指针方式两种方式去访问成员变量(属性或者方法)
查看>>
JS根据key值获取URL中的参数值,以及把URL的参数转换成json对象
查看>>
HDU 5496 Beauty of Sequence
查看>>
HDU 5656 CA Loves GCD 01背包+gcd
查看>>
BZOJ 1854: [Scoi2010]游戏 无向图判环
查看>>
php从数组中取出一段 之 array_slice
查看>>
Python操作文件-20181121
查看>>
Angular之constructor和ngOnInit差异及适用场景(转)
查看>>
Extjs4实现客户端搜索(过滤数据)
查看>>
学习TF:《TensorFlow技术解析与实战》PDF+代码
查看>>
3.4 变量
查看>>
[转]Timer和TimerTask
查看>>
MAC下Android的Eclipse开发环境的搭建
查看>>
svn安装
查看>>
CF 914 D. Bash and a Tough Math Puzzle
查看>>
802.11网络协议细节(二)
查看>>
进击的Objective-C------------内存
查看>>
c++约瑟夫环问题
查看>>
EasyPlayer RTSP安卓Android播放器架构简析
查看>>
windows上使用clang编译程序
查看>>