Catching a Specific WCF FaultException

牧云@^-^@ 提交于 2019-12-12 09:45:26

问题


A single tier application can distinguish exceptions by:

Exception ex;

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

where ex is just a generic exception.

When you move to WCF for multi-tier, you lose all this and you need to use the FaultException mechanism.

The problem is that I can't find any way to do the above.

In my client I want to catch the FaultException types and then distinguish between them i.e. something like:

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

Is there a way to do this?

Otherwise I have to have many catch constructs - one for each type of FaultException.


回答1:


When using WCF service, you have to use FaulException because it's the native Soap approach for handling errors (Exception is also not serializable).

In the typical scenario you will first to add typed FaultContract on each operation contract.

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

You service will send typed faultexception for all fault cases in which you decide the client requires fault information.

Your client can catch the FaultException type that represents the custom SOAP fault specified in the operation contract.

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

At the end, because FaultException inherits Exception, you can still use reflection to get inner fault type and detail as shown here.

Also note that common expected exceptions from communication methods on a WCF client include TimeoutException, CommunicationException, and any derived class of CommunicationException (like FaultException). These indicate a problem during communication that can be safely handled by aborting the WCF client and reporting a communication failure.




回答2:


Just use something like:

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


来源:https://stackoverflow.com/questions/16045726/catching-a-specific-wcf-faultexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!