【问题标题】:ASP.NET MVC: Is "views must be dumb" correct statement?ASP.NET MVC:“视图必须是愚蠢的”正确说法吗?
【发布时间】:2016-05-15 04:44:34
【问题描述】:

Web 上大多数关于 MVC 的优秀参考都强烈建议“视图必须是愚蠢的”。它不应该包含任何逻辑。当我尝试实现它时,这似乎无效。

  • 我的一些视图只显示学生的名字,一些只显示姓氏,一些显示全名。我的数据库(以及 POCO 和 DTO)将名称存储在单独的组件中。我认为格式化名称的最佳位置是视图。
  • 我的视图在客户端的某些操作上发生了变化,而没有访问服务器。例如,单击某个按钮时,它会隐藏视图的某些部分并显示其他部分并禁用某些控件。或者另一个按钮打开新窗口并接受一些输入并验证它。此输入永远不会发送到服务器;它仅对某些客户端活动有用。
  • 我在服务器端进行了验证。但为了将命中保存到服务器,我也在客户端进行了验证。
  • 使用 KnockoutJS 进行数据绑定。
  • 根据从服务器接收到的数据(开始日期和结束日期),我在客户端生成表格以显示该时段的各个部分,每个部分切片 1 小时。这是类似于 GUI 的调度。为了实现这一点,我需要进行日期和时间计算。当我在石器时代(ASP.NET WebForms)时,我在服务器端生成这个表;我知道你很震惊。我将其转移到 JS 以提高性能。
  • 在 SPA 中,视图通过 AJAX 仅从服务器获取必要的数据来保存大部分逻辑。

我可以在这里放许多其他类似的例子,这些例子迫使我把一些逻辑放在眼里。考虑到视图仍然具有逻辑性,并且使用 JS 的人数日益增加,我们还能说“视图必须愚蠢”是正确的说法吗?

对以上几点进行解释的一些细节会有所帮助。

注意事项:

  • 虽然我的问题是基于 ASP.NET,但我希望得到的答案仅引用 MVC 作为设计模式;无论我使用什么技术。因此,请不要建议进行验证的另一种方法。以上几点只是为了说明一些需要考虑逻辑的情况。
  • 我执行上述几点的方式可能有问题。但我唯一的观点是,JS 的使用(并因此将逻辑放入视图)正在增加。
  • 欢迎大家反驳以上几点,以防我执行错误;只是不要以这种方式重定向整个讨论。

编辑 1: @kayess:是的,我有模型和视图模型,这在 MVC 中很明显。与特定视图密切相关且无法重用的服务器逻辑放在 ViewModels 中。可重用的领域逻辑的主要部分放在模型中。即使在拥有 ViewModel 之后,我还是更愿意在客户端做很多事情。关于缩小问题,这个问题的基本答案将是“是”或“否”。其他细节将只是为了支持答案。 我认为这不会引起意见,因为一定有一些关于 MVC 观点的东西我没有完全理解。回答问题的人只需向我指出

【问题讨论】:

    标签: asp.net-mvc design-patterns model-view-controller view


    【解决方案1】:

    我认为“视图必须是愚蠢的”通常是指具体视图的服务器端部分。在视图中使用 TypeScript/JS 是完全正常的。但是,我不希望在从数据库中获取记录的视图中有几十行 C#。

    但是,有一些非常简单的逻辑,例如以下是很常见的:

    @{
        if(user.IsLoggedIn)
        {
            <span>You have new messages!</span>
        }
        else
        {
            <span>You need to login to view messages.</span>
        }
    }
    

    但是,服务器端视图代码不应该比这复杂得多,因为这会破坏分离关注点以及具有适当的抽象和设计模式等的整个点,并且变得无法维护。

    另请参阅:Microsoft documentation on "Adding a View"

    【讨论】:

      【解决方案2】:

      可能是任何技术都有一套理论支持不同的概念,就像你说的观点应该是愚蠢的,模型的拥护者应该是愚蠢的。

      这里的想法是让您的视图模型在需要时负责操作,并让您的视图引用视图模型。所以这种变化是中心化的。

      而且我相信你已经这样做了。

      【讨论】:

        【解决方案3】:

        虽然这是一个老问题并且有一个公认的答案,但我想补充一些没有在任何答案中涉及的要点。

        我认为您忽略了可以将更多逻辑推送到您的域模型的情况。例如,您提到了“姓名”的概念,并且您必须在视图中使用条件逻辑来决定是显示名字、姓氏还是全名。我的域模型中有一个名为 Name 的类。它结合了 FirstName、LastName 和 FullName 的逻辑,如下所示:

        public class Name
        {  
            public Name(string firstName, string lastName)
            {
                this.FirstName = firstName;           
                this.LastName = lastName;            
            }
        
            public string FirstName { get; }       
            public string LastName { get; }      
           
            public string FullName
            {
                get { return $"{this.FirstName} {this.LastName}"; }
            }        
        }
        

        在我的 UI 中,我有 ViewModels 以及我需要的任何名称属性。当我将域模型转换为视图模型时,我的转换逻辑会告诉 ViewModel 使用哪个属性。如果我需要 FullName,我使用 Name.FullName。如果我只需要名字,我使用 Name.Firstname。在任何时候我都不需要在我的视图中放置关于名称的条件逻辑。

        此外,您可以使用自定义助手、格式化程序和扩展来封装视图的可重用逻辑。例如,我有用于格式化电话号码、地址等的实用程序,因此我不必将此逻辑放在需要它的每个视图中。我的 UI 中还有一个分页模块,它封装了分页,因此除了调用分页器之外,我的视图中不必有分页逻辑。

        局部视图也很有帮助。例如,从接受的答案中,我会将以下内容放在部分视图中,并在每个视图中调用它,而不是在每个视图中重复条件逻辑:

        @{
            if(user.IsLoggedIn)
            {
                <span>You have new messages!</span>
            }
            else
            {
                <span>You need to login to view messages.</span>
            }
        }
        

        我的观点是,您可以做很多事情来将逻辑从视图中移出以保持它们的愚蠢。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-10
          • 1970-01-01
          • 2011-06-09
          • 1970-01-01
          • 2012-01-25
          • 2011-01-20
          • 2010-09-18
          相关资源
          最近更新 更多