在WCF服务中处理异常的最佳方法是什么?

时间:2009-10-08 07:11:01

标签: wcf

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

WCF服务连接到SQL Server 2005以读取和写入数据。 这是一个Intranet场景,客户端应位于同一域中。

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

  1. 网址无效
  2. WCF服务已关闭
  3. SQL server 2005未​​运行
  4. 客户不在同一个域
  5. 身份验证失败
  6. 授权失败
  7. 以及许多其他例外情况。

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

    请建议最好的设计方法来处理这个问题。

4 个答案:

答案 0 :(得分:33)

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

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

更好的方法是在服务类上实现IErrorHandler接口,该接口提供了一种全局捕获所有异常的方法,并提供了一个FaultException,而且符合SOAP。

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

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

答案 1 :(得分:6)

  1. 创建标有DataContract属性
  2. 的自定义错误类
  3. 使用FaultContract在服务合约界面上标记方法。 IE浏览器。 [FaultContract(typeof(CustomFault))]
  4. 在您的服务方法中,捕获任何适用的内部例外并抛出FaultException<CustomFault>。或者,如marc_s所述,您可以使用IErrorHandler将异常映射到故障。
  5. 就个人而言,我创建了一个具有Reason属性的基类Fault类,并且我从此类扩展了所有自定义错误。当我想抛出错误时,我打电话给:

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

    值得注意的是,我将我的故障类(包括常见的故障类)与我的所有其他服务一起版本化。但是,如果服务版本控制是一个问题,这只是一个问题。

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

    [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);
        }
    }
    

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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;
}