Dus*_*ell 24 c# validation asp.net-mvc fluentvalidation asp.net-mvc-4
以下是我的问题的简化版本.
我不能压扁模型.我需要一个"孩子"列表来验证生日.
我似乎无法在Parent类中引用日期,并想知道如何在Fluent验证中完成此操作?
模型
[Validator(typeof(ParentValidator))]
public class Parent
{
public string Name { get; set; }
public DateTime Birthdate { get; set; }
public List<Child> Children { get; set; }
}
public class Child
{
public string ChildProperty{ get; set; }
public DateTime Birthdate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
验证器
public class ParentValidator : AbstractValidator<Parent>
{
public ParentValidator()
{
RuleFor(model => model.Name).NotEmpty();
RuleForEach(model => model.Children).SetValidator(new ChildValidator());
}
}
public class ChildValidator : AbstractValidator<Child>
{
public ChildValidator()
{
RuleFor(model => model.ChildProperty).NotEmpty();
//Compare birthday to make sure date is < Parents birthday
}
}
Run Code Online (Sandbox Code Playgroud)
Tom*_*nes 26
像这样创建一个自定义属性验证器
public class AllChildBirtdaysMustBeLaterThanParent : PropertyValidator
{
public AllChildBirtdaysMustBeLaterThanParent()
: base("Property {PropertyName} contains children born before their parent!")
{
}
protected override bool IsValid(PropertyValidatorContext context)
{
var parent = context.ParentContext.InstanceToValidate as Parent;
var list = context.PropertyValue as IList<Child>;
if (list != null)
{
return ! (list.Any(c => parent.BirthDay > c.BirthDay));
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
添加这样的规则
public class ParentValidator : AbstractValidator<Parent>
{
public ParentValidator()
{
RuleFor(model => model.Name).NotEmpty();
RuleFor(model => model.Children)
.SetValidator(new AllChildBirtdaysMustBeLaterThanParent());
// Collection validator
RuleFor(model => model.Children).SetCollectionValidator(new ChildValidator());
}
}
Run Code Online (Sandbox Code Playgroud)
Custom Property验证器的替代方法是使用Custom方法:
public ParentValidator()
{
RuleFor(model => model.Name).NotEmpty();
RuleFor(model => model.Children).SetCollectionValidator(new ChildValidator());
Custom(parent =>
{
if (parent.Children == null)
return null;
return parent.Children.Any(c => parent.BirthDay > c.BirthDay)
? new ValidationFailure("Children", "Child cannot be older than parent.")
: null;
});
}
Run Code Online (Sandbox Code Playgroud)
显示失败indicies的粗暴的方法:(也许应该是一些其他标识的名称)
public class ParentValidator : AbstractValidator<Parent>
{
public ParentValidator()
{
RuleFor(m => m.Children).SetCollectionValidator(new ChildValidator());
Custom(parent =>
{
if (parent.Children == null)
return null;
var failIdx = parent.Children.Where(c => parent.BirthDay > c.BirthDay).Select(c => parent.Children.IndexOf(c));
var failList = string.Join(",", failIdx);
return failIdx.Count() > 0
? new ValidationFailure("Children", "Child cannot be older than parent. Fail on indicies " + failList)
: null;
});
}
}
Run Code Online (Sandbox Code Playgroud)
joh*_*y 5 11
使用set child validator有一种更简单的方法:
public class ChildValidator : AbstractValidator<Child>
{
public ChildValidator(Parent parent)
{
RuleFor(model => model.ChildProperty).NotEmpty();
RuleFor(model => model.Birthday).Must(birthday => parent.Birthday > birthday);
}
}
public class ParentValidator : AbstractValidator<Parent>
{
public ParentValidator()
{
RuleFor(model => model.Name).NotEmpty();
}
public override ValidationResult Validate(Parent parent)
{
RuleFor(model => model.Children).SetCollectionValidator(new ChildValidator(this));
return base.Validate();
}
}
Run Code Online (Sandbox Code Playgroud)
基于@kristoffer-jalen 的回答,现在是:
public class ParentValidator : AbstractValidator<Parent>
{
public ParentValidator()
{
RuleFor(model => model.Name).NotEmpty();
//RuleFor(model => model.Children)
// .SetCollectionValidator(model => new ChildValidator(model))
RuleForEach(model => model.Children)
.SetValidator(model => new ChildValidator(model));
}
}
public class ChildValidator : AbstractValidator<Child>
{
public ChildValidator(Parent parent)
{
RuleFor(model => model.ChildProperty).NotEmpty();
RuleFor(model => model.Birthday).Must(birthday => parent.Birthday < birthday);
}
}
Run Code Online (Sandbox Code Playgroud)
如SetCollectionValidator已被弃用。
如今,通过使用扩展方法并将父对象传递给子验证器,可以进一步简化@ johnny-5 的答案SetCollectionValidator:
public class ParentValidator : AbstractValidator<Parent>
{
public ParentValidator()
{
RuleFor(model => model.Name).NotEmpty();
RuleFor(model => model.Children)
.SetCollectionValidator(model => new ChildValidator(model))
}
}
public class ChildValidator : AbstractValidator<Child>
{
public ChildValidator(Parent parent)
{
RuleFor(model => model.ChildProperty).NotEmpty();
RuleFor(model => model.Birthday).Must(birthday => parent.Birthday < birthday);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14629 次 |
| 最近记录: |