使用DTO而不是领域实体进行ASP.NET MVC 2验证

5

我在努力将两个最佳实践相结合:

  1. 在ASP.NET MVC 2中使用DataAnnotations + ModelBinding进行验证
  2. 通过ViewModel传递数据时使用DTO而不是领域实体

如果我想传递DTO而不是领域实体,那么利用DataAnnotations + ModelBinding进行验证就需要在我的DTO类上指定验证属性。这会导致很多重复的工作,因为多个DTO可能具有相同的字段和相同的验证限制。这意味着每当我更改领域中的验证规则时,我都必须去找到所有与该值对应的DTO,并更新它们的验证属性。

3个回答

3

每个实体只应该有一个DTO,因此每个DTO只需要应用一次验证属性。如果您需要为视图使用多个实体,请将多个DTO作为ViewModel的属性包含。


1
这似乎有点限制性。如果一个视图需要实体的所有属性,而另一个视图只需要几个属性,那怎么办?这种情况不应该使用多个DTO吗? - Kevin Pang
1
DTO是您的数据包,ViewModel是混合和匹配的地方。我认为拥有多个具有不同数据的DTO并不是一个好主意,这会导致您不想维护的混乱。 - Dave Swersky
DTO是与存储无关的“扁平化”模型版本。每个实体应该只有一个DTO。我不会创建一个包含产品及其相关实体的DTO。聚合相关数据以支持视图需求是ViewModel的角色。 - Dave Swersky
@Dave Swersky,我不同意一直强调DTOs只能用于扁平化数据的观点。在很多情况下,这样的限制是没有意义的。我们不需要每次查询实体时都访问所有字段,DTOs只是传输数据的容器。你可以在ViewModel中使用这些DTOs。 - jwize
我建议不要将DTO用作ViewModel,而是在ViewModel上使用它们进行修饰。在DTO中使用继承来按照ViewModel组织它们。此外,我建议在类中使用属性而不是MetadataType类中的属性,因为这些对象是“愚蠢”的,如果在此处分离关注点,重构会更具挑战性。 - jwize
显示剩余4条评论

3
您可能会发现这个链接很有用。
请记住,验证无处不在。如果DTO应用UI验证(如获取必填字段、正确格式的日期时间等),领域对象应用领域验证(例如,在提取操作之前,账户是否有足够的资金),这都是没有问题的。
您不能创建通用的验证。最好的做法是将其放在适当的位置。
并且消除关于重复的感觉。使用DTO通常意味着应用单一职责原则。如果您有两个客户对象,其中一个负责承载业务逻辑,另一个负责显示它,则不存在重复。

1
也许您可以使用元注解,将属性放在单独的类中:
namespace MvcApplication1.Models
{
    [MetadataType(typeof(MovieMetaData))]
    public partial class Movie
    {
    }


    public class MovieMetaData
    {
        [Required]
        public object Title { get; set; }

        [Required]
        [StringLength(5)]
        public object Director { get; set; }


        [DisplayName("Date Released")]
        [Required]
        public object DateReleased { get; set; }
    }
}

代码示例借鉴自本文


虽然我可能说错了,但我建议在DTO类中使用元数据而不是在外部使用,如我上面的评论所述。然而,如果我在一个简单的项目中直接绑定到我的Entity Framework层并且/或者使用流畅的API,我会将它们放入元数据类型中。 - jwize

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接