【问题标题】:MVC Using Domain Models in View ModelsMVC 在视图模型中使用领域模型
【发布时间】:2013-02-23 20:42:59
【问题描述】:

以下可以吗?我知道领域模型不应该在视图中使用,但是在视图模型中使用领域模型可以吗?对于一些非常小的模型,为它们创建和管理视图模型似乎不值得。

举例

public class LoginDomainModel
{
    public string Email { get; set; }
    public string Password { get; set; }
    public string DisplayName { get; set; }
    public long UserTypeID { get; set; }      
    public virtual UserType UserType { get; set; } 
}
public class UserTypeDomainModel
{
    public UserType()
    {
        this.Logins = new List<Login>();
    }
    public long UserTypeID { get; set; }
    public string UserType { get; set; }
    public string Description { get; set; }
    public virtual ICollection<Login> Logins { get; set; }
}

public class LoginViewModel
{
    public string Email { get; set; }
    public long UserTypeID {get; set;}

    //Right here
    public List<UserTypeDomainModel> UserTypesSelectList {get; set;}
}

【问题讨论】:

  • 所有很好的答案,谢谢大家。

标签: c# asp.net-mvc


【解决方案1】:

我个人在视图中使用域模型如果它们自然是完全适合的。这可能只发生在本质上是 CRUD 的琐碎项目上(以直接的方式编辑域实体)。我发现为了纯粹性而创建域实体的精确副本是浪费时间。

我将从不稍微修改域模型来满足视图的需求。在我 95% 以上的项目中,我发现自己处于这种情况。当你为了视图而污染域时,就会引入可维护性问题。

【讨论】:

  • 直到您的域实体更新并且您的视图尚未更新。然后,您会对界面中未显示的新必填字段感到头疼。我猜对每个人来说,这仅取决于您的域模型中的更改可以或确实发生的频率。
  • @BradChristie:在 95% 的项目中,我使用映射层将视图模型和域模型分开(自动映射器很好)。对于 5% 的项目(小型、简单的项目......通常是 1 个人的项目)来说,这是矫枉过正的。
  • 可能存在安全隐患。我发现在视图/视图模型中使用域模型实体会显着增加您以“过度发布”攻击的形式引入安全漏洞的可能性(另请参阅odetocode.com/blogs/scott/archive/2012/03/11/…)。我还观察到直接在 view/viewmodel 中使用域实体通常是“贫血域模型”反模式 (martinfowler.com/bliki/AnemicDomainModel.html) 的标志。我将在视图/视图模型中使用“值对象”,但不使用实体。
  • 如果您使用 Automapper 之类的东西而没有像 Scott 的博客文章中所示的那样小心谨慎(不包括某些映射),那么安全问题仍然存在。在一个微不足道的情况下(我认为唯一没有单独的域模型的情况),域模型无论如何都会变得贫乏,因为根据定义,主题是微不足道的。每当域有任何丰富性时,出于这个原因,我都会有单独的域和视图模型。
【解决方案2】:

这取决于您所说的“域模型”是什么意思。你的意思是EF实体吗?还是您的意思是业务层对象?

将 EF 实体传递给视图绝不是一个好主意,尤其是在您使用默认模型绑定的情况下。如果您不小心,这可能会产生安全问题。虽然如果您对传递给视图的业务对象不小心,也会出现同样的问题。

视图模型的巨大优势之一是您可以更精细地控制数据映射,因此您可以更轻松地验证只有正确的映射出现。

不过,这一切都取决于您的应用。如果它是一个简单的应用程序,那么做更复杂的映射可能不值得。如果它是一个复杂的应用程序,它必须存在很长时间,并且可能会更新很多......那么你一定要投入精力。

【讨论】:

  • 我指的是 EF 实体。
  • @Preston - 那是你的数据模型,而不是你的域模型。我上面的建议仍然适用
【解决方案3】:

长期以来,我一直在为由单独的视图模型和域模型引起的感知重复而苦苦挣扎。我会断言,由于它们用于不同的目的,它并不是真正重复,但声明这么多相似的属性仍然感觉“错误”。

在非常小的项目中(尤其是那些具有高度信任的经过身份验证的用户组的项目),我可能只是直接绑定到域模型并完成它。或者,如果视图模型需要不同的结构(如@Eric J. 所述),我可以混合搭配。

然而:ModelBinder 将尝试将请求中的值与模型上的属性相匹配。这意味着域模型上的任何属性都可能被(流氓)请求填充。有一些方法可以防止这种情况发生,但对我来说,安心胜过创建单独的视图模型的一点额外努力。

我不认为绝对需要为只读、未绑定的值创建单独的视图模型(在您的情况下可能是用户类型列表,尽管public virtual ICollection&lt;Login&gt; Logins 可能会否定这一点)。

或者,您可能希望将域模型投影到面向 UI 的抽象(例如IEnumerable&lt;SelectListItem&gt;)。您可以将SelectListItems 用于各种输入机制,因此您不会将自己束缚于特定的 UI 行为。

即使使用抽象,您仍可能需要验证请求不包含非法值。例如,也许只有超级管理员可以分配某些UserTypeDomainModel ID。不管抽象如何,您仍然需要验证这一点。

TLDR:尽可能多地抽象领域模型,找到合适的抽象(新的视图模型并不总是正确的答案),并且(有点偏执)输入验证。 p>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-07
    • 2023-03-08
    • 1970-01-01
    • 2010-12-20
    • 2012-02-22
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多