2009-03-15 2 views
4

뭔가 잘못되면 일반적인 FaultException을 throw하는 WCF 서비스가 있습니다. 이유를 모르겠다. 때로는 클라이언트가 제네릭 예외 대신 일반이 아닌 FaultException을 잡을 수 있습니다.일반적인 FaultException을 던지고

아무도 모르는가, 문제는 무엇입니까?

답변

18

서비스에서 모든 예외를 처리하고 FaultException에 랩핑해야합니다. <T> 여기서 T는 작성한 데이터 계약입니다. 그래서 첫 번째 단계는 예외 정보를 포함하는 사용자 정의 데이터 계약을 정의하는 것입니다 :

[DataContract] 
public class CustomFault 
{ 
    public string Message { get; set; } 
} 

그런 다음 당신은 그것의 방법은 잠재적 오류 예외 <CustomFault>을 던질 수있는 서비스 계약을 지시합니다.

public class MyService : IMyServiceContract 
{ 
    public void MyMethod(string someArgument) 
    { 
     // Do something here that could throw exceptions but don't catch yet 
    } 
} 

당신이 구현할 수있는 예외를 처리하려면 다음

[ServiceContract] 
public interface IMyServiceContract 
{ 
    [FaultContract(typeof(CustomFault))] 
    void MyMethod(string someArgument); 
} 

다음 단계는이 인터페이스를 구현하는 것입니다 : 이것은 클라이언트가 프록시 클래스를 생성 할 수 있도록 WSDL에 CustomFault 클래스를 노출하는 서비스를 할 수 있습니다 IErrorHandler은 서비스 메소드 중 하나가 예외를 throw 할 때마다 사용됩니다. 이 오류 처리기의 목적은 오류 예외 <CustomFault>에 예외를 래핑하는 것입니다 :

클라이언트 측에서, 당신의 오류 처리기를 등록하면
public class MyErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) 
    { 
     return true; 
    } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message msg) 
    { 
     var customFault = new CustomFault() 
     { 
      Message = error.Message, 
     }; 
     var fe = new FaultException<CustomFault>(customFault); 
     MessageFault fault = fe.CreateMessageFault(); 
     string ns = "http://somenamespace/whatever"; 
     msg = Message.CreateMessage(version, fault, ns); 
    } 
} 

, 당신은 항상 오류 예외 <CustomFault>을 얻을 것이다.

+0

wierd는 동일한 예외이며, 때로는 제네릭이 아닌 FaultException으로 throw됩니다. – mrtaikandi

2

서비스가 캐치되지 않은 다른 예외를 throw하면 비표준 FaultException이 발생합니다. 예외가 무엇인지 알아 내서 버그 일 경우 수정하거나 클라이언트를 공개하려는 것으로 결정한 다음 일반 FaultException에 포장하고 FaultContract을 적절하게 추가해야합니다.

2

다른 가능성은 TDetail이 제대로 직렬화되지 않는 것입니다. 예를 들어, TDetail은 Exception에서 파생되며 직렬화 할 수없는 내부 예외가 있습니다.

5

클라이언트가 예외 유형 자체 (< T>가 FaultException < T>)에 액세스 할 수없는 경우 FaultException의 일반이 아닌 버전이 발생합니다. 나는 이것을 알아 내려고 애쓰는 데 몇 시간을 보냈고, 결국 msdn 포럼에서 this을 발견했을 때 깨달았다. 예외가 서비스 밖으로 던지기 전에 변경되었다는 표시가 있으면 좋겠지 만 그렇지 않습니다.

+0

나는 분명하지 않을 수도 있습니다. 나는 scope visibility와 관련하여 access라는 단어를 사용했다. 예를 들어 예외가 클라이언트 외부에서 정의되고 FaultContract 속성을 사용하는 서비스 호출에 표시되지 않으면 클라이언트가 Exception에 액세스 할 수 없기 때문에 다운 변환이 발생합니다. – Drew

1

FaultContractAttribute를 사용하여 오류 세부 정보 유형을 선언하지 않은 경우 발생합니다.

[ServiceContract] 
public interface IMyServiceContract 
{ 
    //... 
    [OperationContract] 
    [FaultContract(typeof(MyFaultDetail))] 
    [FaultContract(typeof(OtherFaultDetail))] 
    GetDetailsResp GetDetails(GetDetailsReq req); 
    //... 
} 
1

저도 같은 문제와 링크 드류가 나에게 답을 제공 게시 된보고 있었다 : 여기

은 서비스 계약이 보일 것입니다 방법이다.

해결 방법은 내 서비스 인터페이스가 내 서비스 오류와 다른 네임 스페이스를 사용한다는 것입니다.

[ServiceContract(Namespace = "http://dummydomain.com/service/searchservice")] 
    public interface ISearchService 
    .... 

와 서비스 오류가 있었다 :

즉, 서비스 계약했다

[DataContract(Namespace = "http://dummydomain.com/service/searchservicefault")] 
public class MySearchServiceFault 
... 

네임 스페이스 클라이언트가 그것으로 무엇을 해야할지하지 않는 다른 외관상 때갑니다 다시 비 일반 FaultContract ... 나는 위의 코드가 작동하고 일반적인 FaultContract를 반환하는 것으로 보아 클라이언트에 다소 의존한다고 생각합니다.

하지만 내가 네임 스페이스가 동일하게 변경되었습니다. 테스트에서 코드가 항상 작동하도록 만드는 것 같습니다.

관련 문제