为什么自动属性验证对继承集合的模型不起作用?
Why doesn't automatic attribute validation work for models inheriting collections?
我想通过属性将模型验证添加到 Web API (.NET Framework 4.7.2),但我 运行如果模型是一个集合,这将不起作用。
我有一个从字典继承的模型 class。例如:
...
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]
属性 class 以激活对请求的自动模型验证。
- 已将
System.ComponentModel.DataAnnotations
添加到项目。
- 向模型字段添加了验证属性。
这适用于简单模型 classes,但如果模型是从集合继承的,则不会进行属性验证。
为了解决这个问题,我实现了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 方法,在这种情况下,该方法将一遍又一遍地调用自身,从而导致堆栈溢出异常。所以我添加了一个检查以确保验证已经发生。
这样就可以了,但是不清楚:如果这个模型继承了一个集合,为什么不自动检查属性,如何解决?
验证者有一个condition,他可以在其中选择他将如何验证对象。首先检查模型是一个集合,然后检查它的每个元素。由于此集合存储没有验证约束的字符串,因此验证没有任何注释。而如果通过属性验证字段没有问题,那么就会调用Validate
方法,就是这样。
如何解决这个问题:
实现IValidatableObject
接口,在Validate
方法中,尝试验证当前实例,记得退出无限递归。 (题中已完成)
为模型class创建自定义验证属性(继承自ValidationAttribute
),它将搜索具有验证属性的属性并独立验证它们。
我想通过属性将模型验证添加到 Web API (.NET Framework 4.7.2),但我 运行如果模型是一个集合,这将不起作用。
我有一个从字典继承的模型 class。例如:
...
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]
属性 class 以激活对请求的自动模型验证。 - 已将
System.ComponentModel.DataAnnotations
添加到项目。 - 向模型字段添加了验证属性。
这适用于简单模型 classes,但如果模型是从集合继承的,则不会进行属性验证。
为了解决这个问题,我实现了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 方法,在这种情况下,该方法将一遍又一遍地调用自身,从而导致堆栈溢出异常。所以我添加了一个检查以确保验证已经发生。
这样就可以了,但是不清楚:如果这个模型继承了一个集合,为什么不自动检查属性,如何解决?
验证者有一个condition,他可以在其中选择他将如何验证对象。首先检查模型是一个集合,然后检查它的每个元素。由于此集合存储没有验证约束的字符串,因此验证没有任何注释。而如果通过属性验证字段没有问题,那么就会调用Validate
方法,就是这样。
如何解决这个问题:
实现
IValidatableObject
接口,在Validate
方法中,尝试验证当前实例,记得退出无限递归。 (题中已完成)为模型class创建自定义验证属性(继承自
ValidationAttribute
),它将搜索具有验证属性的属性并独立验证它们。