验证嵌套的ViewModel

时间:2011-11-29 22:10:37

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

我有两个ViewModel(简化):

public class ParentViewModel
{
    public ParentViewModel
    {
        Content = new ChildViewModel();
    }

    public ChildViewModel Content { get; set, }
}

public class ChildViewModel
{
    [Required]
    public string Name1 { get; set, }
    [Required]
    public string Name2 { get; set, }
}

以下控制器发布操作:

[HttpPost]
public ActionResult Create(ParentViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        // process viewModel -> write something into database
        return RedirectToAction("Index");
    }
    return View(viewModel);
}

现在我将一个帖子请求正文中的以下表单值发送到与该操作相对应的URL(在Fiddler Request Builder中手动):

  • Content.Name1 = X

    一切正常,Name1属性填充在viewModel.Content中,Name2null且模型状态无效,因为需要Name2。因此,验证按预期失败。

  • Xontent.Name1 = X Name1 = X 或其他任何内容,以便任何内容都不会绑定到viewModel

    现在viewModel.Content不是null(因为我在构造函数中实例化它),但所有属性Name1Name2都是null。这是预料之中的。我所做的期望的是模型状态是有效,因此它通过了验证(之后导致数据库异常,因为存在不可为空的列)。

如何改进此代码,以便验证在第二种情况下也有效?

我做了三次实验:

  • 我在Content构造函数中删除了ParentViewModel的实例化,然后在上面的第二个示例中Contentnull,但验证仍然通过。< / p>

  • 我在[Required]属性中添加了Content属性(但未删除Content构造函数中ParentViewModel的实例化)。这完全没有效果,上述两个测试的描述行为是相同的。

  • 我在[Required]属性中添加了Content属性,并且删除了Content构造函数中ParentViewModel的实例化。这看起来像我想要的那样:在第二个测试中Contentnull,由于[Required]属性,验证失败。它看起来像这样:

    public class ParentViewModel
    {
        [Required]
        public ChildViewModel Content { get; set, }
    }
    
    public class ChildViewModel
    {
        [Required]
        public string Name1 { get; set, }
        [Required]
        public string Name2 { get; set, }
    }
    

我现在得出结论,在Content构造函数中实例化ParentViewModel子属性是问题的根源,并且模型绑定器本身必须实例化子属性(否则,如果没有匹配请求中的表单字段,以便正确运行服务器端验证。

我在其他几个视图模型构造函数中有子属性实例化,直到现在才注意到这个问题。那么,这通常是一种不好的做法吗?还有其他方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

ModelState.IsValid告诉您是否已将任何模型错误添加到ModelState。

默认模型绑定器会为基本类型转换问题添加一些错误,例如为“int”传递非数字。您可以根据您使用的任何验证系统更完整地填充ModelState。我建议查看数据注释以验证ViewModel,因为它运行良好。

此语法可能有误或有旧。 ModelState.AddModelError(“key”,Exception)

转述自 What is ModelState.IsValid valid for in ASP.NET MVC in NerdDinner?

答案 1 :(得分:0)

第三种解决方案很好:

public class ParentViewModel
{
    [Required]
    public ChildViewModel Content { get; set, }
}

public class ChildViewModel
{
    [Required]
    public string Name1 { get; set, }
    [Required]
    public string Name2 { get; set, }
}

我现在在几个地方使用它,并没有发现任何问题。