asp.net - 在父 View 模型的特定条件下,关闭本身是 View 模型的属性的数据注释验证

标签 asp.net asp.net-mvc-3

我正在使用编辑器模板和合成构建一个页面。我的 View 模型包含本身就是 View 模型的属性。例如

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 自定义验证属性,但它仅在条件是同一 View 模型的值时才有效。我需要一些可以检查父级的东西,或者实际上是祖先的属性。

我的临时 hack 是在复选框不正确时清除回发时的 ModelState 错误。

我还必须编写一些自定义 javascript,以便客户端浏览器在未勾选复选框时抑制验证。

实际示例比这复杂得多,但希望从上面的简化示例中可以清楚地看出我所追求的是什么。

如果父 View 模型上有一个类似这样的属性就好了

public class ParentModel
{
    public boolean SomeCheckBox { get; set; }

    [SuppressValidationIf("SomeCheckBox", false)]
    public ChildModel Child { get; set; }
}

有什么想法吗?

最佳答案

这个出色的示例完美地说明了进行声明性验证的局限性,这就是数据注释。

出于这个原因,我建议您对验证规则使用命令式方法,因为您可以处理许多情况。 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);
    }
}

和一个 View :

@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 个属性。

关于asp.net - 在父 View 模型的特定条件下,关闭本身是 View 模型的属性的数据注释验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8991526/

相关文章:

javascript - 单击下拉列表更改 css

javascript - 通过 ajax 将 LIst<t> 发送到复杂模型

Asp.Net Core 2 复杂标签帮助器

c# - 如何删除换行符

.net - Razor - 我可以为 View 制作可选模型吗?

c# - 如何只在第一次读取查询字符串?

c# - 格式化货币值的更有效方法

kendo ui 网格中分页的 Javascript 验证

jquery - Ajax 文件上传在 IE7 中不起作用

c# - 使用 UpdateModel() 时如何消除服务器端清理的重复代码?