ASP.NET MVC是否真正遵循MVC模式?或者如何将模型与控制器分离?

5
这个问题有点反问。我在某些时候感觉ASP.NET MVC不是MVC模式的正统实现,或者我没有理解它。
考虑以下领域:电灯泡、开关和运动检测器。它们连接在一起,当您进入房间时,运动检测器会打开电灯泡。如果想将它们表示为MVC:
- 开关是模型,因为它保存状态并包含逻辑。 - 灯泡是视图,因为它向人类呈现模型的状态。 - 运动检测器是控制器,因为它将用户操作转换为通用模型命令。
开关有一个私有字段(On/Off)作为状态,两个方法(PressOn,PressOff)。如果在关闭状态下调用PressOn,则会变为开启状态;如果再次调用,状态不会改变。
灯泡可以用蜂鸣器替换,运动检测器可以用定时器或按钮替换,但是模型仍然表示相同的逻辑。最终,系统行为相同。
这就是我理解的经典MVC分解方式,如果我错了,请纠正我。
现在让我们按照ASP.Net MVC的方式进行分解。
- 灯泡仍然是视图。 - 控制器将是开关+运动检测器。 - 模型是一些对象,只需将状态传递给灯泡。
因此,定义行为的逻辑移动到了控制器中。
问题1:我对MVC和ASP.NET MVC的理解是否正确? 问题2:如果是,请问您是否同意其不是100%准确的实现?
最后一个问题是如何在ASP.NET MVC中将模型与控制器分离。有两个极端。控制器只做基本工作,并调用模型来执行所有逻辑。另一种是控制器处理所有逻辑,而模型只是类似于映射到数据库的属性的东西。
问题3:我应该在这些极端之间划分界限?如何平衡呢?
谢谢, Andrey

一个控制器将 HTTP 请求转换为模型上的命令,因此控制器不等于开关 + 运动检测器。你的控制器动作只需要调用 switch.Toggle()。开关仍将保持状态。 - Ryan
@Ryan 是的,我对MVC的理解就是这样。在ASP.NET MVC中,控制器并不会直接翻译HTTP请求,而是由引擎代为处理,并将其转换为方法调用,从而使控制器与HTTP请求分离。 - Andrey
3个回答

2

我认为可以两种方式都行。下面是一个在ASP.NET MVC中实现的解决方案,它保持了你在第一个示例中的逻辑。

模型(存储库)

Function switchOn() as bulb
    if !bulb.lightOn then
        bulb.lightOn = true
    end if
        return bulb
End Function

Function switchOff() as bulb
    if bulb.lightOn then
        bulb.lightOn = false
    end if
        return bulb
End Function

Function Motion(senseMotion as boolean) as bulb
    if(senseMotion and !bulb.lightOn) then
         bulb.lightOn = true
    end if
    return bulb
End Function

控制器

Function PressSwitchOn() as actionresult
     return view("Bulb", lightRepository.switchOn)
End Function

Function PressSwitchOff() as actionresult
     return view("Bulb", lightRepository.switchOff)
End Function

Function SomethingMoved(byval hasMoved as boolean) as actionresult
     return view("Bulb", lightRepository.Motion(hasMoved))
End Function

我的控制器中没有业务逻辑,它只是将状态从模型传递到视图。我的理解和你的例子差不多吗?
回答问题:
1. 是的,我认为你理解得很好。 2. 不,我不同意。ASP.NET MVC 的一个好处就是非常灵活,你可以把所有逻辑都放在视图中(为什么要这样做呢),但你有这个选择。 3. 我认为要划清界限,要牢记 DRY 原则。如果你有多次重复的逻辑,请确保它是模型或某个自定义业务类的一部分,以便从一个地方引用。对我来说,这是设计 MVC 应用程序的主要驱动原则之一。

虽然这对讨论并不重要,但是你在代码库中的if语句有些冗余。将状态设置为“true”会产生相同的结果,无论之前的状态是“true”还是“false” ;) - Tomas Aschan
@Tomas:我不喜欢上一条评论的表达方式... :/ 所以,是的,你是对的,绝对不会像那样编写生产代码(耶!重构),但是我试图展示模型中的所有逻辑而不是控制器中的逻辑。很难想出灯泡逻辑函数 :) - Tommy
但是控制器只是调用分发器。这将把MVC转换为MV。 - Andrey
@Andrey - 这与我的第二点相符,你有灵活性以任何你想要的方式进行。就像下面 @Tomas 所说的,按照你感觉相关的方式编写你的应用程序。 - Tommy

1
在你的例子中,运动检测器仍然需要调用SwitchOn和SwitchOff方法,这与控制器在存储库上调用相同的方法基本相同。因此,如果考虑实现存储库模式的ASP.NET MVC应用程序,则你的论点不成立。
结论:
  1. 是的,在原则上你是正确的,但你对MVC框架的使用方式过于局限。
  2. 不,我不同意你的观点。
  3. 这重要吗?MVC是一种旨在使开发更加容易而不是更难的模式。以感觉相关的方式编写应用程序,并在认为自己正在打破规则时称其为“MVC启示”(但谁会关心呢...?)。

但是MVC模式并不是一把万能的工具,因此它并不适用于所有需求。3是的,这很重要,因为我想最大化使用MVC带来的好处。如果我只是随意跟从灵感而行,那么使用MVC就没有任何好处。 - Andrey

0
在MVC框架中,请求总是首先到达控制器;然后才使用视图创建和呈现模型。
在您的情况下,请求发送到开关(正如您所说的那样是模型),因此您无法按照上述方式分解开关-灯泡-运动场景。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接