我正在使用编辑器模板和合成构建页面。我的视图模型包含自身视图模型的属性。 E.g。
public class ParentModel
{
public boolean SomeCheckBox { get; set; }
public ChildModel Child { get; set; }
}
public class ChildModel
{
[Required]
public string SomeString { get; set; }
[Required]
public string SomeOtherString { get; set; }
}
我希望数据注释验证只有在父项的属性SomeCheckBox为真时才会启用子项。
我在stackoverflow上的其他地方看到过RequiredIf自定义验证属性,但只有在条件是相同视图模型的值时它才有效。我需要的东西可以检查父母,或者确实是祖先的财产。
我的临时黑客是如果复选框不为真,则清除回发时的ModelState错误。
我还必须编写一些自定义javascript,以便客户端浏览器在未勾选复选框时禁止验证。
真实的例子比这复杂得多,但希望从上面简化的例子可以清楚地知道我在追求什么。
什么是好的是父视图模型上的属性类似于
public class ParentModel
{
public boolean SomeCheckBox { get; set; }
[SuppressValidationIf("SomeCheckBox", false)]
public ChildModel Child { get; set; }
}
有什么想法吗?
答案 0 :(得分:6)
这个优秀的例子完美地说明了进行声明性验证的局限性,这就是数据注释的作用。
出于这个原因,我建议您使用命令式方法来处理验证规则,因为您可以处理许多场景。 FluentValidation.NET是一个很好的例子,它可以使这个验证场景变得轻而易举。
让我举例说明它如何处理这种情况:
我们首先为我们的子模型和父模型定义验证器:
public class ChildModelValidator : AbstractValidator<ChildModel>
{
public ChildModelValidator()
{
RuleFor(x => x.SomeString).NotEmpty();
RuleFor(x => x.SomeOtherString).NotEmpty();
}
}
public class ParentModelValidator : AbstractValidator<ParentModel>
{
public ParentModelValidator()
{
RuleFor(x => x.Child)
.SetValidator(new ChildModelValidator())
.When(x => x.SomeCheckBox);
}
}
请注意如何根据父级SomeCheckBox
属性的值包含子验证器?现在你的模型看起来像这样:
[Validator(typeof(ParentModelValidator))]
public class ParentModel
{
public bool SomeCheckBox { get; set; }
public ChildModel Child { get; set; }
}
public class ChildModel
{
public string SomeString { get; set; }
public string SomeOtherString { get; set; }
}
就是这样。
您只需安装FluentValidation.MVC3
NuGet,在Application_Start
中添加以下行:
FluentValidationModelValidatorProvider.Configure();
现在你像往常一样工作:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new ParentModel
{
Child = new ChildModel()
});
}
[HttpPost]
public ActionResult Index(ParentModel model)
{
return View(model);
}
}
和观点:
@model ParentModel
@Html.ValidationSummary(false)
@using (Html.BeginForm())
{
@Html.CheckBoxFor(x => x.SomeCheckBox)
@Html.EditorFor(x => x.Child.SomeString)
@Html.EditorFor(x => x.Child.SomeOtherString)
<button type="submit">OK</button>
}
如果选中该复选框,则子验证器将启动并需要2个属性。