关于c#:应该在每一层中进行哪些参数验证?

Which parameter validations should be done in each layer?

我之前曾在这个问题上问过类似的问题,并获得了很好的反馈,但是我仍然对如何进行有疑问。

这是场景...

App允许用户发布和删除他们对视频的评论。

当用户发布评论时,UI层将评论字符串和userId(guid)传递给用户,当删除时,会将commentId(int)和userId(guid)传递给BLL,然后BLL传递给DAL。

在UI层,我假设我需要进行完全验证,因此我确保同时使用客户端(如果适用)和服务器端验证进行以下操作:

  • userId实际上是一个向导
  • userId存在于用户数据库中(通过调用BLL方法)
  • userId是与commentId关联的对象(用于删除)(通过调用BLL方法)
  • 评论不为空
  • 评论不超过最大长度
  • commentId为> 0
  • commentId存在于数据库中(通过调用BLL方法)
  • videoId> 0
  • videoId存在于数据库中(通过调用BLL方法)

所有这些验证完成后,我将BLL方法称为

保存(字符串注释,int videoId,字符串userId)
或者
Delete(int commentId,字符串userId)

由于BLL也可以用作Web服务或用于其他页面/应用程序,因此我知道我也需要在BLL中进行验证。从我学到的知识来看,我认为我需要重做与UI层中相同的所有验证:

  • userId实际上是一个向导
  • userId存在于用户数据库中(通过调用BLL方法)
  • userId是与commentId关联的对象(用于删除)(通过调用BLL方法)
  • 评论不为空
  • 评论不超过最大长度
  • commentId为> 0
  • commentId存在于数据库中(通过调用BLL方法)
  • videoId> 0
  • videoId存在于数据库中(通过调用BLL方法)

这是正确的吗?除非必须,否则我讨厌进行额外的数据库调用!

现在,我需要调用关联的DAL调用来实际进行数据库更改。我需要在DAL中再次执行上述哪些验证?

该应用程序没有出售或出售任何东西,但我想了解处理验证的最佳方法,而又不会因我可能需要或可能不需要的额外数据库调用而影响性能。


我仅在UI层中对可能是无辜的用户错误的内容进行验证。这里的验证纯粹是出于可用性的考虑。在您的列表中,该值为

  • 评论不为空
  • 评论不超过最大长度

幸运的是,这些不需要数据库调用。

在后端,您需要验证列表中的所有内容。这是真正确保确保有效性,安全性,完整性等的唯一方法。

如果某项通过UI层验证但未通过后端验证,则发生非常非常错误的事情-恶意用户或代码中的错误。如果这是您代码中的错误,向用户显示验证消息对他们并没有真正的帮助。如果是恶意用户,则验证消息实际上是有害的,因为它们使坏人更容易确定您执行的验证检查并发现漏洞。当后端验证失败时,您的应用应仅向用户显示一般错误消息。


在我看来,您应该在每个级别上验证您有能力验证的每个项目。冷战时代"信任但要核实"的说法在这里适用。假设您有一个很好的分层方法,并且每个层都有可能在另一个项目的以后某个点被重用,那么假设将来的上层将验证原始层的使用方式是一个错误的假设。 >

显然,与业务逻辑相比,它具有添加更多验证的潜力,甚至可以重复验证,但可能更安全。

如果您希望保存数据库调用,那么我想说是在最低级别上进行的,但是只要确保您在较高级别上的错误处理能力足够强大,就可以处理各种冒泡的错误情况。


我知道这是一个相当简单的答案,但是由于每个层都代表一个边界,因此您不能信任该层之外的任何代码,因此,尽管您可以在UI中进行验证,但应该查看在业务层中运行的逻辑(域)作为唯一的实际验证逻辑。

请参阅Expert C#2008业务对象的第11页,业务逻辑。


我不建议您对每个黑客都有自己的数据库调用进行大量额外的检查。如何创建存储过程并将所有数据库检查放入其中。然后,您可以调用" Class.IsDatabaseValid(字符串,字符串,Id等)"。因此," IsDatabaseValid"方法将成为BLL有效性检查的一部分,并且您在sp。

上只有一个数据库调用。