【问题标题】:API .Net - Validate query parametersAPI .Net - 验证查询参数
【发布时间】:2022-08-17 15:28:00
【问题描述】:

我有一个场景,如果值是字符串,它会忽略传递给我的查询参数的值。

示例路线

v1/data?amount=foo

这是示例代码

[HttpGet]
public async Task<IActionResult> GetData([FromQuery]decimal? amount)
{
}

所以到目前为止我尝试的是,我添加了一个 JsonConverter

public class DecimalConverter : JsonConverter
{
    public DecimalConverter()
    {
    }

    public override bool CanRead
    {
        get
        {
            return false;
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException(\"Unnecessary because CanRead is false. The type will skip the converter.\");
    }

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(decimal) || objectType == typeof(decimal?) || objectType == typeof(float) || objectType == typeof(float?) || objectType == typeof(double) || objectType == typeof(double?));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        value = CleanupDecimal(value);

        if (DecimalConverter.IsWholeValue(value))
        {
            writer.WriteRawValue(JsonConvert.ToString(Convert.ToInt64(value)));
        }
        else
        {
            writer.WriteRawValue(JsonConvert.ToString(value));
        }
    }

    private static object CleanupDecimal(object value)
    {
        if (value is null) return value;

        if (value is decimal || value is decimal?)
        {
            value = decimal.Parse($\"{value:G0}\");
        }
        else if (value is float || value is float?)
        {
            value = float.Parse($\"{value:G0}\");
        }
        else if (value is double || value is double?)
        {
            value = double.Parse($\"{value:G0}\");
        }

        return value;
    }

    private static bool IsWholeValue(object value)
    {
        if (value is decimal decimalValue)
        {
            int precision = (decimal.GetBits(decimalValue)[3] >> 16) & 0x000000FF;
            return precision == 0;
        }
        else if (value is float floatValue)
        {
            return floatValue == Math.Truncate(floatValue);
        }
        else if (value is double doubleValue)
        {
            return doubleValue == Math.Truncate(doubleValue);
        }

        return false;
    }
}

所以根据我的观察,这只适用于 [FromBody] 参数。

有没有办法在不更改数据类型的情况下验证查询参数?我知道可以将数据类型从十进制更改为字符串并验证它是否是有效数字。

更新:

我想要一个像这样的回应

{
    \"message\": \"The given data was invalid.\",
    \"errors\": {
       \"amount\": [
          \"The amount must be a number.\"
        ]
    }
}
  • 从阅读您的问题中我不清楚您想要的预期行为是什么。当他们在查询字符串中传递 \'amount\' 的字符串时,您是否试图强制做出错误的请求响应?
  • 你的意思是你想修改自动映射以允许asp.net核心用字符串映射十进制?默认情况下,asp.net 核心自动映射将自动检查字符串是否为数字。

标签: c# .net api asp.net-core .net-core


【解决方案1】:

您可以使用自定义模型绑定:

  [HttpGet]
    public async Task<IActionResult> GetData([ModelBinder(typeof(CustomBinder))]decimal? amount)
    {
    }

自定义绑定器:

public class CustomBinder:IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }
            //get amount data with the following code
            
            var data=bindingContext.ValueProvider.GetValue("amount").FirstValue;
            
            //put your logic code of DecimalConverter  here
        
            bindingContext.Result = ModelBindingResult.Success(data);
            return Task.CompletedTask;
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-29
    • 2020-01-08
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多