【问题标题】:MVC logic: View needs more dataMVC 逻辑:视图需要更多数据
【发布时间】:2011-11-14 13:16:20
【问题描述】:

我是 MVC 的新手,我可能还没有完全理解它的逻辑,这就是为什么我总是遇到麻烦。

在我看来,MVC 应该将 Web 应用程序的三个部分分开:模型(处理数据:获取、更改等)、控制器(根据用户决定返回哪些数据作为响应请求)和视图(将来自控制器的数据(例如,转换为 HTML)作为响应发送回用户)。

“分离”意味着这三个元素彼此抽象。 Controller不关心Model部分的实现细节(反之亦然),它只是告诉他需要获取(或改变)哪些数据并知道如何处理,Model与视图(即数据转换的方式)。 最后,Controller 与 View 转换无关,他只知道需要转换哪些数据(取决于请求)以及以何种方式转换(例如,为当前数据选择正确的模板)。 而 View 部分是从 Controller 中抽象出来的,它的工作是以某种预设的方式转换特定的输入数据数组。

所以现在假设我有一个网站。它有索引页(/)和一些非索引页(/vacancy/、/about/、/articles/bytag/fun/5/ 等)。 在每一页的顶部都有一个标志。问题是:我希望徽标成为除索引页面本身之外的每个页面上的索引页面的超链接(因为我不希望我的页面包含指向自身的超链接)。 所以我想要索引页面上的“”和其他页面上的“”。 p>

当然,我不想重复自己并创建多个具有相同徽标图像的模板(header_index 和 header_nonindex)。所以,我需要做的是检查我是否在模板某个位置(即视图部分内)的索引页面上,并根据结果添加或不添加链接标签。

在这里我面临一个逻辑问题。我无法在视图中获取地址(因为逻辑上这部分与用户请求无关,它转换数据,从控制器接收)。 所以我需要我的控制器将特定数据(例如页面地址,或像“isIndex”这样的布尔值)发送到视图。但是视图不能“要求”来自控制器的数据,视图只是数据转换的方式。因此,如果转换本身需要任何特定变量,将其添加到 Controller 将使 View 依赖于特定 Controller 和 Controller - 与特定 View 相关,这将破坏抽象和分离的整个想法。 因此,如果不破坏 MVC 逻辑,就无法做我需要的事情。

我错了哪一部分?

【问题讨论】:

  • 这是C#和ASP.NET MVC 3和Razor还是纯学习理论?
  • 比方说,纯学习理论。

标签: model-view-controller


【解决方案1】:

一个经典的难题,但并不是特别孤立于 MVC。在 OOP 中,您希望增加类内的凝聚力并减少类之间的耦合。 MVC 将同样的原则提升到架构级别,每个组件对其活动负责,但与其他两个组件的操作分开。这是 ideal 的情况,但就像在 OOP 中一样,ideal 并不意味着绝对分离。它们确实共享一些数据——控制器访问实体模型、构建视图模型和解释输入(通常作为基于 Web 的 MVC 中的模型)。视图使用视图模型,并且在网络上是输入的来源。该模型可能是最孤立的。

现实情况是,分离不是绝对的,而是连续的。与其他架构模式相比,您有或多或少的分离。 MVC 往往处于架构模式的“更多”分离端,但并非所有 MVC 实现,甚至这些框架内的应用程序实例,在这方面都是平等的。俗话说,“你可以用任何语言编写 Fortran”,这意味着如果你愿意,你可以在任何程度上违反设计模式,甚至可以将其破坏为另一种模式。

这并不总是一件坏事。你必须务实。毕竟,目标不是实现纯粹的架构实现。目标是完成应用程序的业务。在您的情况下,您有一些 UI 目标要求视图可以访问有关哪个控制器正在呈现它的一些详细信息。 ASP.NET MVC 通过 ViewContext 属性公开这一点,该属性反过来公开对 Controller、RouteData 和 HttpContext 的引用。

您可以选择使用这些来实现您的业务目标,但会破坏架构模式,也就是说,视图现在正在处理一些“输入”并直接根据这些值做出一些决策。或者,您也可以选择通过增加视图模型的复杂性来保持您的分离更加清晰,或者通过从包含一些管理属性的基本模型派生,或者在 MVC 中,使用 ViewBag 作为每个模型的扩展相同目的。这增加了与控制器的耦合,因为它现在需要知道视图需要这些管理属性才能正确呈现。同样,它是一个连续统一体 - 您是在增加耦合,而不是在不存在的地方创建耦合。

我已经放弃了创建纯 MVC 的想法。是的,我想尽可能地接近 MVC 框架的范例。使用框架比反对它更容易。但是,当我有一个目标导致我违反了关注点分离(经过彻底检查以确保我确实需要之后)时,我更感兴趣的是以一种可持续和可维护的方式来完成它,而不是跳过架构环做一些框架不适合的事情,或者最好以框架没有预料到的方式完成。

【讨论】:

    【解决方案2】:

    你说得对,MVC 的 3 个组件需要分离,它们的目的是保持代码的干净和分离。

    但这并不意味着它们是独立的。这并不意味着您可以采用任何 VIEW 并将其与任何 CONTROLLER 结合并期望它能够工作。

    如果这样可以提供更好的解决方案,您总是可以稍微扭曲一下模式。 在这种情况下,您应该使用全局变量,可能是静态变量,可以通过 MVC 的 3 个组件访问。

    因此,当您在索引页面的控制器中时,告诉该静态变量您在索引页面中,并且对于所有其他控制器使其成为默认值(默认 = 您不在索引页面上)。然后您可以在任何视图中使用该静态变量,无论控制器如何。

    【讨论】:

    • View 的想法(如我所见)是转换具有特定预设格式的输入数据。因此,视图可以与任何能够以特定格式(和 vv)发送数据的控制器结合使用。功能非常相似。假设“阶乘(int)”接受一个整数并返回它的阶乘(这实际上也是数据转换)。我相信只要将整数作为输入,它就应该可以正常工作,这是唯一的条件。这就是我认为分开的意思。如果函数需要特定的全局变量,则不需要。
    • 全局变量是个坏主意。依赖注入是必经之路-
    猜你喜欢
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 2020-10-29
    • 2011-12-22
    • 2017-04-02
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    相关资源
    最近更新 更多