API.Net-验证查询参数



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

样品路线

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."
]
}
}

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

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

CustomBinder:

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;
}
}

最新更新