处理WCF服务错误的最佳实践是什么?

5
我正在编写一种 WCF 服务。大多数异常都在 BL 实现中被捕获并在那里处理。我的每个 API 返回类型都是一个名为 "result" 的类,其中包含错误代码、错误消息和成功布尔值。
当异常被处理时,这个类会相应地更新,并最终发送回客户端。当然,有些异常是无法处理的。目前,我正在将服务层中的每个 BL 调用都包装在一个通用的 try-catch 中,以便可以捕获每个未处理的异常,并创建一个通用的“result”类,其中包含通用的失败消息、错误代码和 success=false。
这种方式处理异常是否好?或者应该让未处理的异常由服务抛出给客户端?假设客户端无法使用异常中的数据,因此不会从异常中包含的额外信息中受益。

只是一点小提示:在使用WCF REST服务时,抛出WebFaultException实际上被映射到了HttpStatusCode,与设置WebOperationContext.Current.OutgoingResponse.StatusCode相比非常有帮助。 - J. Tihon
那么,最终你选择了不同的方式吗? - Vaibhav
5个回答

7

请查看异常屏蔽。

这是一个过程,其中由服务引发的异常根据您在配置文件中指定的规则映射到故障合同。这样可以节省很多使用try/catch块的麻烦。

这里有一篇文章可以帮助你:

总的来说,故障将分为3类:

1) 客户端错误 - 客户端试图执行不允许的操作,因此需要了解情况。例如:未能设置必填字段。- 返回解释性的特定消息。

2) 不影响客户端的业务错误。被认为是正常操作的错误,例如:付款授权检查失败。要么完全隐藏,要么返回一些消息:"执行请求时出错:请稍后再试..."

3) 系统错误 - 意外 - 非正常操作:替换为通用消息:"系统错误:请联系支持"

但无论如何,在所有情况下,关键的一点是您要删除堆栈跟踪,特别是如果它是面向公众的服务。

使用屏蔽,您将拥有3个故障合同,涵盖上述情况,并在屏蔽配置中适当设置文本。

请注意,在开发过程中通常希望关闭屏蔽,因为这使得调试系统变得非常麻烦!


1

我和其他人的看法不同。我认为HTTP方法GET、POST、PUT、DELETE支持CRUD操作,而HTTP响应代码200、500等则支持成功/失败,我认为这是适当的利用方式。500结果仍然具有HTTP响应体,而且这样的响应体是完全可读的(只要IIS没有输出HTML;您可以控制此项)。与此同时,像Microsoft WCF中的Microsoft SOAP一样的XML协议实现已经使用故障协议包装了异常。

如果你要抛出异常,就抛出它们。在这样做的同时,请记录它们,以便消费者可以相应地计划。


0

我认为这两种方法都是可行的。

个人而言,我更喜欢在WCF中不抛出异常,这样客户端就可以轻松区分服务器端处理错误和连接/协议问题:在第一种情况下,响应将指示失败,在第二种情况下将抛出异常。


0
个人而言,我不会暴露未处理的异常并将其传播到客户端。我会定义那些客户可能感兴趣的异常,并只传播那些异常。与客户想要执行的操作直接相关的异常(例如ArgumentException可以将原因设置为“CustomerId不能超过20个字符”等),我会在服务中处理,并且仅指示发生了某种内部服务器错误,这导致执行失败并意味着客户尝试运行的操作无法完成。我之所以这样做,是因为客户无法根据内部服务器错误采取任何措施。如果抛出ArgumentException,则可以通过重新验证参数并重试操作来修复其输入参数。
不确定这是否真正回答了您的问题,但希望至少能给您一些想法。

0

如果您让未处理的异常从WCF服务中出现,这可能会产生不良影响,例如通信通道处于故障状态,在会话场景中,客户端不能再使用相同的客户端代理实例,而是被迫创建一个新的实例并开始新的会话。总的来说,我认为有控制WCF服务中出现的错误并为客户端提供有用信息是很好的。请查看IErrorHandler。该接口使您可以控制生成的SOAP故障、未处理的异常,并允许您执行额外的任务,如日志记录,并让您决定在会话绑定的情况下是否要保留会话。您可以通过WCF可扩展性(如服务、终结点、契约、操作行为)添加自定义错误处理程序。

请注意,IErrorHandler在发送响应消息之前调用。因此,在序列化、编码等过程中,仍有可能发生未处理的异常。


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