2013-04-16 4 views
4

А применение одноуровневых может различать исключения по:Поймать Конкретная WCF FaultException

Exception ex; 

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

где ех просто родовое исключение.

Когда вы переходите к WCF для многоуровневого уровня, вы теряете все это, и вам нужно использовать механизм FaultException.

Проблема в том, что я не могу найти способ сделать это.

В моем клиенте я хочу, чтобы поймать типы FaultException, а затем различать между ними то есть что-то вроде:

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

Есть ли способ сделать это?

В противном случае у меня должно быть много конструкций catch - по одному для каждого типа исключения FaultException.

ответ

8

При использовании службы WCF вы должны использовать FaulException, потому что это родной подход Soap для обработки ошибок (исключение также не является сериализуемым).

В типичном сценарии вы должны сначала добавить набранный 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); 
} 

Служба высылает типизированные ошибки для всех случаев сбоев, в которых вы решаете, что клиент нуждается в информации о неисправности.

Ваш клиент может поймать тип FaultException, который представляет собой пользовательскую ошибку SOAP, указанную в контракте на операцию.

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 и сообщая об ошибке связи.

+0

Исключения, безусловно, сериализации, то вся суть [этого перегруженного конструктора] (http://msdn.microsoft.com/en-us/library/tz6bzkbf .aspx). Однако не все исключения реализуют его правильно (* блики в DirectoryServicesCOMException *). –

-2

Просто использовать что-то вроде:

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

Каковы эти очень странные угловые скобки и как они должны работать в коде C#? –

+0

Исправлены его скобки, но это именно то, о чем уже говорил принятый ответ. –

Смежные вопросы