【问题标题】:ASP.net MVC - One ViewModel per View or per Action?ASP.net MVC - 每个视图或每个操作一个 ViewModel?
【发布时间】:2011-09-13 19:48:55
【问题描述】:

每个视图使用一个 ViewModel 还是每个控制器操作一个更好?

例子:

public ProjectController : Controller
{
    public ActionResult Edit(int id)
    {
        var project = ...;

        return View(new ProjectEditViewModel(project));
    }

    [HttpPost]
    public ActionResult Edit(ProjectEditViewModel model)
    {
    }

    **OR**

    [HttpPost]
    public ActionResult Edit(Project model)
    {
    }

    [HttpPost]
    public ActionResult Edit(ProjectEditPostViewModel model)
    {
    }
}

以下是三个选项,哪个最好?

  1. 对我的 POST/GET 操作使用相同的 ViewModel。
  2. 对我的 GET 操作使用 ViewModel,对我的 POST 操作使用我的域模型。
  3. 对 GET 使用不同的 ViewModel,对 POST 使用不同的 ViewModel。

【问题讨论】:

    标签: c# .net asp.net-mvc


    【解决方案1】:

    对 GET 和 POST 操作使用不同的视图模型是最好和最灵活的设计。但是对于 GET 和 POST 操作使用相同的视图模型也适用于 90% 的情况,这是一个很好的设计。因此,如果在您的场景中使用相同的视图模型,请不要犹豫,像这样重用它。

    在 GET 和 POST 操作使用不同视图模型的情况下,这些类之间仍然存在某种关系:继承或组合。

    【讨论】:

    • 一般来说,使用域模型本身作为您要发布到控制器操作的对象是一个坏主意吗?在我的示例中,如果我的 Project 类是一个实体框架类,那么将它用作我的 POST 控制器操作的参数是不是一个坏主意?
    • @Dismissile,非常糟糕的主意。在任何情况下都不要使用任何域模型作为任何控制器操作的输入/输出。虽然对于这里讨论的视图模型的两种方法可能会有不同的意见,但域模型甚至不应该被考虑。您应该始终定义视图模型。
    • 类似于您所说的从不使用域模型作为任何控制器操作的输入/输出。如果我创建了一个用于编辑项目的 ViewModel 并将其命名为 ProjectEditViewModel,那么该 ViewModel 是否会将项目的引用作为其属性之一,或者您是否会创建一个包含所有需要显示的字段的 ViewModel,然后使用某种映射以从 Project 获取字段到 ViewModel?
    • @Dismissile,我不会将任何域模型作为视图模型的属性引用。我会在这个特定视图中包含并重复我需要的属性。
    • @DarinDimitrov: AD 你的“你应该总是定义视图模型,总是”我宁愿这样定义:总是使用非 DAO 类进行用户交互。它们可能是视图模型实体、应用程序模型实体或任何其他转换为服务器上的数据模型实体的东西。我通常有一个App.Objects 程序集,其中包含在整个应用程序中使用的层间通信 POCO,并由存储库来回转换为数据模型实体。当一个视图需要一个严格的 Asp.net MVC 特定视图模型时,该类就不是同一个程序集的一部分。
    【解决方案2】:

    正确答案

    都不是。没有灵丹妙药,也不应该。

    因此,正确答案是:使用尽可能多的视图模型,以满足您的用户界面流程的需求。这与视图或控制器操作无关。

    有时一个动作需要一个视图,另一个需要一个视图。但不要遵循一些会阻碍你的发展的严格指导方针。在您开发应用程序时,视图模型会自然而然地出现。并且应该。否则,您最终可能会得到基于某些指导方针的不合理观点。

    这实际上与@DarinDimitrov 的答案相似,但有一个直接的结论。

    【讨论】:

      【解决方案3】:

      在 Post 操作中使用不同的模型来接收输入参数(在这种情况下我什至不称它为 ViewModel)而不是将输出参数传递给视图。

      这样您就可以准确地自定义您接受的输入参数。

      【讨论】:

        【解决方案4】:

        我对基本表单遵循这种方法:

        • GET 的一个视图模型
        • POST 的一个视图模型

        GET 模型继承 POST 模型。

        我经常将域对象传递给 GET 模型的构造函数,并用它做两件事:

        1. 使用域对象中的数据填充 POST 模型属性。
        2. 将域对象封装为 GET 模型中的局部变量。我用它来显示来自域对象的一些(只读)数据。省了一点力气。有些人会告诉你不要这样做。

        【讨论】:

        • 与这里的其他答案/cmets 一致,我总是每个视图都有一个模型(或一对 get/post 模型)。
        猜你喜欢
        • 2014-07-12
        • 1970-01-01
        • 2014-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-13
        • 2013-09-14
        • 2019-10-03
        相关资源
        最近更新 更多