视图是否应该执行验证?


10

我正在阅读“ 在MVC中模型应该处理验证吗? ”,因为我很好奇验证逻辑在MVC网站中的位置。最高答案中的一行如下:“控制器应处理验证,模型应处理验证”。

我很喜欢,但是让我感到奇怪的是,为什么由于以下几个原因我们不会在View中进行数据验证:

  1. 视图通常具有强大的验证支持(JS库,HTML5标签)
  2. 视图可以在本地验证,从而减少网络IO
  3. 用户界面已经考虑了数据类型(日期的日历,数字的微调框),使其距验证仅一步之遥

在多个地方进行验证与MVC隔离职责的概念背道而驰,因此“在两个地方都做”似乎不合适。仅在控制器中执行数据验证是真正的主导方法吗?


这里的问题可能是错误的二分法之一:没有理由不能在多个地方进行验证,并且将情况视为“要么要么都不是”可能会笼罩您对该问题的看法(双关!)。 。例如,在网站上进行某种形式的客户端验证可能非常有用,因为用户可以获得即时反馈,但是它也不值得信赖,因此它不是唯一的验证。
Miles Rout 2015年

Answers:


10

我认为没有一个地方可以说所有验证都可以进行。这是因为在标准的asp.net mvc网站中,我们有几种相互竞争的编程策略。

首先,我们的想法是将域逻辑分为模型,将“动作”逻辑分为控制器,将显示分为视图。这是基于以下想法:所有逻辑都将在服务器上进行,而浏览器仅提供视图的呈现即可。

然后,我们使用客户端javascript扩展视图。如今,这种方法是如此先进,以至于带有Jquery / knockout / angular的“一页网站”的想法很普遍。

这种做法可以等同于编写一个本身实现MVC或MVVM模式的整个客户端应用程序。我们将视图定义为数据传输对象,将控制器定义为服务端点。将所有业务和UI逻辑移至客户端。

这样可以提供更好的用户体验,但是您必须信任本质上不可信的客户端。因此,无论客户端对请求的预验证如何,您仍然需要在服务器上执行验证逻辑。

另外,我们经常有验证要求,客户无法执行。例如。“我的新ID是否唯一?”

您创建的旨在提供最佳体验/性能的任何应用程序都必定会借鉴多种编程范例,并对其进行折衷以实现其目标。


4
+1,并强调:永远不要信任客户发布的数据。曾经
马查多

我的理解是:“验证不是一个孤立的概念-您的应用程序的所有部分都需要在不同的上下文中相互验证。” 有道理,即使需要更多工作。
WannabeCoder

是的,但是:“您可能有两个(或更多)应用程序,都遵循不同的模式”
Ewan

den·i·grate:不公正地批评;鄙视。 ”我认为您没有正确使用该词。否则,好的答案。
kdbanman 2015年

不,那是我的意思
Ewan

1

在多个地方进行验证与MVC隔离职责的概念背道而驰,因此“在两个地方都做”似乎不合适。

在这里可以考虑多个验证职责吗?如您在#3中所说:

用户界面已经考虑了数据类型(日期的日历,数字的微调框),使其距验证仅一步之遥

所以也许是:

视图:验证输入类型,格式,需求...与业务逻辑无关的基本用户输入验证。在我们通过请求服务器生成网络流量之前,请捕获所有这些蓬松的内容。

模型:验证数据的业务关注点。根据业务规则,这是否具有法律价值?是的,它是一个数值(我们在视图中确保了这一点),但这有意义吗?

只是一个想法。


1

我将假设您需要对持久性进行验证。

不仅View,而且Model也不应处理验证。在从事IT的那几天,我意识到DDD是确保您实际上在正确执行操作的一种方法,即。类实际上负责它们应该是什么。

在遵循域驱动设计时,您的模型包括您的业务逻辑,就是这样。但是它们不包括验证,为什么不呢?

假设您已经在使用远距离Data Mapper而不是Active Record持久化域层。但是,您仍然希望对模型进行验证,因此可以将验证添加到模型中。

interface Validation
{
    public function validate();
}

class ConcreteModel extends MyModel implements Validation
{
    public function validate() { // the validation logic goes here }
}

验证逻辑可确保您可以将模型正确地插入MySQL数据库中……几个月后,您决定将模型也存储在noSQL数据库中,这些数据库需要与MySQL不同的验证规则。

但是您有一个问题,您只有一种验证方法,但是需要以Model两种不同的方式进行验证。

模型应该做他们应该做的事情,应该照顾好您的业务逻辑并做好。验证与持久性相关,而不与业务逻辑相关,因此验证不属于模型

您应该Validator改为创建,它将使用模型在其构造函数中进行验证作为参数,实现Validation接口并使用这些Validator来验证对象。

interface Validation
{
    public function validate();
}

class MySQLConcreteModelValidator implements Validation
{
    public function __construct(ConcreteModel $model) { }

    public function validate()
    {
        // you validate your model here
    }
}

class RedisConcreteModelValidator implements Validation
{
    public function __construct(ConcreteModel $model) { }

    public function validate()
    {
        // you validate your model with different set of rules here
    }
}

如果将来在任何时候决定要为另一个持久层添加另一种验证方法(因为您确定Redis和MySQL不再可行),您将创建另一个Validator并使用您的IoC容器基于正确的实例在你的config


1

对于许多开发人员而言,首选针对傻瓜丑陋控制器的Fat模型

文本中的基本概念是

...因此,请始终记住,模型不仅仅是数据库。甚至从Web服务获取的数据也可以表示为模型!是的,即使是Atom饲料!扰乱模型介绍的框架几乎从来没有解释过这一前期内容,这只会加剧误解。

视图仅应与生成和呈现UI有关,以便用户可以将意图传达给模型。控制器是协调器,负责将UI输入转换为对模型的操作,并从使View知道模型呈现的任何视图传回输出。控制器必须仅在将用户输入映射到模型中的调用的意义上定义应用程序行为,但是在该角色之外,应该清楚所有其他应用程序逻辑都包含在模型中。控制器是具有最低代码的卑鄙生物,它们只是搭建舞台并让事物以组织的方式工作。

视图仅应与生成和呈现UI有关,因此用户可以将意图传达给模型是重要的部分。模型应该定义存储的数据,因此它还必须负责检查数据的有效性。

记录个人时,每个人都必须具有国家/地区提供的唯一ID号。该检查(通常)是UNIQUE通过数据库的密钥检查来完成的。每个给定的ID号都应满足某些控制步骤(奇数之和应等于偶数之和,等等)。此类控制应由Model

控制器正在从中收集数据Model并将其传递给View,或反过来从中收集用户数据View并将其传递给Model。访问数据和验证数据的任何限制都不应由Controller。是Controller谁收集cookie数据,然后是Model谁检查它是有效的会话还是用户有权访问应用程序的这一部分。

View是从用户收集数据或向用户显示数据的用户界面。可以通过View诸如是否输入用户电子邮件地址之类的方式来进行简单检查(因此也可以在“视图”中执行)IMO。

View是客户端,您不应强调用户输入。Javascript可能无法在客户端上运行,用户可以使用手写脚本来更改它们或使用浏览器禁用该脚本。您可以设置客户端验证脚本,但绝对不要强加它们并在层上进行实际检查Model


只是强调一下,仅与UI有关的视图并不意味着它不能进行某种形式的验证-当用户犯错时向用户提供即时反馈实际上是客户端脚本为何如此重要的重要部分在将MVC应用于网站的情况下很有用。
Miles Rout 2015年

@MilesRout实际上,我的意思Simple checks can be done by the View like the user input e-mail address or not 是说不清楚。但是您说的对我也适用,可以在视图中轻松完成简单检查。
FallenAngel 2015年

我不是不同意你。
Miles Rout 2015年

0

视图应出于以下目的执行验证:

  1. )前端验证可以减少服务器中的数据流量。
  2. ),它将处理无效数据,然后才能在您的服务器中传输。
  3. ),如果您想要更高的安全性,则将前端和后端验证结合使用会更好。
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.