ASP.NET MVC:“视图必须是愚蠢的”正确的声明吗?

时间:2016-02-05 09:13:34

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

网上对MVC的大多数好参考都强烈建议“观点必须愚蠢”。它不应该包含任何逻辑。当我尝试实现它时,这似乎无效。

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

我可以在这里提出许多其他类似的例子,迫使我把一些逻辑放在视野中。考虑到视图仍然存在逻辑并且JS的使用日益增加,我们仍然可以说“观点必须愚蠢”是一个正确的陈述吗?

有关上述各点解释相同的细节会有所帮助。

备注:

  • 虽然我的问题是基于ASP.NET的,但我期待将答案仅仅引用MVC作为设计模式;无论我使用什么技术。所以请不要建议进行验证的另一种方法。以上几点只是要注意一些视野中需要逻辑的情况。
  • 我如何实现以上几点可能有问题。但我唯一的观点是,使用JS(并在视图中放置逻辑)正在增加。
  • 如果我以错误的方式实施,我们欢迎大家反驳以上几点;只是不要那样重定向整个讨论。

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

4 个答案:

答案 0 :(得分:2)

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

然而,有一些非常简单的逻辑,如下所示是很常见的:

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

然而,服务器端视图代码不应该变得复杂得多,因为这会破坏整个分离问题,并具有适当的抽象和设计模式等,并且变得无法维护。

另请参阅:http://www.asp.net/mvc/overview/getting-started/introduction/adding-a-view

答案 1 :(得分:0)

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

这里的想法是让你的视图模型处理任何需要的操作,并让你的视图参考视图模型。所以改变是中心的。

而且我相信你这样做了。

答案 2 :(得分:0)

这是接受的答案 我认为我们应该将渲染逻辑集中到View部分,而不是集中在他们的ViewModel部分。 即使理论认为“观点必须愚蠢”,这也有一些实际的优点:

1)由于逻辑较少,服务器上的CPU周期较短。

2)节省带宽,因为在线路上传输的数据更少。

3)更好地分离关注点,因为表示逻辑集中在视图中。服务器只需要将数据传递到客户端,有效地简化了服务器端的编码复杂性。

<强>结论:

让理论说“观点必须愚蠢”。将表示逻辑放在客户端是很好的实用方法。

答案 3 :(得分:0)

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

我认为您忽略了可以将更多逻辑推送到域模型的情况。例如,您提到了“姓名”的概念,并且必须在视图中使用条件逻辑来决定是显示名字、姓氏还是全名。我的域模型中有一个名为 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 中,我有带有我需要的任何名称属性的 ViewModel。当我将域模型转换为视图模型时,我的转换逻辑会告诉 ViewModel 要使用哪个属性。如果我需要全名,我使用 Name.FullName。如果我只需要名字,我使用 Name.Firstname。我在任何时候都不需要在我的视图中放置关于名称的条件逻辑。

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

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

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

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