Asp.net mvc ASP.NET MVC中ViewModels的验证

Asp.net mvc ASP.NET MVC中ViewModels的验证,asp.net-mvc,validation,viewmodel,Asp.net Mvc,Validation,Viewmodel,关于如何在ASP.NET MVC中实现验证的大多数提示似乎都围绕着模型(在模型和控制器之间构建服务层或使用验证属性装饰模型的属性) 在我的应用程序中,控制器和视图之间的所有通信都使用ViewModels 我的登录页面有一个名为“LoginViewModel”的ViewModel,其属性名为“EmailAddress” 当用户输入其电子邮件地址并单击“提交”时,将填充此ViewModel并发送到控制器,在控制器中验证电子邮件地址 它必须是有效的电子邮件地址,并且用户必须来自在系统中注册的域 向此添

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

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

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

当用户输入其电子邮件地址并单击“提交”时,将填充此ViewModel并发送到控制器,在控制器中验证电子邮件地址

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

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

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

验证逻辑不在控制器中。相反,它通过一个checking属性(即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));
}
详情如下:

构建模型

在这里:

视图数据和视图模型

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

如果您查看一个工具,例如,您可以看到,通过修饰数据类的字段,可以自动完成例行验证(例如,必填字段、范围内的数字、与正则表达式匹配的字符串)。事实上,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");
需要更多信息或更复杂计算的验证发生在模型层本身内部


另一种方法不是嵌入实体对象,而是在两者之间映射单个字段。我最近发现了一个名为的工具,它可以自动链接域和视图模型对象之间的字段。看起来它应该支持这种验证方法,尽管我还没有使用它。

好主意,Keith!目前,我的策略与您相同——在ViewModels中嵌入模型。我想知道的是,如果模型和ViewModels都能以相同的方式实现验证,那么像xVal这样的JS框架就可以无缝地与其中任何一个协同工作。这将是最灵活的方式。我认为验证不应该只局限于模型,我还使用了带有嵌入式模型类的自定义视图模型,包括xVal。但是,有时我需要viewmodel仅包含模型属性的子集。我目前正在寻找Automapper来映射这些模型。它工作得很好,但是在那种情况下如何使用xVal呢?如果元数据对象包含不属于ViewModel的属性,则AssociatedMetadataTypeDescriptionProvider将抛出,因此使用MetaData属性装饰ViewModel不起作用。如果您一直在使用Automapper,我想知道您是如何解决此问题的。注意:有关更新的NerdDinner,请参阅此处: