查看: 91|回复: 0

ASP.NET Core 去除请求参数的空格

[复制链接]

3

主题

4

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2023-4-26 15:40:52 | 显示全部楼层 |阅读模式
在http://ASP.NET Core WebApi项目中,后端接收用户输入时通常需要做去除空格处理,通过查看官网和源码后,发现继承并实现 IModelBinder和IModelBinderProvider即可。
我们知道,模型绑定有[FromQuery]、[FromRoute]、[FromForm]、[FromBody]等多种绑定方式,我们先从简单类型着手,处理[FromQuery]、[FromRoute]这些情况
处理简单类型

先定义一个简单类型的Trim绑定器SimpleStringTrimModelBinder
    /// <summary>
    /// 简单类型Trim绑定器
    /// </summary>
    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 valueProviderResult = valueProvider.GetValue(bindingContext.ModelName);

            if (valueProviderResult != ValueProviderResult.None)
            {
                bindingContext.Result = ModelBindingResult.Success(valueProviderResult.FirstValue.Trim());
                return Task.CompletedTask;
            }

            //调用默认绑定
            SimpleTypeModelBinder simpleTypeModelBinder = new SimpleTypeModelBinder(_type, (ILoggerFactory)bindingContext.HttpContext.RequestServices.GetService(typeof(ILoggerFactory)));
            return simpleTypeModelBinder.BindModelAsync(bindingContext);
        }
    }
再定义一个简单类型Trim绑定提供器StringTrimModelBinderProvider
    /// <summary>
    /// 简单类型Trim绑定提供器,用于[FromQuery]参数Trim处理
    /// </summary>
    public class StringTrimModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (!context.Metadata.IsComplexType && context.Metadata.ModelType == typeof(string))
            {
                //简单类型
                return new SimpleStringTrimModelBinder(context.Metadata.ModelType);
            }

            return null;
        }
    }
最后在Program.cs中注册该提供器
    ......
    builder.Services.AddControllers(option =>
    {
        option.ModelBinderProviders.Insert(0, new StringTrimModelBinderProvider());
    });
    ......
此时,在Controller中使用 [FromQuery] 、[FromRoute] 解析请求参数时,即可默认去除空格
        [HttpGet]
        public IActionResult findAll([FromQuery] string name)
        {
            //name等参数默认去除空格
        }
处理复杂类型

那么针对[FromBody]这种绑定复杂类型的,如果继续沿用上面的思路,则需要构建一个复杂类型模型绑定器,通过反射逐个解析每一个属性,再针对string类型去除空格,虽然技术层面仍可以实现,但考虑到复杂类型的属性嵌套,就不免有些复杂了。我们不妨换一种思路:http://ASP.NET Core框架在将Request.Body解析到指定实体类的过程中,是通过System.Text.Json实现json反序列化的,那么在其json反序列的过程中,将string类型的属性去除空格即可。定义以下StringTrimJsonConverter
    using System.Text.Json;
    using System.Text.Json.Serialization;   

    /// <summary>
    /// 用于[FromBody]属性中的string参数Trim处理
    /// </summary>
    public class StringTrimJsonConverter : JsonConverter<string>
    {
        public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return reader.GetString().Trim();
        }

        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value);
        }
    }
最后在Program.cs中注册该json转换器:
        ......
        builder.Services.AddControllers()
        .AddJsonOptions(option =>
        {
            option.JsonSerializerOptions.Converters.Add(new StringTrimJsonConverter());
        });
        ......
此时,在Controller中使用 [FromBody] 解析请求参数属性时,即可默认去除空格
        [HttpPost]
        public IActionResult save([FromBody] ApiDto apiDto)
        {
            //apiDto.Name属性默认去除空格
        }
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表