C# MVC:将业务逻辑放在哪里?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18563229/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 12:35:40  来源:igfitidea点击:

MVC: Where to put business logic?

c#asp.net-mvcmodel-view-controllerbusiness-logic

提问by Andrius Naru?evi?ius

First of all, I have seen many questions of this, but not enough reasoning behind that. If my question is not good enough and should be removed I'll understand.

首先,我看到了很多关于这个的问题,但背后的推理还不够。如果我的问题不够好,应该删除,我会理解的。

I have taken a look at, for example, thisand a 45+ voted up answer says he advises you to put the business logic in the model, which sounds pretty logical.

例如,我查看了这个,一个 45+ 投票的答案说他建议您将业务逻辑放入模型中,这听起来很合乎逻辑。

However, my first large project I have done with all my BL fully in the controllers, because I didn't question these things and looked how it is done in the AccountControllerwhich is the automatically added if you choose MVC with form authentication. All the methods look pretty stuffed with BL. Or maybe it is the least amount of code that was possible to be added and I am overlooking things?

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

A person on youtube asked me whether he is right by putting all the logic into his models and at first I was no! Then I started thinking that maybe he was right!?

youtube 上的一个人问我他是否将所有逻辑都放入他的模型中,一开始我是错的!然后我开始想,也许他是对的!?

So, after all, where do I put my business logic?If it is in models classes, then, how much code should be considered a healthy amount in a method which is in controller? One line to call some method from the model in a controller at most and then a return to the view?

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

采纳答案by Ferruccio

I prefer to put domain logic in the model for a couple of reasons.

出于几个原因,我更喜欢将域逻辑放入模型中。

  1. The model should have no UI code in it and thus be easier to test. Whenever possible, I like to have a fully working (meaning complete test coverage) model before writing any UI code. The controller can trust that the model is doing the right thing and just deal with UI concerns.

  2. If you put domain logic in a controller, it's not as easy to share between different apps, or even between different controllers.

  1. 该模型中不应包含 UI 代码,因此更易于测试。只要有可能,我喜欢在编写任何 UI 代码之前有一个完全工作(意味着完整的测试覆盖)模型。控制器可以相信模型正在做正确的事情并且只处理 UI 问题。

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

回答by Mark Walsh

I like to keep my models clean I.e. Just with properties and no business logic. I always think its good to inject dependencies into the controller and these dependencies contain the logic I perform on my models. I like to adhere to the single responsibility principle where possible and I find that models with tons of methods get bloated very quickly. There's pros and cons for both, injecting a lot of dependencies has an overhead yet allows to test in isolation and keeps classes simple and you'll end up having leaner controllers. Despite my logic not actually existing on my model as members of the class, its still business logic. I tend to not have business logic defined in the controller as mocking things like the Httpcontext are a bit of a nightmare and unnecessary.

我喜欢保持我的模型干净,即只有属性,没有业务逻辑。我一直认为将依赖项注入控制器是好的,这些依赖项包含我在模型上执行的逻辑。我喜欢尽可能坚持单一责任原则,我发现拥有大量方法的模型很快就会变得臃肿。两者都有利有弊,注入大量依赖项会产生开销,但允许单独测试并保持类简单,最终您将拥有更精简的控制器。尽管我的逻辑实际上并不作为类的成员存在于我的模型中,但它仍然是业务逻辑。我倾向于没有在控制器中定义业务逻辑,因为像 Httpcontext 这样的嘲讽有点像噩梦,而且没有必要。

回答by Theodoros Chatzigiannakis

The businesslogic belongs to the problem domain and everything that belongs to the problem domain goes to the modelin MVC.

业务逻辑属于问题域,一切都属于问题域进入到模型中MVC。

The controllershould be responsible for passing the data from the model to the view and from the view back to the model. The controller is therefore the bridge between what the user interacts with and how the program models and stores the state of the problem. The plumbing, so to speak.

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

The key here is the distinction between the business logic and the plumbing logic. In my opinion, what the autogenerated Account Controller does is mostly plumbing, not really business logic. Keep in mind that the plumbing logic isn't necessarily short at all, so you don't need to impose artificial limits (like "X number of calls at most in the controller").

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

回答by Bob H

I like to keep my models clean as well (ref: @Mark Walsh). The problem of not being able to reuse logic embedded in controllers can easily be overcome through dependency injection, or, if you think there would be too much of that, expose your business/domain logic through interfaces and use the fa?ade pattern in the controllers. That way you get the functionality you need, but keep both the controllers and model nice and clean.

我也喜欢保持我的模型干净(参考:@Mark Walsh)。无法重用控制器中嵌入的逻辑的问题可以通过依赖注入轻松解决,或者,如果您认为这样会太多,请通过接口公开您的业务/域逻辑并在控制器。这样你就可以得到你需要的功能,同时保持控制器和模型干净整洁。

回答by Nikitesh

I would also prefer to keep models clean. The MVC controllers should be used only to make calls and should also be kept clean. So depending upon its reusability, sensitivity and relevance the business logic can be written in

我也更愿意保持模型清洁。MVC 控制器应仅用于进行调用,并且还应保持清洁。因此,根据其可重用性、敏感性和相关性,可以编写业务逻辑

1.WebApi Controller:The advantage of using a webapi controller is that you can expose these as services later to other devices making your code reuseable.

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

2. BAL / Common commonent:There are some logics which have specific usage and cannot be exposed as an api, can be pushed in this class.

2. BAL / Common common:有些逻辑有特定的用法,不能作为api暴露,可以在这个类中推送。

3. Repository:All the database related queries are added in a repository. There can be a generic repository which will implement all the functions (CRUD operations)or specific repositories for each table. Depending upon the operations to be performed.

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

回答by Muneeb Zulfiqar

My team when moved to mvc from webforms (asp.net) did alot of research and came up with the following structure. According to me its not about how big or small the application is. Its about keeping the code clean and clear.

我的团队从 webforms (asp.net) 转移到 mvc 时做了很多研究,并提出了以下结构。在我看来,这与应用程序的大小无关。它是关于保持代码干净和清晰。

DALProject

DAL项目

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

Controllersshould be responsible for the data passing between model and view. Other than that it there should not be any unnecessary code. For example if you are logging it should be done at model level rather than controller.

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

回答by Otta Augusto

I know that it's a question about MVC, but I think the example I'm giving (Web API) will be usefull.

我知道这是一个关于 MVC 的问题,但我认为我给出的示例(Web API)会很有用。

I'm developing my first Web API and I'm re-using the business logic from other applications. To be specific, it comes from an external DLL, so my API is used just to "talk" with a SAP solution, receiving requests from PO and send responses back.

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

How could I put my logic (already implemented) into my controller? I don't need it. My controller will only receive, validate requests and compose responses to send data back.

我怎么能把我的逻辑(已经实现)放到我的控制器中?我不需要它。我的控制器只会接收、验证请求并撰写响应以将数据发回。

I'm working with ViewModel classes and all they must have is a mapping function, just to read information from TransferObjects (that comes from the external DLL) and translate to a ViewModel.

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

I'm not comfortable with my application (in this case Web API) holding the business logic, I think that the re-usability will be lost in this way.

我对我的应用程序(在这种情况下是 Web API)持有业务逻辑不满意,我认为这样会失去可重用性。

I'm treating my business logic as a dependency that I inject into controller.

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

I've done a lot of refactoring in the legacy to provide a Unit Testable solution, I had to create a lot of interfaces and implement some design patterns into the legacy to provide this solution.

我在遗留系统中进行了大量重构以提供可单元测试的解决方案,我必须创建大量接口并将一些设计模式实现到遗留系统中以提供此解决方案。

In my point of view, the business layer must be apart of the application, preferably in another class library. So you will have a real separation concept implemented in your application.

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

Of course, if your CORE (business) is your application (API/WebSite), the business rules will be implemented into your MVC classes. But in the future if you want to develop a new app and some business rules are the same, I bet you will have a lot of problems just to maintain the same logic implemented in both applications.

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

回答by treefiddy

There seems to be some confusion around this topic. Mostly it seems that people tend to confuse the MVC pattern with N-tier architecture as an either/or situation. The reality is that the two approaches can be used together, but one is not dependent on the other and neither is required.

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

N-tier architecture is concerned with separating an application into multiple tiers. A simple example is where the application is split into a presentation layer, a business logic layer, and a data access layer.

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

MVC is a design pattern dealing with the presentation layer of an application. It is entirely possible to design an application following an MVC approach without separating business logic and data access logic from the presentation layer and thus end up with a single tier design.

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

The result, if you are following an MVC approach without also separating the application into tiers is that you end up with Models, Views, and Controllers that have bits of business rules and data access logic mixed in with the rest of the logic.

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

By definition, in an N-tier architecture, the presentation tier is only supposed to be able to communicate with the business logic layer so it should hold that any of the MVC components can only communicate with the business logic layer.

根据定义,在 N 层架构中,表示层只能与业务逻辑层通信,因此它应该持有任何 MVC 组件只能与业务逻辑层通信。

If you are building an application that does not involve presentation, and thus not a presentation layer, you should not have to concern yourself with the MVC pattern. However, you very well may still split your application into multiple tiers and thus follow an N-tier design even though there is no presentation layer involved.

如果您正在构建一个不涉及表示的应用程序,因此也不是表示层,您不应该关心 MVC 模式。但是,即使不涉及表示层,您仍然很可能将应用程序拆分为多个层,从而遵循 N 层设计。

回答by ahanusa

Generally speaking, business logic shouldn't reside in any of the MVC players; it should only be consumedby your controller actions.

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

As many have mentioned, it's best to create a library to host business logic as a set of client agnostic, reusable components.

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

When done this way, we greatly increase reusability, compatibility, scalability, and testability with our software. We also reduce our dependence on certain framework features, which makes it easier to migrate to newer / different technologies.

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

Abstracting our business logic into a stand alone assembly (or assemblies) has served us well over the years. Our business logic can then be consumed by virtually any .NET technology (ASP.NET MVC/API/Core, WPF, Win Forms, WCF, UWP, WF, Console, etc.).

多年来,将我们的业务逻辑抽象为一个独立的程序集(或多个程序集)对我们很有帮助。我们的业务逻辑几乎可以被任何 .NET 技术(ASP.NET MVC/API/Core、WPF、Win Forms、WCF、UWP、WF、Console 等)使用。

In addition, we like our middle tier to handle business rule and validation logic to reduce our dependencies on the .NET MVC Framework's. For example, we avoid using the .NET MVCs validation helpers and instead rely on our own. This is another factor that allows us to easily consume our business logic from any .NET technology.

此外,我们希望我们的中间层处理业务规则和验证逻辑,以减少我们对 .NET MVC 框架的依赖。例如,我们避免使用 .NET MVCs 验证助手,而是依靠我们自己的。这是使我们能够轻松使用任何 .NET 技术中的业务逻辑的另一个因素。

Logically designing our middle tier this way has allowed us to easily achieve this physical architecture:

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

enter image description here

在此处输入图片说明

It was written with Peasy.NET, and has served us well over the years. So well in fact that we decided to open source it.

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

If anyone is curious as to what our middle tier looks like, here is a sampleof a client agnostic, business layer. It also showcases the consumption of it by multiple .NET clients (ASP.NET MVC, Web Api, and WPF).

如果有人对我们的中间层是什么样子感到好奇,这里有一个客户端不可知的业务层示例。它还展示了多个 .NET 客户端(ASP.NET MVC、Web Api 和 WPF)对它的使用。

Hope this helps someone!

希望这可以帮助某人!

回答by Ryozzo

As ahanusa wrote, you should put your business logics into separate DLL or separate directory.
I often use a directory named Logics at same level of Models and Controllers where I put classes which do business logics.
In this way I let both models and controllers clean.

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