我有两个 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, }
}
以及以下 Controller 发布操作:
[HttpPost]
public ActionResult Create(ParentViewModel viewModel)
{
if (ModelState.IsValid)
{
// process viewModel -> write something into database
return RedirectToAction("Index");
}
return View(viewModel);
}
现在,我将发布请求正文中的以下表单值发送到与该操作对应的 URL(在 Fiddler 请求生成器中手动):
这工作正常,
Name1
属性填写viewModel.Content
, Name2
是 null
模型状态无效,因为 Name2
是必须的。因此,验证按预期失败。 viewModel
现在
viewModel.Content
不是 null
(因为我在构造函数中实例化它)但是所有属性 Name1
和 Name2
是 null
.这是意料之中的。我没想到的是模型状态是有效的,所以它通过了验证(后来导致数据库异常,因为有不可为空的列)。 如何改进此代码,以便验证也适用于第二种情况?
我做了三个实验:
Content
的实例化在 ParentViewModel
构造函数,然后 Content
是 null
在上面的第二个示例中,但验证仍然通过。 [Required]
Content
的属性属性(但没有删除 Content
构造函数中 ParentViewModel
的实例化)。这根本没有影响,上面两个测试的描述行为是相同的。 [Required]
Content
的属性属性并删除 Content
的实例化在 ParentViewModel
构造函数。这似乎可以按我的意愿工作:在第二个测试中 Content
是 null
由于 [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
中的子属性构造函数是问题的根源,模型绑定(bind)器本身必须实例化子属性(或者不实例化,如果请求中没有匹配的表单字段),以便进行正常工作的服务器端验证。我在其他几个 View 模型构造函数中有子属性实例化,直到现在才注意到这个问题。那么,这通常是一种不好的做法吗?还有其他方法可以解决问题吗?
最佳答案
ModelState.IsValid 告诉您是否已将任何模型错误添加到 ModelState。
默认模型绑定(bind)器将为基本类型转换问题添加一些错误,例如为“int”传递非数字。您可以根据您使用的任何验证系统更充分地填充 ModelState。我建议查看数据注释以验证 ViewModel,因为它运行良好。
此语法可能错误或陈旧。 ModelState.AddModelError(“键”,异常)
转述自
What is ModelState.IsValid valid for in ASP.NET MVC in NerdDinner?
关于asp.net - 嵌套 ViewModel 的验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8318465/