一.前言

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

然后查看官网和源码之后,发现继承并实现 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. Docs-.NET-C#-指南-语言参考-预处理器指令:#undef(C# 参考)

    ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#undef(C# 参考) 1.返回顶部 1. #undef(C# 参考) 2018/06/30 #undef 允许你定义一个符 ...

  2. Android Studio 3.5新特性

    Android Studio 3.5新特性     原文链接:https://blog.csdn.net/jklwan/article/details/99974869 Android Studio ...

  3. 机器学习 - 算法 - Xgboost 数学原理推导

    工作原理 基于集成算法的多个树累加, 可以理解为是弱分类器的提升模型 公式表达 基本公式 目标函数 目标函数这里加入了损失函数计算 这里的公式是用的均方误差方式来计算 最优函数解 要对所有的样本的损失 ...

  4. 002-创建型-05-原型模式(Protype)

    一.概述 指原型实例指定创建对象的种类,并通过克隆这些原型创建新的对象 原型模式就是让类实现Cloneable接口,达到克隆原型类的方式. 1.1.适用场景 1.在创建对象的时候,我们不只是希望被创建 ...

  5. 阶段5 3.微服务项目【学成在线】_day18 用户授权_04-方法授权-方法授权实现

    2.3 方法授权实现 2.3.1资源服务添加授权控制 1.要想在资源服务使用方法授权,首先在资源服务配置授权控制 1)添加spring-cloud-starter-oauth2依赖. 2)拷贝授权配置 ...

  6. [Feature] Feature selection - Embedded topic

    基于惩罚项的特征选择法 一.直接对特征筛选 Ref: 1.13.4. 使用SelectFromModel选择特征(Feature selection using SelectFromModel) 通过 ...

  7. jquery控制一个元素是否显示

    比如说我有一个id为dlg-buttons的div元素. 我可以通过 $('#dlg-buttons').show(); 让他显示出来: 可以通过 $('#dlg-buttons').hide(); ...

  8. MySQL5.1中文文档学习笔记——第1章:一般信息(一)

    原文地址 MySQL软件是一种开放源码软件. 开放源码"意味着任何人都能使用和改变软件.任何人都能从Internet下载MySQL软件,而无需支付任何费用.如果愿意,你可以研究源码并进行恰当 ...

  9. win7下Excel2003/2010 同时打开多个独立窗口

    最近新买了本本,装了许多软件,由于许多苦逼的原因系统被我搞的乱乱的,不得已重装了几次,话说之前我用的都是台式机,用得蛮顺的,但是在重装系统之后发现自己装的Office 2003 在打开Excel 文档 ...

  10. 【Leetcode_easy】594. Longest Harmonious Subsequence

    problem 594. Longest Harmonious Subsequence 最长和谐子序列 题意: 可以对数组进行排序,那么实际上只要找出来相差为1的两个数的总共出现个数就是一个和谐子序列 ...