【问题标题】:Should web services throw exceptions OR result objectsWeb 服务是否应该抛出异常或结果对象
【发布时间】:2009-06-19 17:35:57
【问题描述】:

我不确定我是否完全满意在 Web 服务中抛出异常是一个好主意。如果不是堆栈跟踪,我不会那么介意。这不是我不想要的。

我研究了几种实现,但似乎并没有就此达成共识。例如,CampaignMonitor 确实返回了一个 Result 对象,而其他的则没有。

从架构上讲,我不确定返回返回对象是否有意义,当然异常就是异常,但我喜欢返回对象的地方在于它对最终用户来说是一种更优雅的解决方案。

有人有更好的解决方案吗?

编辑

顺便说一句,我正在使用 ASMX Web 服务,在该服务中打开 CustomErrors 不是一个选项。

【问题讨论】:

  • 其实,我相信删除异常细节的方法是使用 web.config 中的 customErrors 标签。信不信由你。
  • @John:是的,这就是我要说的。不幸的是,这不是我的选择。否则对我来说这将是一个更简单的问题:(。

标签: web-services soap exception-handling asmx


【解决方案1】:

不要让您在 Web 服务中的事实混淆了这个问题。这只是一个实现细节。

使用正常的异常处理策略。最佳实践是不要在低级代码中捕获异常——除非您可以在那里解决该异常并正常继续。应向表示层提出异常,以便将错误通知用户。

因此,应用于 Web 服务 - 通常会引发异常(这会导致 SoapFault)。这允许调用客户端代码使用其内置的异常处理标准来处理它。

【讨论】:

  • @Maladon:这是一个很好的答案,除了层边界。通常,策略会在层边界上发生变化,尤其是在服务层。特别是,对于 WCF,层边界将是捕获异常“A”并将其替换为 FaultException 的好地方,这将发送 SOAP 故障 AFault。没有堆栈跟踪,顺便说一句。 ASMX 不能正确支持故障;停止使用它的另一个原因。
【解决方案2】:

你在说什么堆栈跟踪?你试过吗?

在 ASMX 和 WCF 服务中,未捕获的异常将被转换为 SOAP 错误。在这两种情况下,它们都可以配置为不包含任何堆栈跟踪。事实上,这是 WCF 中的默认设置。

因此,返回此类错误的正确方法是通过故障。产生错误的一种方法是抛出异常而不处理异常。

【讨论】:

  • 本质上,我想通知用户的只是一个带有错误代码和描述(我选择的)的异常。我觉得 Web 服务和应用程序架构的异常处理之间存在语义不同,但我不确定是否应该区别对待它们。当出现错误时,您不会在代码中返回 Result 对象。 Web 服务是否应该有所不同。不(正如你暗示的那样)。我想我的问题是如何抽象异常细节?
  • 阅读 SOAP 错误。这是向客户端返回任意细节的标准方式。在 ASMX Web 服务中,您必须在 SoapException 实例的 Detail 属性中“手动”返回它们,但如果您必须使用 ASMX,这是正确的方法。当然更好的方法是使用WCF。此外,不要将其视为通知用户有关异常的信息。异常是一个实现细节。你是在通知他们一个错误。
  • 这不是我观察到的。我的 ASMX Web 服务都在默认设置下返回堆栈跟踪,这让我抓狂。当有一个服务链互相调用,并且链中的最后一个抛出时,客户端会从所有参与的服务接收到大量的堆栈跟踪(以SoapException 的形式,其中的Message 属性包含堆栈跟踪作为连接文本)。这太可怕了,我不知道如何关闭它。
  • @GSerg:您可以通过以下两种方式之一将其关闭:1. 切换到 WCF,您可以在其中控制详细信息是否在消息中,以及 2. 修复您的代码以不被破坏.
  • @JohnSaunders 出于兼容性原因,我不会切换到 WCF,并且代码没有损坏,我愿意在检测到错误参数时抛出异常,提供有用的 Message。我知道我可以使用Success = false 返回一个虚拟回复对象,但这很愚蠢,正如您在回答中所说,正确的方法是抛出异常。我仍然无法相信关闭堆栈跟踪是不可能的——在这种情况下,所有公开暴露的 ASMX 服务的所有客户端都可以不时地查看其源代码结构?
【解决方案3】:

一种方法是将系统错误和业务错误分开。 (系统错误:例如格式错误的请求、用户未授权等;业务错误:例如方法 UpdateCars 导致错误,用户没有任何汽车)。

如果发生业务错误,返回一个包含错误描述的响应对象;如果出现系统错误,抛出异常。

【讨论】:

  • SOAP 规范提供了返回错误条件的错误,应该使用它们。否则,您的客户将不得不重新检查错误返回值,并且无法使用其平台特定的错误翻译。
【解决方案4】:

你能澄清一下吗? Web 服务的服务器端可以抛出异常。 Web 服务的服务器端可以向客户端返回消息。该消息可能包含错误信息,并且该错误信息可能具体包括异常详细信息。或者它可能不会。在客户端,您通常有一个生成的代理来处理来自服务器的消息。如果该响应包含错误信息,此代理可能会生成异常。

你想知道这个场景的哪一部分?

【讨论】:

  • @Bruce:未捕获的异常将被转换为错误。在某些情况下,这些将包括异常细节。
  • @Bruce:我了解 Web 服务的工作原理,我的意思更多的是架构设计。在某些情况下,我确实需要抛出异常。在这些情况下,堆栈跟踪信息被序列化到客户端。我不认为这是一个好主意。隐藏细节的最佳方法是什么?或者是返回“返回”对象的答案(我给出的示例是 CampaignMonitors api 示例)。
  • @Ryan:处理 web.config 中 customeError 标记的所有组合。我相信其中一个会关闭堆栈跟踪。
  • @John:请参阅对原始问题的评论。不幸的是,这不是我的选择。
【解决方案5】:

我认为抛出异常通常是一种比返回结果更好的设计模式。 我想你必须做的是在你的 web 服务中通过将以下模式应用于作为 web 服务公开的每个方法来隐藏堆栈跟踪:

public void MyWebServiceMethod() {
试试
{

 ///Do something that may cause an error

} 捕获(异常前)
{ throw new ApplicationException("用户友好 异常描述");

}

}

或者你也可以

catch(异常前){ 扔前; }

如果您重新抛出异常,您将对 Web 服务的客户端隐藏原始堆栈跟踪。

【讨论】:

  • @Bogdan:首先,MS 在 .NET 1.1 中已经弃用了 ApplicationException。请改用“例外”。其次,我的印象是 OP 根本不需要堆栈跟踪。
  • @John,ApplicationException 我指的是任何自定义异常。好的,可以说它应该是 MyWebServiceException 或类似的东西。此外,实际上它并没有被弃用,像 System.Threading.WaitHandleCannotBeOpenedException 这样的异常仍然继承自它。 MS 只告诉他们不认为它很有价值,但您使用什么作为异常的基类自然是您自己的选择,这有时也取决于您在当前项目中应该遵守的编码约定。
【解决方案6】:

我不明白为什么你不能两者都做?捕获异常,将其记录(记录到数据库或文件),然后返回错误代码。这样,您就可以优雅地执行 web 服务调用,并通知错误,并且您可以在其他地方进一步调试。

【讨论】:

  • @James:坚持标准可能会更好。它提供了故障,那么为什么不使用它们呢?此外,开发人员忘记检查错误代码。这就是发明异常的原因,而 SOAP 故障是异常的 Web 服务版本。
  • 正如@John 所说,我同意,有异常可以通知故障。异常将被序列化为 SOAP 错误。结果返回错误代码不太适合协议。见下文:msdn.microsoft.com/en-us/library/ds492xtk(VS.85).aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多