我的某个类在某些属性上有[Required]
个装饰,但也需要一些自定义验证,所以它使用IValidatableObject
。
public class ModelCourse : IValidatableObject
{
//some other code...
[DisplayName("Course Name")]
[Required]
[StringLength(100, MinimumLength=1)]
public String name { get; set; }
//more code...
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (courseGradeLevels == null || courseGradeLevels.Count < 1)
{
yield return new ValidationResult("You must select at least one grade level.");
}
if ((courseLength == CourseLength.Other) && string.IsNullOrEmpty(courseLengthDescription))
{
yield return new ValidationResult("Course Length Description is Required if Length is Other.");
}
}
}
//course is one of a few child objects in this class
bool dbDetailsValid = TryValidateModel(dbDetails);
ViewData["courseValid"] = !ModelState.ContainsKey("course");
foreach(KeyValuePair<string, ModelState> pair in ModelState.Where(x => x.Value.Errors.Count > 0))
{
ViewData[pair.Key + "ErrorList"] = pair.Value.Errors.ToList();
}
运行此代码时,name
的空白字符串不会导致ModelState
出错。自定义验证逻辑按预期工作,但我不明白为什么TryValidateModel
没有接受装饰...是我手动检查每个必填字段的唯一选择?
答案 0 :(得分:1)
感谢@nick nieslanik指点我Understanding ValidationContext in DataAnnotations,我有答案。
在我的自定义验证方法中,我使用反射来遍历每个属性,并在每个属性上调用TryValidateProperty
,如果它不验证则将其添加到结果中:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> results = new List<ValidationResult>();
foreach (PropertyInfo property in this.GetType().GetProperties())
{
Validator.TryValidateProperty(property.GetValue(this), new ValidationContext(this, null, null) { MemberName = property.Name }, results);
if (results.Count > 0)
{
foreach (ValidationResult err in results)
{
yield return new ValidationResult(err.ErrorMessage);
}
results.Clear();
}
}
//the rest of the validation happens here...
}