最好在MVC中拥有大型控制器或多个控制器?


69

我们正在ASP.NET MVC中构建一个相当大的HR应用程序,到目前为止,我们的控制器变得越来越大。例如,我们有一个Employee控制器,并且包括了所有雇员视图(个人信息,雇员扣除额,家属等)。这些视图中的每一个都可能具有多个操作或子视图(例如CRUD)。每个动作都相对较小,但是控制器可能具有数十种功能。

是否有拆分控制器的最佳实践?与其让Employee控制器具有数十个视图,不如为每个子类型(即EmployeePersonalInfoController,EmployeeDeductionController,EmployeeDependentController)配备一个控制器会更好吗?

最后,这甚至有关系吗?

更新说明

我最初关心的是CRUD动作。例如,让我们考虑创建和删除...

EmployeeController中的当前操作

  CreateEmployee()
  DeleteEmployee()
  CreateEmployeeDeduction()
  DeleteEmployeeDeduction()
  CreateDependent()
  DeleteDependent()
  etc.

如果控制器拆分:

  EmployeeController
    Create()
    Delete()
  EmployeeDeductionController
    Create()
    Delete()
  EmployeeDependentController
    Create()
    Delete()
  EmployeeBenefitController
    Create()
    Delete()
  etc.

在第一种情况下,我们的约100个屏幕分为8-10个大型控制器。在第二个中,我可能会有约50个控制器。

Answers:


16

以我的拙见,如果您要使控制器中的代码保持压缩状态,那么这并不重要。

您的大多数代码都将发生在某个地方的业务层中吗?如果是这种情况,那么您在控制器中真正要做的就是将数据返回到视图。应该的。

不太确定我是否喜欢将控制器分成子类型。虽然您应该保持关注点的分离,但我认为子类型有些过分了。

您可以看一下这篇文章,看看是否有帮助。 相同视图的不同路径

这可能比您建议的子类型方法更好。


不知道“子类型”是否是我最好的措辞。我不会实现区域(将它们分组到文件夹中),而只是创建更多区域。我将用一些示例类型来澄清这个问题。谢谢。
哔哔声,2009年

实际上,实际情况是MVC控制器所做的不仅仅是渲染视图。至少,每个页面都需要一个单独的get和post处理程序。每个都需要不同的输入。如果幸运的话,您渲染的视图模型与返回的视图模型相同。在一篇博文中,您的控制器至少必须将视图模型分解为DTO才能传递到业务逻辑层,并且您可能必须对其进行某种转换,因为来自用户的数据的逻辑分解与发送到业务逻辑层的内容不一定相同。
Triynko

将数据传递到业务层进行处理后,控制器必须处理成功或失败情况。失败时,如果您具有自定义数据模型(例如,将数据呈现为JSON字符串),则内置模型状态是无用的,并且您必须采取其他步骤来确保用户发布的内容正确无误。 -在显示中呈现。成功后,您需要确定下一步将用户发送到何处。所有这些都是不平凡的,它仍然遵循不将业务逻辑放入控制器的基本规则。控制器并不像人们想象的那么简单。
Triynko

31

部分课程使您可以将类分布在多个文件中。这样,您可以将控制器的相关区域分组到单独的文件中,但它们仍将属于同一控制器。例如

EmployeeDeductionController.cs

public partial class EmployeeController
{
    public ActionResult Deduct()
    {
    }
    // etc
}

EmployeeBenefitController.cs

public partial class EmployeeController
{
    public ActionResult GiveBenefit()
    {
    }
    // etc
}

2
这可以很好地工作,这是我要打扰局部类的唯一原因。
Mark Dickinson

4
好主意...但是出于好奇,与将Controller分成多个控制器相比,这有什么好处呢?
哔哔声,2009年

19
一个有趣的想法,但是我认为它有点滥用了部分类功能。部分类主要是为代码生成方案设计的,以便开发人员可以添加到生成的类中,并在重新生成期间保留这些更改。除非引起我的误解,否则我认为使用共享的基类创建单独的控制器比使用局部函数更好。
塞斯·佩特里·约翰逊

11
自发布我的答案以来,我实际上完全同意您的想法。过去,部分课程让我很伤心,现在我通常避免使用它们。哦,我真善变。
山姆·韦塞尔

2
@SamWessel您具体遇到了什么样的问题?
MateuszMigała2015年

11

我不想有50个控制器。现在我的应用程序中有16个,感觉还可以。如果您有50个控制器,则还将有50个用于查看的顶层文件夹。很难找到您需要使用的视图和控制器。正如其他人提到的,动作通常很短,并且在控制器中包含几个动作也并不坏。

我试图按系统部分设置1个控制器。我通过采用数据库模式并在属于一起的表周围画一条线来定义系统部分。


3

为什么不将它们分组?

具有类似的结构

employee/payroll/
    employee/payroll/giveraise
    employee/payroll/manage401k

employee/general/
    employee/general/address
    employee/general/emergencycontact

现在,您可以有一个薪资控制员来处理与薪资有关的操作,还有一个通用控制员来处理雇员的常规详细信息。


1
我们很乐意,但是在标准ASP.NET MVC中没有区域的概念(我相信这是您的建议)。我们可以添加一个扩展来支持区域,但是如果不需要,我不喜欢添加一堆东西。
哔哔

1
我认为瑜伽士的意思是工资单是控制者,giveraise / manage401k是这些人的行为。无需任何扩展,只需向global添加更多路由规则即可。
xandy

1
@Jess等人-现在存在对地区的FYI支持:msdn.microsoft.com/en-us/library/ee671793.aspx
Drew Noakes 2010年

1
Drew评论的更新链接:msdn.microsoft.com/en-us/library/ee671793
v

2

控制器是作为一种上下文中的动作的容器。即,客户控制器将具有与控制客户有关的动作。这特别适合CRUD。由于这个原因,我将使用较少的大型控制器。就是说,作为应用程序架构师,真正由您决定如何选择最适合您的代码的方式,只是因为以一种方式进行更常见并不意味着您必须这样做。

如果您有大量的代码,我建议您研究一下ASP.NET MVC领域。您可以在Scott Gu的博客中Steve Sanderson的博客中找到关于它的出色文章。。如果您有太多的控制器,则可能适合您。

重新阅读您的帖子后,我只是想了一下,我怀疑您的示例与您的代码中的复杂程度还差得很远。如果您不确定不确定是否拆分一个更具体的控制器(而不是CRUDDY,因为CRUD非常简单),则可能会有所帮助。


2

我们一直在使用的另一种方法是拥有ControllerBase,以将横切关注点放在CRUD操作的通用位置。该控制器声明通用操作,并包括特定实体内容的扩展点。没有这样的东西,我们有太多的代码重复。

然后,您继承此控制器并为每个实体创建一个。是的,有很多控制器,但是有这么多的屏幕,我认为这不是主要问题。

大多数动作接受一个复杂的模型,然后我们使用模型绑定器进行游戏,以消除控制器上的混乱情况。您可以在此处看到有关内容的好帖子。

然后,使用@Odd建议这样的区域是一个好主意,至少要分开视图,因为当您有很多视图时便会一团糟。

希望ASP.NET MVC v2将带给我们一些领域,并将视图封装在不同的程序集中(实际上,现在可以通过扩展VirtualPathProvider类来完成)。


1

我将围绕用例及其逻辑分组大致组织控制器。例如,如果您有多个管理/ HR型用例,可能对一小部分人可用,请将它们捆绑在一个控制器中。可以围绕特定域模型对象来组织其他控制器,例如自助休假管理,薪水查询等。没有硬性规定,必须在不对单个控制器承担过多责任与重用公共控制器之间取得平衡。内部结构。

还请记住,您的控制器中不应包含核心业务逻辑。它们真正实现了前端行为,而真正的系统规则应该在您的域模型和服务层中。只要将事物大致保持在正确的层中并合理地分离,就可以将单个操作放置在控制器中的方式不会太过错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.