MVC:在哪里放置业务逻辑?

时间:2013-09-01 21:40:45

标签: c# asp.net-mvc model-view-controller business-logic

首先,我已经看到了很多这方面的问题,但背后还没有足够的推理。如果我的问题不够好而且应该删除,我会理解。

我已经看了一下,例如,this和45+投票的答案说他建议你把业务逻辑放在模型中,听起来很合乎逻辑。

然而,我的第一个大型项目我完全在控制器中完成了所有BL,因为我没有质疑这些事情,看看它是如何在AccountController完成的,如果您选择自动添加MVC与表单身份验证。所有方法看起来都非常充满BL。或者也许它是可以添加的最少量的代码,我忽略了一些东西?

youtube上的一个人通过将所有逻辑放入他的模型中问我是否正确,起初我不是!然后我开始想,也许他是对的!?

那么,毕竟,我在哪里放置我的业务逻辑?如果它在模型类中,那么,在控制器中的方法中应该将多少代码视为健康数量?一行最多从控制器中的模型调用一些方法,然后返回视图?

12 个答案:

答案 0 :(得分:48)

我更喜欢将域逻辑放在模型中,原因有两个。

  1. 模型中应该没有UI代码,因此更容易测试。在编写任何UI代码之前,我希望尽可能地使用完全工作(意味着完整的测试覆盖)模型。控制器可以相信模型正在做正确的事情并且只处理UI问题。

  2. 如果您将域逻辑放在控制器中,那么在不同的应用程序之间或甚至不同的控制器之间共享并不容易。

答案 1 :(得分:36)

我喜欢保持我的模特清洁I.e.只是属性而没有业务逻辑。我总是认为将依赖项注入控制器很好,这些依赖项包含我在模型上执行的逻辑。我希望在可能的情况下坚持单一责任原则,我发现有很多方法的模型很快就会膨胀。两者都有利有弊,注入大量依赖有一个开销,但允许单独测试并保持类简单,你最终会有更精简的控制器。尽管我的逻辑实际上并不存在于我的模型中作为类的成员,但它仍然是业务逻辑。我倾向于没有在控制器中定义业务逻辑,因为像Httpcontext这样的模拟事情有点像噩梦并且是不必要的。

答案 2 :(得分:21)

商家逻辑属于问题域,属于问题域的所有内容都转到MVC中的模型

控制器应负责将数据从模型传递到视图,并从视图传递回模型。因此,控制器是用户与之交互的内容与程序如何建模和存储问题状态之间的桥梁。 管道,可以这么说。

这里的关键是业务逻辑和管道逻辑之间的区别。在我看来,自动生成的帐户控制器所做的主要是管道,而不是真正的业务逻辑。请记住,管道逻辑根本不一定是短路的,因此您不需要施加人为限制(例如“控制器中最多X个调用”)。

答案 3 :(得分:10)

我的团队从webforms(asp.net)转移到mvc时做了很多研究,并提出了以下结构。据我所知,它不是关于应用程序的大小。它关于保持代码清洁和清晰。

<强> DALProject

AccountsDAL.cs --- > Calls SP or any ORM if ur using any

BLLProject

AccountsBLL.cs ---> Calls DAL

<强> WebProject

Model
    AccountsModel --- > Contains properties And call BLL
Controllers
    IndexController ---> Calls Models and returns View
Views
    Index

控制器应负责模型和视图之间的数据传递。除此之外,不应该有任何不必要的代码。例如,如果您正在记录它,则应该在模型级别而不是控制器上完成。

答案 4 :(得分:10)

围绕这个话题似乎有些混乱。大多数人似乎都倾向于将MVC模式与N层架构混淆为一种或两种情况。实际情况是这两种方法可以一起使用,但一种不依赖于另一种,也不需要。

N层架构涉及将应用程序分成多个层。一个简单的例子是将应用程序拆分为表示层,业务逻辑层和数据访问层。

MVC是一种处理应用程序表示层的设计模式。完全可以按照MVC方法设计应用程序,而不将业务逻辑和数据访问逻辑与表示层分离,从而最终得到单层设计。

结果,如果你遵循MVC方法而不将应用程序分成层,那么你最终会得到模型,视图和控制器,它们具有一些业务规则和数据访问逻辑与其余逻辑混合在一起。

根据定义,在N层体系结构中,表示层应该只能与业务逻辑层进行通信,因此它应该认为任何MVC组件只能与业务逻辑层进行通信。

如果您正在构建一个不涉及演示的应用程序,因此不是表示层,那么您不必关心MVC模式。但是,即使没有涉及表示层,您仍然可以将应用程序拆分为多个层,因此遵循N层设计。

答案 5 :(得分:4)

一般来说,业务逻辑不应该驻留在任何MVC播放器中;它只应由控制器操作消耗

正如许多人所提到的,最好创建一个库来托管业务逻辑,作为一组客户端无关,可重用的组件。

通过这种方式,我们可以使用我们的软件大大提高可重用性,兼容性,可扩展性和可测试性。我们还减少了对某些框架功能的依赖,这使得更容易迁移到更新/不同的技术。

将我们的业务逻辑抽象为独立的组件(或组件)多年来为我们提供了很好的服务。几乎所有.NET技术(ASP.NET MVC / API /核心,WPF,Win Forms,WCF,UWP,WF,控制台等)都可以使用我们的业务逻辑。

此外,我们喜欢我们的中间层来处理业务规则和验证逻辑,以减少我们对.NET MVC框架的依赖性。例如,我们避免使用.NET MVC验证帮助程序,而是依赖于我们自己的帮助程序。这是允许我们从任何.NET技术轻松使用业务逻辑的另一个因素。

以这种方式逻辑设计我们的中间层使我们能够轻松实现这种物理架构:

enter image description here

它是用Peasy.NET写的,多年来一直为我们服务。事实上,我们决定开源。

如果有人对我们的中间层看起来很好奇,那么这是一个与客户无关的业务层的sample。它还展示了多个.NET客户端(ASP.NET MVC,Web Api和WPF)对它的消耗。

希望这有助于某人!

答案 6 :(得分:2)

我也想保持模特的清洁(参考:@Mark Walsh)。无法重用嵌入在控制器中的逻辑的问题可以通过依赖注入轻松解决,或者,如果您认为存在太多,则通过接口公开您的业务/域逻辑并使用控制器中的façade模式。这样您就可以获得所需的功能,但要保持控制器和模型的良好和干净。

答案 7 :(得分:1)

我也希望保持模特清洁。 MVC控制器应仅用于拨打电话,也应保持清洁。因此,根据其可重用性,灵敏度和相关性,可以在

中编写业务逻辑

1.WebApi控制器:使用webapi控制器的优势在于,您可以将这些服务稍后作为服务公开给其他设备,使您的代码可以重复使用。

<强> 2。 BAL / Common commonent:有一些逻辑具有特定用途,不能作为api公开,可以在这个类中推送。

第3。存储库:所有与数据库相关的查询都添加到存储库中。可以有一个通用存储库,它将为每个表实现所有功能(CRUD操作)或特定存储库。取决于要执行的操作。

答案 8 :(得分:1)

正如ahanusa所写,您应该将业务逻辑放入单独的DLL或单独的目录中。
我经常在模型和控制器的同一级别使用名为Logics的目录,在该目录中放置执行业务逻辑的类。
通过这种方式,我让模型和控制器都干净了。

答案 9 :(得分:1)

我的一般回答是,业务逻辑通常分为两类:

面向对象的业务逻辑::将模型建模为对象(在模型中),通常作为存储库注入。

过程业务逻辑:进入具有可注入控制器的接口的服务。

控制器逻辑:该逻辑控制如何接收命令并将其传递给模型/服务,然后将这些结果如何传递给视图。

控制器应该没有 业务逻辑 ,这是设计模式中非常具体的部分,用于控制用户界面如何将输入传递给处理业务逻辑(或服务,如果您的问题本质上是过程性的)的模型。

答案 10 :(得分:1)

业务逻辑不应进入模型视图或控制器。应该有一个单独的 业务逻辑层 ;该层的唯一目的是处理您的业务逻辑。这更符合SOLID

如果将业务逻辑放入M V或C中,最终将得到难以测试/重用的代码。

答案 11 :(得分:0)

我知道这是关于MVC的问题,但我认为我给出的示例(Web API)将非常有用。

我正在开发我的第一个Web API,并且我正在重新使用其他应用程序中的业务逻辑。具体来说,它来自外部DLL,因此我的API仅用于与SAP解决方案“交谈”,接收来自PO的请求并发回响应。

我如何将我的逻辑(已经实现)放入我的控制器?我不需要它。我的控制器只接收,验证请求并撰写响应以发回数据。

我正在使用ViewModel类,他们必须拥有的只是一个映射函数,只是从TransferObjects(来自外部DLL)读取信息并转换为ViewModel。

我对使用业务逻辑的应用程序(在本例中为Web API)感到不舒服,我认为以这种方式会丢失可重用性。

我将业务逻辑视为我注入控制器的依赖。

我在遗留下做了很多重构以提供单元可测试解决方案,我必须创建大量接口并在遗留中实现一些设计模式以提供此解决方案。

在我看来,业务层必须是应用程序的一部分,最好是在另一个类库中。因此,您将在应用程序中实现真正的分离概念。

当然,如果您的CORE(业务)您的应用程序(API / WebSite),业务规则将实现到您的MVC类中。但是在未来如果你想开发一个新的应用程序并且一些业务规则是相同的,我敢打赌你会遇到很多问题只是为了维护两个应用程序中实现的相同逻辑。