重用视图模型,但在ASP.NET MVC中应用不同的验证规则

时间:2014-10-25 19:33:17

标签: asp.net-mvc asp.net-mvc-4 validation viewmodel

因此我们使用DataAnnotations来实现ASP.NET MVC表单的输入验证。如果我们重新开始,我会考虑流利验证,但我们现在做的太过分了。

所以这个项目要求我们建立很多形式。随着我们的进步,我们已经确定了在表单中重复的输入组。一个例子可能是一组表示地址的输入。

然后我们通过为其创建_AddressEntry部分视图以及相关的视图模型AddressViewModel,将地址输入转换为可重复使用的模块。然后,父表单的视图模型如下所示:

public class SubmitEnquiryViewModel
{
    public AddressViewModel Address { get; set; }

    public string Enquiry { get; set; }

    ...
}

_SubmitEnquiry视图中,我们使用_AddressEntry插入EditorFor()部分视图。

这一点工作正常,直到我们意识到地址输入的不同实例具有不同的验证要求 - 装饰AddressViewModel的验证属性并不总是适用。为了解决这个问题,我们定义了IAddressViewModel

public interface IAddressViewModel
{
    string LineOne { get; set; }

    string LineTwo { get; set; }

    ...
}

然后为验证规范的所有不同排列定义此接口的具体实现 - 例如AddressViewModel(默认验证),AddressNoValidationViewModel等。

然后将_AddressEntry部分视图绑定到IAddressViewModel,并为父视图模型的Address属性选择适当的具体实现。

这种方法的主要缺点是我们可能最终会得到相当多的视图模型,这些视图模型仅因应用于它们的验证属性而不同。尽管可重用模块的数量预计相对较小,但这被认为是可以接受的。

之前还有其他人遇到过这个挑战吗?你想出了什么解决方案?您对上述解决方案有何看法?

2 个答案:

答案 0 :(得分:1)

您可能需要查看MetadataTypeAttribute

基类:

public abstract class AddressDetailsBase
{
  public string Line1 { get; set; }
  public string Line2 { get; set; }
  public string City { get; set; }
  public string State { get; set; }
  public int PostalCode { get; set;}
}

验证(我使用接口以便不会意外地实例化):

public interface IUserAddressDetailsValidation
{
  [required]
  string Line1 { get; set; }
  [required]
  string Line2 { get; set; }
  [required]
  string City { get; set; }
  [required]
  string State { get; set; }
  [required]
  int PostalCode { get; set;}
}

查看型号类型:

[MetadataType(typeof(IUserAddressDetailsValidation))]
public class UserAddressDetails : AddressDetailsBase { }

答案 1 :(得分:0)

数据注释适用于非常简单的场景和原型项目。 正如您所看到的,您已经在与注释作斗争,这些注释不适合在不同的环境中工作。

只需在控制器操作中使用普通的ModelState.AddModelError,并在控制器中构建自定义验证逻辑。

ModelState.AddModelError("Prop", "Your custom 'validation failed' message.");

在进行自定义验证之前,您仍然可以评估ModelState.IsValid,因此您仍然可以将DataAnnotations用于一些代码重用的简单案例。