.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(,new StringTrimModelBinderProvider(options.InputFormatters));
})
记录成长中的点点滴滴。。
.NET Core 使用ModelBinder去掉所有参数的空格的更多相关文章
- ASP.NET Core WebApi 返回统一格式参数(Json 中 Null 替换为空字符串)
相关博文:ASP.NET Core WebApi 返回统一格式参数 业务场景: 统一返回格式参数中,如果包含 Null 值,调用方会不太好处理,需要替换为空字符串,示例: { "respon ...
- 解决.NET Core Ajax请求后台传送参数过大请求失败问题
解决.NET Core Ajax请求后台传送参数过大请求失败问题 今天在项目上遇到一个坑, 在.Net Core中通过ajax向mvc的controller传递对象时,控制器(controller)的 ...
- 地址栏url中去掉所有参数
1.地址栏url中去掉所有参数,这个是纯前端解决,很多时候页面跳转时候会选择在url后面带参数过去,(使用?&),方便传也方便取,但是我们要做的是不要让页面的一些请求参数暴露在外面 正常项目工 ...
- C++去掉字符串中首尾空格和所有空格
c++去掉首尾空格是参考一篇文章的,但是忘记文章出处了,就略过吧. 去掉首尾空格的代码如下: void trim(string &s) { if( !s.empty() ) { s.erase ...
- php中利用正则去掉中文全角空格
一开始用$temp = trim($temp, " "); 这种方法,导致trim后的中文字符有乱码 最后 $str = " 广东君孺律师事务所 "; $str ...
- C# 调用命令行,参数有空格
在程序中调用cmd命令打开一个文件,而文件路径带有空格,如果直接把路径传给cmd,那么cmd就会把路径空格前面的部分当做是一个参数,空格后当做另一个参数,命令行执行把后边截掉了,导致程序出错,会弹出了 ...
- 关于一些url中传递参数有空格问题
1.关于一些url中传递参数有空格问题: url.replace(/ /g, "%20") 从上面的例子中可以看到可以用:replace(/ /g, "%20" ...
- 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 ...
- ios 去掉字符串中的空格 和指定的字符
[问题分析] .使用NSString中的stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]方法只是去掉左右 ...
随机推荐
- H5内嵌原生app
前言 其实我们不管是从ios还是安卓都可以看出 原生app能内嵌H5的原因是因为有了webview这个app内嵌浏览器视图,从而使得我们可以开发html然后加载到app中(原理几乎跟pc端请求.加载. ...
- Elasticsearch .net 记录-1
简介 ElasticSearch是一个开源的分布式搜索引擎,具备高可靠性,支持非常多的企业级搜索用例.像Solr4一样,是基于Lucene构建的.支持时间时间索引和全文检索.官网:http://www ...
- 最简易的python web框架的后端实现
1.源代码 #!/usr/bin/python #encoding=utf-8 from flask import json, Flask, request app = Flask(__name__) ...
- Django——models中导入数据重复的解决办法
如果你导入数据过多,导入时出错了,或者你手动停止了,导入了一部分,还有一部分没有导入.或者你再次运行上面的命令,你会发现数据重复了,怎么办呢? django.db.models 中还有一个函数叫 ge ...
- PAT 甲级 1034 Head of a Gang (30 分)(bfs,map,强连通)
1034 Head of a Gang (30 分) One way that the police finds the head of a gang is to check people's p ...
- Go项目部署到服务器
-bash: ./main: cannot execute binary file 将 go build main.go 生成的文件上传到服务器后,./main 运行后出新的报错 env GOOS=l ...
- UIScrollView实现自动循环滚动广告
实现效果如下: 功能说明: 程序运行,图片自动循环播放,采用定时器实现; 当用户用手势触摸滑动时,定时器的自动播放取消,停止触摸时,自动无限播放; 代码如下 : 采用封装视图,外部进行调用即可: 1. ...
- RobotFramework:发现一个大坑,当post接口入参为json时,千万不能用sojson转化后的json串(ride解析会有异常,非sojson工具问题),直接用浏览器粘过来的就行
问题背景: 和以往一样愉快的进行着自动化测试,突然就不停的提示我,“程序异常”,查看log发现data中的json变为了数组?????? 那算了,我不先组装入参数据直接data=json入参吧,wha ...
- Azure DevOps 利用rest api设置variable group
我们在Azure DevOps中设置参数的时候,可以使用build,release各自的variables,但是各自的变量不能共用.此时我们需要使用variable group,它允许跨Build和R ...
- CentOS 7中安装和配置Promethues
Prometheus 是什么? Prometheus是一套开源的监控&报警&时间序列数据库的组合,起始是由SoundCloud公司开发的.随着发展,越来越多公司和组织接受采用Prome ...