关于如何在ASP.NET MVC中实现验证的大多数提示似乎都以模型为中心(在模型和控制器之间构建服务层或使用验证属性装饰模型的属性)。
在我的应用程序中,我使用ViewModels进行控制器和视图之间的所有通信。
我的登录页面有一个名为“LoginViewModel”的ViewModel,其中包含一个名为“EmailAddress”的属性。
当用户输入他们的电子邮件地址并单击“提交”时,将填充此ViewModel并将其发送到控制器,在该控制器中验证电子邮件地址。
它必须是有效的电子邮件地址,并且用户必须来自在系统中注册的域。
为此添加验证的便捷方法是什么?我应该将验证放在ViewModel本身吗?还是应该留在控制器中?
答案 0 :(得分:5)
“我应该将验证放在ViewModel本身吗?或者它应该留在控制器中”我同意Robert的意见,但我会添加一个插件以进行额外的自动化。
如果查看xVal等工具,可以看到例程验证(例如,必填字段,范围内的数字,与正则表达式匹配的字符串)可以通过装饰数据类的字段自动完成。实际上,xVal可以自动编写用于例行验证的JavaScript,以便在客户端执行。所有没有编写任何代码。更深入的验证(例如,此用户是我们数据库中注册的域的成员吗?)在模型层本身内部发生在服务器端。
使用ViewModel习惯用法可能会给这个方案带来一些挑战。我目前的方法是将我的实体对象嵌入到我的视图模型中,例如
public class Contact {
[Required]
string Name { get; set; }
}
public class ContactView {
public Contact Contact { get; set; }
public string SomeOtherViewProperty { get; set; }
}
然后在控制器中,更新模型时会发生浅层验证:
UpdateModel(contactViewModel.Contact, "Contact");
并且需要更多信息或更复杂计算的验证发生在模型层本身内。
另一种方法不是嵌入实体对象,而只是在两者之间映射单个字段。我最近发现了一个名为AutoMapper的工具,它自动链接域和视图模型对象之间的字段。它看起来应该支持这种验证方法,尽管我还没有使用它。
答案 1 :(得分:3)
NerdDinner tutorials显示验证发生在模型的部分类中(即Linq to SQL或Entity Framework)。但是,由于您使用的是View Models,因此可以将验证逻辑放在那里。
验证逻辑不会进入控制器。相反,它与控制器挂钩,具有检查属性,即ModelState.IsValid
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Dinner dinner) {
if (ModelState.IsValid) {
try {
dinner.HostedBy = "SomeUser";
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch {
ModelState.AddModelErrors(dinner.GetRuleViolations());
}
}
return View(new DinnerFormViewModel(dinner));
}
详细信息如下:
构建模型
http://nerddinnerbook.s3.amazonaws.com/Part3.htm
在这里:
ViewData和ViewModel
http://nerddinnerbook.s3.amazonaws.com/Part6.htm