19

大多数关于如何在 ASP.NET MVC 中实现验证的技巧似乎都围绕着模型(在模型和控制器之间构建服务层或使用验证属性装饰模型的属性)。

在我的应用程序中,我使用 ViewModels 进行控制器和视图之间的所有通信。

我的登录页面有一个名为“LoginViewModel”的 ViewModel,其属性名为“EmailAddress”。

当用户输入他们的电子邮件地址并单击提交时,这个 ViewModel 被填充并发送到控制器,在那里验证电子邮件地址。

它必须是有效的电子邮件地址,并且用户必须来自在系统中注册的域。

对此添加验证的便捷方法是什么?我应该将验证放在 ViewModel 本身吗?还是应该留在控制器中?

4

2 回答 2

5

“我应该将验证放在 ViewModel 本身中吗?还是应该留在控制器中”我同意罗伯特的观点,但我会添加一个插件以实现额外的自动化。

如果您查看诸如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的工具,它可以自动链接域和视图模型对象之间的字段。看起来它应该支持这种验证方法,虽然我还没有使用它。

于 2009-07-17T00:37:40.513 回答
3

NerdDinner 教程显示验证发生在模型的部分类中(即 Linq to SQL 或实体框架)。但是由于您使用的是视图模型,因此您可以将验证逻辑放在那里。

验证逻辑不在控制器中。相反,它是从具有检查属性的控制器中挂钩的,即 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

于 2009-07-16T04:29:12.693 回答