【发布时间】:2020-12-13 10:26:04
【问题描述】:
我想通过属性向 Web API (.NET Framework 4.7.2) 添加模型验证,但我发现如果模型是集合,这将不起作用。
我有一个从字典继承的模型类。例如:
...
using System.ComponentModel.DataAnnotations;
...
public class MyModel : Dictionary<string, string>
{
[StringLength(100)]
public string SomeField
{
get => TryGetValue("someField", out var value) ? value : null;
set => this["someField"] = value;
}
}
我做了什么:
- 将
[ApiController]属性添加到控制器类以激活请求的自动模型验证。 - 在项目中添加了
System.ComponentModel.DataAnnotations。 - 向模型字段添加了验证属性。
这适用于简单的模型类,但如果模型是从集合继承的,则不会发生属性验证。
为了解决这个问题,我实现了IValidatableObject接口,我在其中写了以下内容:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
const string validationStatusFieldName = "alreadyValidated";
if (validationContext.Items.TryGetValue(validationStatusFieldName, out var alreadyValidated) && (bool) alreadyValidated)
return Enumerable.Empty<ValidationResult>();
validationContext.Items[validationStatusFieldName] = true;
var validationResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(validationContext.ObjectInstance, validationContext, validationResults, true);
return isValid
? Enumerable.Empty<ValidationResult>()
: validationResults;
}
在这种情况下,Validate 方法会被自动调用,我们可以在其中手动验证属性。但是,如果属性验证通过且没有验证错误,则将调用 Validate 方法,在这种情况下,该方法将一遍又一遍地调用自身,从而导致堆栈溢出异常。所以我添加了一个检查以确保验证已经发生。
这样就可以了,但是不清楚:如果这个模型继承了一个集合,为什么不自动检查属性,如何解决?
【问题讨论】:
-
为什么需要将模型继承到集合中。您可以在模型内部使用集合类型
Property的简单模型中执行此操作。 -
它是否可以被继承取决于实际的属性:自定义属性声明以
System.AttributeUsageAttribute开头,它定义了属性类的一些关键特征。例如,您可以指定您的属性是否可以被其他类继承或指定该属性可以应用于哪些元素。 也许这些属性不是以允许它们被继承的方式创建的。 -
继承一个集合会带来很多通常最好避免的奇怪现象。支持composition over inheritance。例如,
MyModel可能有一个 Dictionary 属性,其处理方式与其固有属性不同(如SomeField)。 -
是的,没错。但我想知道为什么它会这样工作?
标签: c# validation asp.net-web-api data-annotations