排序逻辑应该放在模型,视图还是控制器中?

时间:2012-08-15 13:15:36

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

我有一个下拉列表,显示从表到最终用户的值。我希望按字母顺序排列这些值。

根据适当的MVC设计,我应该在什么层放置我的排序逻辑:模型,视图或控制器?

编辑:在回答LarsH的问题时,“你的意思是代码决定了什么样的排序顺序吗?还是执行排序的代码?”,我原本指的是决定什么的代码需要排序顺序。

12 个答案:

答案 0 :(得分:62)

谁控制排序顺序?

Simple MVC diagram(来自Wikipedia

1)数据本身内的自然顺序:

订单是模型的一部分,所以它应该去那里。 “所有数据”的原始提取将按排序顺序返回数据,并且没有用于选择排序顺序的界面。

2)用户应该控制他们看到数据的方式:

View将提供与Controller交互的接口(例如上升/下降箭头),并且Model能够很好地理解数据,以便对数据执行请求的排序。但是,与(1)中不同,数据的原始拉动不一定必须进行排序。

在任何一种情况下,

View不理解正在进行排序,另外还有能够显示选择了哪个排序方向。不要把逻辑放在那里。

小警告

排序功能可以完全在视图中,在一种情况下(我可以随意思考;可能还有更多):

“哑”排序,其中所有数据已经​​在视图中,并且不必使用任何领域知识来进行排序。例如,非常简单的字符串或数字比较。例如,当结果可能跨多个页面分割时,这在网页上的搜索结果中是不可能的。

答案 1 :(得分:47)

(注意:这句引文和引文来自@dasblinkenlight's answer,但我们不同意我们对它的解释。阅读他的帖子并自己决定。)

根据MVC description

  

控制器可以向其关联视图发送命令以更改视图的模型表示(例如,通过滚动文档)。它可以向模型发送命令以更新模型的状态(例如,编辑文档)。

排序逻辑(例如,排序比较器/排序算法)属于模型,因为它包含业务规则和状态数据。由于改变模型数据的排序方式完全属于“更改视图的模型表示”类别,控制器负责通过调用model.changeSortedState()方法“进行排序”。

答案 2 :(得分:18)

根据MVC description

  

控制器可以向其关联视图发送命令以更改视图的模型表示(例如,通过滚动文档)。它可以向模型发送命令以更新模型的状态(例如,编辑文档)。

根据这一点,排序逻辑属于控制器,因为改变模型数据的排序方式完全属于“更改视图的模型表示”类别。

编辑:为了澄清评论中提到的多个误解,“排序逻辑”执行排序的代码;它是定义排序的代码。排序逻辑将各个项目相互比较以建立顺序(例如,通过IComparator<T>的实例)或包含构造用于由外部系统排序的对象的逻辑(例如,通过{{1的实例) }})。此逻辑属于您的控制器,因为它需要与应用程序的“业务”方面相关的知识。完成排序就足够了,但它与实际执行它的代码是分开的。排序的代码可能在您的视图中,在您的模型中,甚至在支持模型的持久层中(例如您的SQL数据库)。

答案 3 :(得分:10)

以上都不是。排序是业务逻辑,业务逻辑不属于三者中的任何一个。并非您的应用程序中的每一段代码都是模型,视图或控制器。

我在MVC应用程序中通常做的是我有一个执行所有业务逻辑的服务层。服务层中的方法应该具有干净,简单的API以及具有良好命名的参数。然后,您可以从控制器调用这些方法来操作模型中的数据。

从这个意义上说,排序是“在控制器中”,但是进行排序的代码本身不应该在控制器中实现,只能从那里调用。

答案 4 :(得分:8)

绝对不是控制器:它向视图和模型发送消息,但应尽可能少地工作。如果用户可以通过通知模型或视图来更改控制器处理请求的排序。

如果它是一个纯粹的View,那么可能是View。如果应用程序在没有排序的情况下也能正常工作,那么排序只是表示的一部分,应该放在视图中。

如果排序是域的固有部分,那么它应该放在模型中。

答案 5 :(得分:7)

  • 视图是MVC的一部分,它应该包含表示逻辑。
  • 模型层是包含业务逻辑的地方。
  • 控制器仅根据用户输入更改两者的状态。

所以选择是 - 你认为这是域业务逻辑或表示逻辑的一部分。

如果您正在实现适当的MVC Model2或经典MVC模式,那么我会说模型层提供的数据排序应该由视图对模型层的请求触发。查看请求有序数据,模型层提供它。

但是,由于您使用ASP.NET MVC对MVC模式的解释,这与您的标准MVC略有不同 - ViewModel实例应该从模型层请求有序信息(出于某种原因,ASP.NET框架认为模板应该被称为“视图”,视图应该被称为“viewmodels”..这很奇怪)。

答案 6 :(得分:5)

我通常会在控制器中按照其他答案保持与模式一致。请参阅下面的推理。

我一直在考虑这个并阅读答案和相关材料,并且务实地说我会说这将取决于您的申请:

是中型/大型应用程序和/或是否有多个与之关联的UI(即Windows应用程序,Web界面和手机界面)。

  • 在这种情况下,我可能会构建一个服务层并将其放入 然后从业务对象中调用适当的方法 控制器。

如果它是一个定义良好的单一UI网站,并且您使用的是EF Code First之类的东西,并且您没有或无意创建服务层并计划使用简单的开箱即用扩展方法来实现它:

  • 在这种情况下,我可能会以实用的方式将它放在控制器中 它最适合时间/预算。

如果与上述BUT相同,则无法使用开箱即用的扩展方法实现。

  • 我可能会选择在Model类中弹出它(如果它真的是定制的 这种单一类型)因为它比a更合适 控制器。如果排序可以应用于多个类 我将在扩展方法中实现它,然后在中调用它 控制器。

总结一下:

教条回答:服务层

务实回答:通常是控制器

答案 7 :(得分:3)

我建议从表中对数据进行排序 - 数据小到足以在下拉列表中使用 - 应该来自已经通过查询排序的数据库。对我来说,这使得模型成为应用排序的地方。

如果您决定手动进行排序,我认为使用模型或控制器作为逻辑的首选位置有很好的理由。限制将是您的特定框架。我更喜欢仅在模型中管理数据。我使用控制器将数据(模型)和演示文稿(视图)结合起来(就像我自己一样)。

答案 8 :(得分:2)

虽然我原则上同意排序是商业逻辑的想法,因为通过将其分解为它的起源,您最终会得到类似“客户希望产品页面显示的图像按日期排序”然后它很明显,数据的排序顺序通常不是任意的 - 即使没有排序因为遗漏仍然是商业决策(空列表仍然是列表)。

但是......这些答案似乎没有考虑到ORM技术的进步,我只能谈谈实体框架(让我们避免争论这是否是真正的ORM,这不是重点)来自Microsoft,因为我使用它,但我确信其他ORM提供类似的功能。

如果我使用MS MVC和Entity Framework为Product类创建一个Strongly Typed视图,并且Product和Image表之间存在外键关系(例如FK_Product_Image_ProductId)那么我就可以开箱即用了在视图中使用类似的内容快速对图像进行排序:

@foreach(Image i in Model.Image.OrderBy(e => e.DisplayOrder)){ //etc etc... }

提到了一个特定的业务逻辑层,我也用它来执行80%的业务逻辑,但我不会在我的业务逻辑层中编写排序功能,模仿出现的问题。实体框架中的框。

除了这样说之外,我认为这个问题没有正确答案;你应该在可能的情况下抽象复杂的业务逻辑,但不要以重新发明轮子为代价。

答案 9 :(得分:1)

假设您拥有MVC网站,WebForms网站和移动应用程序。

如果您希望排序在这些表示层之间保持一致,那么我会说在表示层之外排序。服务将是一个很好的候选人。

否则,我会将该逻辑存储在视图模型中。为什么?因为它可以重复使用并且易于测试。

答案 10 :(得分:0)

在你列出的三个中,我会说它属于控制器。不过,我真的不喜欢在控制器中放置这种逻辑。我通常创建一个控制器与之通信的服务层,负责与数据存储通信并处理排序逻辑。对于小型应用程序,它可以很好地坐在控制器中。

答案 11 :(得分:0)

这是一个问题与asp.net的问题,但由于有人提到了Rails,我认为在这种情况下考虑问题会很有趣。在Rails中,由于框架和ActiveRecord / ActiveQuery api为它提供了排序,因此将检索作为控制器操作执行排序是很自然的。另一方面,可以为静态项定义某种自定义排序顺序,并将其放在模型中以供控制器使用,因此模型可以在排序逻辑中起作用,即使它没有执行直接操作。无论它是什么,可以安全地说,在视图中放置排序逻辑通常都不赞成。

我有点觉得有些答案完全反对将控件放入控制器或模型中,我发现它们对我的品味太过苛刻了,但我认为这取决于所用框架的性质和通常与之相关的惯例。我也同意比尔K的评论,即首先分离是更重要的。