验证子ASP.NET MVC视图模型,该视图模型在其父级中是非强制性的,但具有必填字段

时间:2018-04-05 10:35:23

标签: c# asp.net-mvc asp.net-mvc-5

我是ASP.NET MVC的新手,并尝试研究如何验证AlphaViewModel类型的视图模型,它是Create控制器方法的参数。

视图模型如下。

public class AlphaViewModel
{
    [HiddenInput]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string Description { get; set; }

    bool HasBeta { get; set; }

    public BetaViewModel Beta { get; set; } = new BetaViewModel(); // Always initialize otherwise null exception when trying to set its values.
}

public class BetaViewModel
{
    [HiddenInput]
    public string Id { get; set; }

    [Required]
    public string Location { get; set; }

    [Required]
    public string Area { get; set; }
}

我想通过相同的UI使用相同的Save按钮设置上面的所有属性。

但是,Beta属性在AlphaViewModel中是可选的,因此它可以为null。如果Beta属性不为null,则其所有属性(LocationArea)都是必需的。

在用户界面中,我可以设置一个复选框,将HasBeta设置为false,然后不显示BetaViewModel的字段。但是,在这种情况下,ASP.NET-MVC的验证仍在解决,LocationAction字段在UI中收到警告消息,表明它们尚未设置。

一种选择是关闭BetaViewModel属性的验证,例如在ModelStatealphaViewModel.Beta时为BetaViewModel,但这依赖于将字段名称作为字符串传递。

alphaViewModel.Beta为空时,是否有其他方法可以阻止验证curl https://install.meteor.com/ | sh字段?

1 个答案:

答案 0 :(得分:2)

您需要先从= new BetaViewModel();媒体资源中删除Beta。如果请求包含模型的任何名称/值对,DefaultModelBinder将在POST方法中初始化AlphaViewModel

由于BetaViewModel,它会初始化= new BetaViewModel()。由于它不是null,因此LocationArea属性会触发验证,ModelState无效。

但是,您的实施还存在其他问题。假设用户检查HasBeta属性并开始输入Location的值,然后实现他们的错误并取消选中该复选框。由于表单控件是隐藏的,因此您不会收到客户端验证错误(默认情况下不会验证隐藏的输入),但现在会为Beta.Location发送名称/值对。这反过来会初始化BetaViewModel,因为尚未为Area输入值,ModelState无效。假设您在这种情况下返回视图,用户不知道发生了什么,因为错误消息也是隐藏的(他们只是一直按下提交按钮,直到他们沮丧地放弃)。

如果未选中该复选框,您可以在提交之前添加一个脚本来禁用BetaViewModel输入或确保它们具有null值。

另一种选择是使用条件验证属性,例如foolproof [RequiredIf]。然后使用包含所有属性的单个模型

public class AlphaViewModel
{
    [HiddenInput]
    public int Id { get; set; }
    ....
    bool HasBeta { get; set; }

    // Include properties from BetaViewModel
    [HiddenInput]
    [RequiredIf("HasBeta ", true)]
    public string Id { get; set; }
    [RequiredIf("HasBeta ", true, ErrorMessage = "...")]
    public string Location { get; set; }
    [RequiredIf("HasBeta ", true, ErrorMessage = "...")]
    public string Area { get; set; }
}