一.前言

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

然后查看官网和源码之后,发现继承并实现 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(,new StringTrimModelBinderProvider(options.InputFormatters));
})

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

.NET Core 使用ModelBinder去掉所有参数的空格的更多相关文章

  1. ASP.NET Core WebApi 返回统一格式参数(Json 中 Null 替换为空字符串)

    相关博文:ASP.NET Core WebApi 返回统一格式参数 业务场景: 统一返回格式参数中,如果包含 Null 值,调用方会不太好处理,需要替换为空字符串,示例: { "respon ...

  2. 解决.NET Core Ajax请求后台传送参数过大请求失败问题

    解决.NET Core Ajax请求后台传送参数过大请求失败问题 今天在项目上遇到一个坑, 在.Net Core中通过ajax向mvc的controller传递对象时,控制器(controller)的 ...

  3. 地址栏url中去掉所有参数

    1.地址栏url中去掉所有参数,这个是纯前端解决,很多时候页面跳转时候会选择在url后面带参数过去,(使用?&),方便传也方便取,但是我们要做的是不要让页面的一些请求参数暴露在外面 正常项目工 ...

  4. C++去掉字符串中首尾空格和所有空格

    c++去掉首尾空格是参考一篇文章的,但是忘记文章出处了,就略过吧. 去掉首尾空格的代码如下: void trim(string &s) { if( !s.empty() ) { s.erase ...

  5. php中利用正则去掉中文全角空格

    一开始用$temp = trim($temp, " "); 这种方法,导致trim后的中文字符有乱码 最后 $str = " 广东君孺律师事务所 "; $str ...

  6. C# 调用命令行,参数有空格

    在程序中调用cmd命令打开一个文件,而文件路径带有空格,如果直接把路径传给cmd,那么cmd就会把路径空格前面的部分当做是一个参数,空格后当做另一个参数,命令行执行把后边截掉了,导致程序出错,会弹出了 ...

  7. 关于一些url中传递参数有空格问题

    1.关于一些url中传递参数有空格问题: url.replace(/ /g, "%20") 从上面的例子中可以看到可以用:replace(/ /g, "%20" ...

  8. as3中去掉字符串两边的空格,换行符

     as3 去掉字符串两边的空格,换行符,方法一  ActionScript Code  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20   pub ...

  9. ios 去掉字符串中的空格 和指定的字符

    [问题分析] .使用NSString中的stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]方法只是去掉左右 ...

随机推荐

  1. 服务器更新了php版本报错(PHP7.3)

      Warning: "continue" targeting switch is equivalent to "break". Error:"con ...

  2. mysql中的sql-mode导致的datetime类型字段不能为0000

    问题描述: 在执行建表语句的时候,出现invalid default datetime value '0000-00-00 00:00:00',从字面意思看,就是不合法的默认值'0000-00-00 ...

  3. 阶段5 3.微服务项目【学成在线】_day17 用户认证 Zuul_17-身份校验-身份校验过虑器编写

    5 身份校验 5.1 需求分析 本小节实现网关连接Redis校验令牌: 1.从cookie查询用户身份令牌是否存在,不存在则拒绝访问 2.从http header查询jwt令牌是否存在,不存在则拒绝访 ...

  4. 算法习题---3.11换抵挡装置(UVa1588)

    一:题目 给你连个长度分别为n1,n2且每列高度只为1或2的长条,然后将他们拼在一起,高度不能超过3,问他们拼在一起的最短长度 二:实现思路 1.获取主动轮和从动轮的数据. 2.主动轮不动,从动轮从左 ...

  5. java判断请求是否ajax异步请求

    java判断请求是否ajax异步请求   解决方法: if (request.getHeader("x-requested-with") != null && re ...

  6. CentOS7下搭建zabbix监控(五)——Web端配置自动发现并注册

    好像有点问题,没法自动添加主机,我后期再测测 (1).自动发现主机并注册 1)创建发现规则 2)编辑自动发现规则信息(这两步不配置问题也不大,因为在动作中也有主机IP地址) 3)添加自动发现的动作 4 ...

  7. Java点滴-List<Integer> list; 中尖括号的意思

    这是jdk1.5后版本才有的新特性,泛型,指定传入的类型.这样定义之后,这个list只能接收Integer的对象. 以前没有加这个,传入的都是Object类型的,取出来的时候要强制类型转换为自己想要的 ...

  8. 【Leetcode_easy】788. Rotated Digits

    problem 788. Rotated Digits solution1: class Solution { public: int rotatedDigits(int N) { ; ; i< ...

  9. Azure DevOps的variable group实现array和hashtable参数的传递

    Azure Devops中的variable group建议或者只能(?)添加string类型的value.基于此我们想在variable group实现array或者hashtable的传递的核心思 ...

  10. Docker 镜像小结---操作指令介绍(七)

    目录 一.搜索镜像 二.下载镜像 三.查看本地镜像 四.显示镜像构建历史 五.删除镜像 六.镜像创建 七.上传镜像 八.给镜像打 tag 九.存出和载入镜像 一.搜索镜像 很多情况下我们可能需要下载某 ...