c# - .NET Core,通过验证将字符串绑定到集合
问题描述
有控制器:
public async Task<IActionResult> GetFoo([FromQuery] FooParams params)
{
// ...
}
端点应该有参数x=1,2,3
。我想要达到的目标:
- 将字符串值转换
1,2,3
为IReadOnlyCollection<string>
(~new HashSet<string> { "1", "2", "3" }
) - 在转换之前验证属性的值(应用正则表达式)
这是模型:
class FooParams
{
[Required]
[RegularExpression("^\\d+(,\\d+)*$")]
[BindProperty(Name = "x")]
public IReadOnlyCollection<string> Params { get; set; }
// ... more properties here
}
捆绑
自定义模型绑定器:...通常不应该用于将字符串转换为自定义类型,TypeConverter 通常是更好的选择。
所以我正要这样写我的自定义TypeConverter
:
public class FooTypeConverter : CollectionConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) =>
sourceType == typeof(string);
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) =>
destinationType == typeof(IReadOnlyCollection<string>);
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var plainValue = value as string;
if (string.IsNullOrWhiteSpace(plainValue))
{
return null;
}
var values = plainValue
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(v => v.Trim());
return new HashSet<string>(values);
}
}
不幸的是,我无法申请[TypeConverter(typeof(FooTypeConverter))]
财产本身。唯一不被忽略的地方TypeCovnerterAttribute
是当我为整个模型类设置它时,但这样做会使转换器更加复杂。
另一种方法是将我的类型转换器设置为IReadOnlyCollection<string>
这样(在Startup.cs
):
TypeDescriptor.AddAttributes(typeof(IReadOnlyCollection<string>), new TypeConverterAttribute(FooTypeConverter));
...但是通过这种方式,我正在其他地方“配置”模型的行为,这对我(或其他任何人)几天后可能不清楚。
有没有更好的办法?我应该实施IModelBinder
吗?
验证
我目前使用失败的尝试RegularExpressionAttribute
- 似乎我只能验证目标类型。但这可能已经太晚了,无法确定参数是完全丢失还是格式无效(实现IModelBinder
我可以将验证错误添加到模型状态,将绑定和验证结合在一个地方)。
解决方案
推荐阅读
- php - 通过PHP动态删除表格内容的mySQL自动增量+自动调整id?
- python - python列表 - 无法转换为json
- python - 为什么 python 可能会覆盖与尚未调用的字典键关联的值?
- axios - 如何使用 Laravel Passport 访问令牌
- symfony - 相同的composer.json,相同的composer.lock,但结果不同
- django - Django 模型作为 Python 字典键
- amazon-s3 - 从 lambda 访问 S3 存储桶的连接超时
- google-cloud-platform - 浏览器内 SSH - IP 地址范围
- python - 包含外部文件时,安装工具是否会在 MANIFEST.in 以外的任何地方显示?
- javascript - 在 vue.js SFC 中使用 lodash.throttle 超时的数据值