【问题标题】:Reusing a view model but applying different validation rules in ASP.NET MVC在 ASP.NET MVC 中重用视图模型但应用不同的验证规则
【发布时间】:2014-10-25 19:33:16
【问题描述】:

所以我们使用 DataAnnotations 来实现我们的 ASP.NET MVC 表单的输入验证。如果我们要重新开始,我会考虑使用 Fluent Validation,但我们现在距离太远,无法做出改变。

所以这个项目需要我们构建很多表单。随着我们的进步,我们已经确定了跨表单重复的输入组。这方面的一个例子可能是一组表示地址的输入。

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

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

    public string Enquiry { get; set; }

    ...
}

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

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

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

    string LineTwo { get; set; }

    ...
}

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

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

这种方法的主要缺点是我们最终可能会得到很多视图模型,它们的区别仅在于应用于它们的验证属性。这被认为是可以接受的,因为可重用模块的数量预计会相对较少。

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

【问题讨论】:

  • 你的验证做得怎么样?
  • 使用 OOTB DataAnnotations 验证属性并让 DefaultModelBinder 做它的事情(因此 DataAnnotationsModelValidator 我猜)。

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


【解决方案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 { }

【讨论】:

  • 感谢 MetadataTypeAttribute 引起我的注意。此解决方案与一个问题不同 - 将视图绑定到 AddressDetailsBase,HTML 帮助程序不选择在 IUserAddressDetailsValidation 中应用的验证属性,因此客户端验证不起作用。有任何想法吗?我正在尝试将传递给 HTML 帮助程序的表达式的参数类型从 AddressDetailsBase 动态更改为 UserAddressDetails 但我现在正在苦苦挣扎!
  • 在这种情况下,您不会使用 Base 对象进行验证,它没有验证。至于改变它的斗争,我无法帮助你,因为你没有提供任何细节。
  • 基本问题已在此处确定:stackoverflow.com/a/15232767/3619572 我已通过使用非通用 HTML 帮助程序解决了该问题。
【解决方案2】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2011-08-28
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多