故障或不故障

L-F*_*our 10 architecture wcf faults exception

我正在与同事讨论何时抛出错误以及何时不在WCF服务中抛出错误.

有一种观点认为,当服务操作由于某些错误而无法完成工作时,我们只会抛出错误; 由于它,某些东西可能处于无效状态.所以,举一些例子:

  • ValidateMember(字符串名称,字符串密码,字符串国家/地区) - >如果未传递强制参数,则会引发错误,因为验证本身无法执行; - >如果发生了一些内部错误就会抛出错误,比如数据库已关闭 - >会在所有其他情况下返回状态合同,指定验证结果(MemberValidated,WrongPassword,MemberNotKnown,...)

  • GetMember(int memberId) - >只会在出现故障时抛出错误,在所有其他情况下它会返回成员,如果没有找到则返回null

另一种意见是我们也应该在GetMember找不到该成员时抛出错误,或者在ValidateMember的情况下密码错误.

你怎么看?

Chr*_*ter 12

我对此的看法......

失败有三个原因:

  1. 服务代码引发了异常,例如数据库错误,代码中的逻辑错误.这是你的错.
  2. 客户端代码未能根据您的文档正确使用您的服务,例如,它未设置必需的标志值,但未能传入ID.这是客户端软件开发人员的错.
  3. 最终用户在屏幕上键入了一些愚蠢的内容,例如缺少出生日期,负薪水.这是最终用户的错.

由您决定如何将实际故障合同映射到每个故障原因.例如,我们这样做:

  • 对于原因1和2,所有客户端代码需要知道的是服务失败.我们定义了一个非常简单的"致命错误"错误合同,它只包含一个唯一的错误ID.错误的完整详细信息记录在服务器上.
  • 对于原因3,最终用户需要确切地知道他/她做错了什么.我们定义了一个"验证错误"错误合同,其中包含一组友好的错误消息,供客户端代码显示在屏幕上.

我们为原因3 借用Microsoft EntLib类,并使用异常屏蔽以声明方式处理原因1和2.它使代码非常简单.

澄清:

我们在服务中处理这样的三个原因:

  1. 服务代码中引发意外异常.我们在顶层捕获它(实际上异常屏蔽捕获它,但原理是相同的).记录完整的详细信息,然后将a抛出FaultException<ServiceFault>到仅包含错误ID的客户端.
  2. 我们验证输入数据并故意抛出异常.它通常是一个ArgumentException,但任何合适的类型都可以.一旦被抛出,它的处理方式与(1)完全相同,因为我们希望它与客户端看起来相同.
  3. 我们验证输入数据并故意抛出异常.这一次,它是一个FaultException<ValidationFault>.我们配置异常屏蔽以通过un-wrapped传递这个,因此它在客户端上FaultException<ValidationFault>不显示FaultException<ServiceFault>.

最终结果:

  • 服务中没有任何捕获块(很干净的代码).
  • 客户端只有在FaultException<ValidationFault>想要向用户显示消息时才必须捕获.所有其他异常类型包括FaultException<ServiceFault>由客户端的全局错误处理程序处理为致命错误,因为服务中的致命错误通常也意味着客户端中的致命错误.