【问题标题】:Catching a Specific WCF FaultException捕获特定的 WCF FaultException
【发布时间】:2013-04-09 08:53:30
【问题描述】:

单层应用程序可以通过以下方式区分异常:

Exception ex;

if (ex is System.DirectoryServices.AccountManagement.PasswordException)
    ...

其中 ex 只是一般的例外。

当你迁移到 WCF 进行多层时,你失去了这一切,你需要使用 FaultException 机制。

问题是我找不到任何方法来完成上述操作。

在我的客户端中,我想捕获 FaultException 类型,然后区分它们,例如:

catch (FaultException ex)
{
    if FaultException is (PasswordExceptionFault)
      ...
    etc
}

有没有办法做到这一点?

否则我必须有许多 catch 构造 - 每种类型的 FaultException 一个。

【问题讨论】:

    标签: c# wcf exception faultexception


    【解决方案1】:

    在使用 WCF 服务时,您必须使用 FaulException,因为它是处理错误的原生 Soap 方法(Exception 也是不可序列化的)。

    在典型场景中,您将首先在每个操作合约上添加类型化的 FaultContract。

    // NOTE: This is the std wcf template
    [ServiceContract]
    public interface IService1
    {
        [FaultContract(typeof(int))]
        [FaultContract(typeof(string))]
        [FaultContract(typeof(DateTime))]
        [OperationContract]
        string GetData(int value);
    }
    

    您的服务将为您决定客户端需要故障信息的所有故障情况发送键入的故障异常。

    您的客户端可以捕获表示操作合同中指定的自定义 SOAP 错误的 FaultException 类型。

     ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client();
    
        try
        {
            Console.WriteLine("Returned: {0}", proxy.GetData(-5));
        }
        catch (FaultException<int> faultOfInt)
        {
            //TODO
            proxy.Abort();
        }
        catch (FaultException<string> faultOfString)
        {
            //TODO
            proxy.Abort();
        }
        catch (FaultException<DateTime> faultOfDateTime)
        {
            //TODO
            proxy.Abort();
        }
        catch (FaultException faultEx)
        {
            Console.WriteLine("An unknown exception was received. "
              + faultEx.Message
              + faultEx.StackTrace
            );
            proxy.Abort();
        }
        catch (Exception e)
        {
            //generic method
            Type exceptionType = e.GetType();
            if (exceptionType.IsGenericType && exceptionType.GetGenericTypeDefinition() == typeof(FaultException<>))
            {
                PropertyInfo prop = exceptionType.GetProperty("Detail");
                object propValue = prop.GetValue(e, null);
                Console.WriteLine("Detail: {0}", propValue);
            }
            else
            {
                Console.WriteLine("{0}: {1}", exceptionType, e.Message);
            }
        }
    

    最后,由于FaultException继承了Exception,你仍然可以使用反射来获取内部故障类型和详细信息,如下所示。

    另请注意,WCF 客户端上的通信方法的常见预期异常包括 TimeoutException、CommunicationException 和 CommunicationException 的任何派生类(如 FaultException)。这些表示通信过程中出现的问题,可以通过中止 WCF 客户端并报告通信故障来安全地处理。

    【讨论】:

    • 异常肯定是序列化的,这是this overloaded constructor 的全部要点。但是,并非所有异常都能正确实现它(盯着 DirectoryServicesCOMException)。
    【解决方案2】:

    只需使用类似的东西:

    if (error is FaultException<ServerTooBusyException>) 
    {
        // Do something
    }
    

    【讨论】:

    • 那些非常奇怪的尖括号是什么,它们到底应该如何在 C# 代码中工作?
    • 修正了他的括号,但这正是公认的答案已经说的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多