目前在我的应用程序中,使用工作单元模式和通用存储库,我所有的控制器都包含所有的业务逻辑。我正在把一切都放在使用ViewModels而不是直接的模型的过程中。
虽然这是一个好主意,但现在出现了一个问题,它可以显著地分离控制器中的业务逻辑。对于控制器和视图模型,哪一个应该包含大部分的业务逻辑?
我已经尝试了几种方法来让我的ViewModels实际上包含所有的业务逻辑。然而,我必须在我的ViewModel的构造函数中有一个参数,它接受一个工作单元。这是个好主意吗?
我的代码气味告诉我它是。然而,我只是有点担心这将如何与执行不需要viewmodel的操作的控制器保持一致。简单地说,不需要将Model/ViewModel传递给View的操作;这种情况发生在重定向到其他操作的操作上。这意味着,我的业务逻辑可以留在该操作中,也可以将该业务逻辑分离到一个功能中。
这里的最佳实践是什么?
我不能说我的方法是最佳实践,但我更喜欢将任何业务逻辑放在单独的"服务"层中。
我倾向于使用ViewModel只存储特定视图所需的属性。如果ViewModel上有任何方法,它们很可能只是检索与该视图相关的集合。
我保持我的控制器轻量级,试图限制他们验证和重定向/显示视图尽可能多。
如果我有任何复杂的逻辑,我将有一个控制器动作调用到一个单独的服务来处理那个逻辑。通过这种方式,逻辑是隔离的,这使得测试更容易,因为不再需要创建控制器或ViewModel来测试它。与拆分ViewModel相比,重用服务也更容易。
希望这有帮助。好运。
对于控制器和视图模型,应该包含大部分的业务逻辑?
都没有
这是个很糟糕的主意。首先,你打破了一些坚实的原则。将所有代码捆绑到视图模型中会使测试变得困难。如果您想在另一个视图中使用某些业务逻辑,该怎么办?你复制了那个代码吗?我已经尝试了几种方法来让我的ViewModels实际上包含所有的业务逻辑。然而,我必须在我的ViewModel的构造函数中有一个参数,它接受一个工作单元。这是个好主意吗?
这里的最佳实践是什么?
让我们先回到MVC模式。这是一个相当广泛的定义,但知道它应该给你一个感觉,你应该把什么放在哪里。
MVC中的"模型"实际上是用来将数据拉到一起的一切。它可以是web服务、业务层、存储库等。
视图是生成HTML的所有代码(因为我们谈论的是web)。
控制器应该被认为是模型和视图之间的粘合剂。因此,它应该从模型中获取信息,并将其转换为视图可用的信息。
该结构的问题是,它很容易将特定于层的信息"泄漏"到模式的其他部分。因此,微软在MVC实现中引入了ViewModels。
通过这种方式,我们可以从视图中删除所有呈现逻辑并将其放入ViewModel中。而不是在视图中这样做:
<span>@(model.Age == 0 ? "n/a" : model.Age)</span>
将该代码放在ViewModel中,并简单地调用@model.Age
。通过这种方式,您不必在使用视图模型的所有视图中复制该代码。
关于ViewModel的问题的答案是,它应该只包含用于正确呈现来自"模型"的信息的逻辑。
至于控制器,我也不会在其中放入任何业务逻辑。首先,它让你很难检验你的逻辑。然后你给它添加更多的责任(这样做会破坏SRP)。控制器中唯一有效的逻辑是从ViewModel中获取信息并将其转换为"Model"可用的信息,反之亦然。
希望这能回答你的问题。
我将创建一个单独的项目并向其中添加类。然后从你的webproject中添加一个引用,并在控制器中调用这些类。
我也会开始使用控制反转容器来自动为我创建那些依赖项。
Autofac既可以为你发现你的服务(零配置),也可以将自己注入MVC。
要遵循分隔的接口模式,创建以下项目:
- 志愿者项目。BusinessLayer <——在这里添加你的类
- YourProject.BusinessLayer。规范<——在这里添加定义业务层的接口。
- 志愿者项目。Mvc <——Mvc项目。
"规范"项目可以用来使测试变得更容易,并且使切换实现变得更容易(可能只有几个类,而不一定是整个业务层)。阅读"分离接口模式"
模型-视图-视图模型(MVVM)是一种用于构建用户界面的设计模式。视图模型是UI上数据和操作的纯代码表示。因此,它应该包含与该UI相关的逻辑。
例如:如果你正在实现一个列表编辑器,你的视图模型将是一个包含项目列表的对象,并公开添加和删除项目的方法。
从维基百科:ViewModel: ViewModel是"视图的模型",这意味着它是一个之间的数据绑定视图和模型。它可以被看作是什么的一个特殊方面将是一个控制器(在MVC模式),作为一个数据将模型信息转换为视图信息的绑定器/转换器并将来自视图的命令传递给模型。ViewModel公开公共属性、命令和抽象。ViewModel被比作数据的概念状态,而不是模型中数据的真实状态[7]
您的控制器调用UoW来获取构建视图模型所需的数据。您可以调用UoW的多个方法
,然后将所有需要的数据传递给视图模型构造函数。(将Uow传递给视图模型听起来真的很糟糕)
如果你需要一些复杂的"逻辑"在你的控制器调用大量的方法从UoW等,你应该考虑创建另一个存储库或业务逻辑层,做所有的艰苦的工作,你从你的控制器调用它,如
SomeClass something = Uow.BLGoodName.DoSomeFancyStuff(params ..)
ViewData.model = new ControllerActionViewModel(something);
Return View();