2011-11-29 85 views
8

我有两个的ViewModels的(简化的):验证嵌套的ViewModels

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.ContentName2null因为Name2需要模型的状态是无效的。因此,验证失败如预期。

  • Xontent.Name1 = X名1 = X或任何这样,任何被绑定到viewModel

    现在viewModel.Contentnull(因为我在构造函数实例化的话),但所有物业Name1Name2null。这是预料之中的。我所做的而不是预计模型状态为有效,所以它通过验证(以后导致数据库异常,因为有不可空列)。

我该如何改进此代码,以便验证也适用于第二种情况?

我做了三个实验:

  • 我在ParentViewModel构造除去Content实例化,然后Content是在上面的第二个例子null,但验证仍然通过。

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

  • 我添加了一个[Required]属性的Content财产ParentViewModel构造去掉Content的实例。这看起来像我想要的那样工作:在第二个测试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, } 
    } 
    

我现在可以得出结论,在实例中ParentViewModel构造的Content子属性是问题的根源和模型绑定本身必须实例子属性(或不,如果请求中没有匹配的表单字段),以便具有正确工作的服务器端验证。

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

+0

我目前正在努力与类似的东西。我的情况只有差异,我有一个ChildViewModels的IEnumerable。我已经尝试了上面的所有三个选项,似乎没有任何工作适合我。 –

回答

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, } 
} 

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

0

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

默认的模型联编程序会为基本类型转换问题添加一些错误,例如传递一个非int数的非数字。您可以根据您使用的任何验证系统更完整地填充ModelState。我建议查看数据注释来验证ViewModels,因为它工作正常。

此语法可能是错误的或旧的。 ModelState.AddModelError(“钥匙”,异常)

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

+0

我知道这是*技术上*替代方法,但*实际上*它将意味着以下内容:在每个具有嵌套视图模型的视图模型的后续操作中,我必须执行如下操作:'if(viewModel.Content.Name1 == null && viewModel.Content.Name2 == null && ...)ModelState.AddModelError(...);'这看起来不太好。对于数据注释:我不知道哪一个可以帮助我。我已经在使用'[Required]',这就是我的模型中验证应该考虑的全部内容。还有其他一些注释“诡计”吗? – Slauma