【问题标题】:What is the best approach to handle exceptions in WCF service?在 WCF 服务中处理异常的最佳方法是什么?
【发布时间】:2010-12-04 21:34:12
【问题描述】:

我在两台或多台远程计算机上部署了 WCF 服务,并且客户端使用一个基于桌面的应用程序来访问任何 wcf 服务。

WCF 服务连接到 SQL server 2005 以读取和写入数据。 这是一个客户端应该在同一个域中的 Intranet 场景。

现在可能会出现 wcf 服务抛出异常的情况:

  1. 网址无效
  2. WCF 服务已关闭
  3. SQL Server 2005 未运行
  4. 客户端不在同一个域中
  5. 身份验证失败
  6. 授权失败

还有许多其他例外。

对于每个异常,我必须执行一些操作或更新状态栏,具体取决于异常。例如,如果授权失败,我必须提示用户重新输入他们的凭据。

请提出处理此问题的最佳设计方法。

【问题讨论】:

    标签: wcf


    【解决方案1】:

    您绝对可以捕获和处理服务类上发生的所有异常,并将它们转换为 FaultException 或 FaultException 异常。

    这样,您就不会“破坏”(或破坏)客户端和服务器之间的通信通道。

    更好的方法是在您的服务类上实现 IErrorHandler 接口,该接口提供了一种在发生异常时全局捕获所有异常并提供 FaultException 的方法,这符合 SOAP 标准。

    您甚至可以将您的IErrorHandler 转换为可在配置中打开或关闭的可配置行为。

    有关更多详细信息,请参阅这些文章和博客文章:

    【讨论】:

    • 我对 IErrorHandler 了解不多,但我阅读了有关使用 IErrorHandler 的文章和帖子,它说它有一些缺点。在某些情况下,异常可能会直接从 wcf 服务抛出到客户端。你会推荐我使用 IErrorHandler 吗??
    • 是的,无论如何 - 我会总是推荐使用 IErrorHandler。你能发布这些文章的链接,说它有缺点吗?从来没有听说过 - 我想调查一下......
    • stackoverflow.com/questions/265551/wcf-errorhandler 阅读第二篇文章!!我不知道它是否正确,但它总是在我脑海中造成混乱
    • 好吧,我猜他期望太高了 - IErrorHandler 将捕获服务器上发生的所有异常 - 服务器上不会发生通信错误或安全设置不匹配 - 但在消息之前甚至到达服务器。这是一个不同的场景。
    • 我可以直接向您指出 Rory Primrose 的帖子。这是一个完整的工作示例。
    【解决方案2】:
    1. 创建一个用DataContract 属性标记的自定义故障类
    2. 用FaultContract 标记服务合同接口上的方法。 IE。 [FaultContract(typeof(CustomFault))]
    3. 在您的服务方法中,捕获任何适用的内部异常并抛出FaultException<CustomFault>。或者,正如 marc_s 所述,您可以使用 IErrorHandler 将异常映射到故障。

    就个人而言,我创建了一个具有 Reason 属性的基本 Fault 类,并从该类扩展了所有自定义错误。当我想抛出错误时,我调用:

    throw Fault.Create<CustomFault>(new CustomFault("Boo hoo"));
    

    还值得注意的是,我对我的故障类(包括常见的故障类)以及我的所有其他服务进行了版本控制。不过,这只是一个问题,如果服务版本是一个问题。

    这是基本的故障类(为简洁起见,我删除了参数验证):

    [DataContract(Namespace = XmlVersionNamespace.FaultNamespace)]
    public abstract class Fault
    {
        internal FaultReason Reason { get; set; }
    
        protected Fault(string reasonText)
        {
            Reason = new FaultReason(new FaultReasonText(reasonText, CultureInfo.CurrentUICulture));
        }
    
        public override string ToString()
        {
            return Reason.ToString();
        }
    
        internal static FaultException<TDetail> Create<TDetail>(TDetail fault) where TDetail : Fault
        {
            return new FaultException<TDetail>(fault, fault.Reason);
        }
    }
    

    【讨论】:

    • 谢谢理查德!如果假设身份验证失败,请给我一个例子。只需给我类关系船舶以及您将如何处理客户端应用程序..
    • 我会创建一个AuthenticationFailedFault(从Fault扩展它),将一条消息传递给基本的Fault构造函数。在您的客户端应用程序中,您只需捕获 FaultException,因为 AuthenticationFailedFault 将成为 WSDL 的一部分(只要您使用 [FaultContract] 标记方法)
    【解决方案3】:

    您可以为您的 WCF 服务中的每个异常场景设计特定的故障数据协定,以便您可以分别处理客户端的故障/异常。

    【讨论】:

    • 我是新手,可以给我一些链接
    【解决方案4】:
    try
    {
      // Actions
    }
    catch (Exception ex)
    {
      // Log the exception
      // Throw Fault Exception back to client
      FaultException fe = new FaultException(ex.Message, new FaultCode("Your fault code"));
      //throw fault exception back to WCF client
      throw fe;
    }           
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-29
      • 1970-01-01
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-26
      • 1970-01-01
      相关资源
      最近更新 更多