3

그래서 WCF 서비스에서 엔터프라이즈 라이브러리를 사용하여 예외 관련 작업을 수행하려고합니다.맞춤 예외 처리기를 사용하여 FaultException을 throw EL WCF

내 생각은 "NullReferenceException"에 대해 "사용자 정의 예외 처리기"을 설정하고 "사용자 지정 예외 처리기"에서 FaultException 예외를 생성하는 것입니다.

제 생각에이 "새로운"예외는 전선을 가로 지르며 클라이언트에서이를 잡아낼 것입니다.

더 나은 이해를위한 몇 가지 코드 :

WCF 서비스 :

[ServiceContract(Name="MyService", ConfigurationName="MyNamespace.MyService")] 
    [ExceptionShielding("PolicyName")] 
    public interface IMyService 
    { 
     [OperationContract] 
     [FaultContract(typeof(MyFaultContract))] 
     string Method(String Param); 
} 

public class MyService : IMyService 
    { 
     public string Method(String Param) 
     { 
      throw new NullReferenceException("code-created null message here"); 
     } 
} 

사용자 정의 예외 처리기 (엔터프라이즈 라이브러리)

public class MyExceptionHandler : IExceptionHandler 
    { 
     public MyExceptionHandler(NameValueCollection collection) { } 

     public MyExceptionHandler() { } 

     public System.Exception HandleException(System.Exception exception, 
           Guid handlingInstanceId) 
     { 
       MyFaultContract details = new MyFaultContract(); 
       if (exception is NullReferenceException) 
       { 
        details.ErrorCode = MyFaultCode.NullReferenceException; 
        details.OriginalMessage = exception.Message; 
        details.MyMessage = "Null Reference exception here!"; 
       } 
       return new FaultException<MyFaultContract>(details); 
      } 
} 
NullReferenceException이 매핑

응용 프로그램 구성 파일에 "사용자 정의 예외 처리기 ":

<exceptionPolicies> 
     <add name="PolicyName"> 
     <exceptionTypes> 
      <add name="NullReferenceException" type="System.NullReferenceException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
      postHandlingAction="ThrowNewException"> 
      <exceptionHandlers> 
       <add type="MyExceptionHandler, MyApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 
       name="MyExceptionHandler" /> 
      </exceptionHandlers> 
      </add> 
     </exceptionTypes> 
     </add> 
    </exceptionPolicies> 
,363,210

그리고이 오류 예외 잡을 것으로 기대 마지막으로 클라이언트 코드 :

MyService.MyServiceClient client = new MyService.MyServiceClient(); 
      client.Open(); 
      try 
      { 
       string result = client.Method(string parameter); 
      } 

      catch (System.ServiceModel.FaultException<MyService.MyFaultContract> ex) 
      { 
       // where I think exception should end up 
      } 
      catch (System.ServiceModel.FaultException ex) 
      { 
       // general FaultException 
      } 

하지만 그 대신 내가 응답 조치가 필요하다고 주장하는 ProtocolException 사용을 얻을 :

응답 메시지가 작동받은 '를 방법 '행동으로'. 그러나 클라이언트 코드는 'http://tempuri.org/MyService/MethodResponse'조치가 필요합니다.

내가 뭘 잘못하고 있니? "Custom Exception Handler"에서 사용자 정의 FaultContract를 사용하여 FaultException을 리턴 (명시 적으로 던지지 않음) 할 수 있습니까?

모든 조언을 주시면 감사하겠습니다.

업데이트 : "사용자 지정 예외 처리기"의 사후 처리 작업은 "ThrowNewException"로 설정됩니다. "NotifyRethrow"로 변경하면 더 이상 "ProtocolException"을 het하지 않습니다! 대신 클라이언트는 일반적인 "FaultException"(사용자 정의 유형이 아님)을 포착합니다.

이제는 원래 사용자 정의 유형의 FaultException이 전선을 가로 지르지 않는 이유가 여기에 있습니다.

업데이트 내가 언급하는 것을 잊었다 2 것은 내 WCF 서비스가되지 IIS에서, ServiceHost를 내에서 실행되고있는 사실이다. 따라서 기본적으로 ServiceHost를 만들고이 ServiceHost를 통해 Service1 인터페이스를 제공하는 Windows 서비스가 있습니다.

이것이이 문제와 관련이 있다고 생각하는 이유는 엔터프라이즈 라이브러리가 서비스 경계 내에서뿐만 아니라 전체 응용 프로그램에서 예외를 처리한다고 주장하기 때문입니다. 어쩌면 이렇게하면 예외가 너무 늦게 던질 수 있습니까? 아니면 올바른 수준으로?

업데이트 3
게시물을 보내 주셔서 감사합니다! 맞습니다. MyFaultCode 값을 설정하기 때문에 커스텀 핸들러가 엉망입니다. 2 명의 처리기를 구성하여 귀하의 충고를 시도했습니다.

First는 사용자 지정 처리기이며 NullReference 예외를 catch합니다. MyFaultContract 필드와 함께 MyApplicationException이라는 새로운 예외를 throw합니다.

그런 다음 MyApplicationException을 포착하고 새 FaultException을 만들고 MyApplicationException에서 MyApplicationException을 새로 생성 된 FaultException에 자동으로 매핑하는 기본 제공 "오류 계약 예외 처리기"를 구성했습니다.

WCF 클라이언트는 여전히 사용자 지정 계약서가 아닌 일반적인 FaultException을 catch합니다.

답변

2

맞춤 WCF IErrorHandler 구현을 사용하는 것이 좋습니다. 그것은 서비스 메소드 내에서 발생하는 모든 처리되지 않은 예외를 중앙에서 처리 할 수있는 장소를 제공합니다.

내 의견으로는 Ent Lib을 사용하는 것보다 더 깔끔하게 끝나고 1 의존성이 적으며 구성에 오류 매핑이 필요하지 않으므로 XML이 적습니다.

예 :

public class MyServiceErrorHandler : IErrorHandler 
{ 
    /// <summary> 
    /// Central error handling for WCF services. 
    /// Whenever a service encounteres an unhandled exception, it will end up here. 
    /// This method will log the error and continue with normal error processing. 
    /// </summary> 
    /// <param name="error">The unhandled exception thrown from a service method.</param> 
    /// <returns>true if the exceptions has been handled, false if normal error processing should continue. This implementation will always return false.</returns> 
    public virtual bool HandleError(Exception error) 
    { 
     return false; // returning false so that WCF will still process the exception as usual. 
    } 

    /// <summary> 
    /// Create a custom Fault message to return to the client. 
    /// </summary> 
    /// <param name="error">The Exception object thrown in the course of the service operation.</param> 
    /// <param name="version">The SOAP version of the message.</param> 
    /// <param name="fault">The Message object that is returned to the client, or service, in the duplex case.</param> 
    public virtual void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     //If it's a FaultException already, then we have nothing to do 
     if (error is FaultException) 
      return; 

     // pack the exception info into the Fault Contract 
     MyFaultContract details = new MyFaultContract(); 
     if (exception is NullReferenceException) 
     { 
      details.ErrorCode = MyFaultCode.NullReferenceException; 
      details.OriginalMessage = error.Message; 
      details.MyMessage = "Null Reference exception here!"; 
     } 
     var faultException = new FaultException<MyFaultContract>(details); 

     // turn the fault contract into the response WCF Message. 
     var messageFault = faultException.CreateMessageFault(); 
     fault = Message.CreateMessage(version, messageFault, faultException.Action); 
    } 
} 

당신은 엔트 lib 디렉토리를 사용하려는 다른 이유가 있다면 물론, 그때 가서. 어떻게 든 그들을 둘 다 묶을 수 있습니다.

이 링크는 또한 사용자 정의 IErrorHandler 동작을 추가하는 등 오류 처리에 대한 좋은 읽기있다 :이 코멘트를 만들려고하지만 너무 오래있어 http://www.codeproject.com/KB/WCF/WCFErrorHandling.aspx

+0

이 솔루션을 지적 해 주셔서 감사합니다. 나는 그것을 시험해 보았다. 그리고 내가 지금 필요로하는 것을하는 것처럼 보인다. 그것은 정말로 느껴진다. 예외를 와이어에 적용하고 일부 로직을 실행하려고 할 때 순간을 포착하고 있음을 의미합니다. 다른 팀 구성원에게는 정확하지 않을 수 있지만 필요한 것은 분명합니다. 다시 한번 고마워! – iEddie

0

합니다.

오류 처리 예외 처리기로 예외 처리 블록 예외 차폐를 사용 했습니까? 나는 그것이 당신이 원하는 대부분을한다고 생각합니다. http://msdn.microsoft.com/en-us/library/ff953192(v=PandP.50).aspx

접근 방식은 사용자 지정 예외 유형에 모든 속성을 매핑하는 자체 처리기를 만드는 것입니다. 그런 다음 FaultContractExceptionHandler를 구성하여 예외의 특성을 결함 계약의 특성에 맵핑하십시오.

MyFaultCode에 값을 설정하지 않아도되면 사용자 지정 처리기를 모두 작성하지 않아도됩니다.

+0

당신이 맞습니다. MyFaultCode 값을 설정하기 때문에 커스텀 핸들러를 망치고있는 유일한 이유가 있습니다. 그래서 여기 내 2 hadnlers : 먼저 사용자 지정 처리기이며 NullReference 예외를 catch합니다. MyFaultContract 필드와 함께 MyApplicationException이라는 새로운 예외를 throw합니다. 두 번째 처리기 - MyApplicationException을 포착하고 새 FaultException을 만들고 ** 자동으로 ** MyApplicationException에서 MyFaultcontract를 새로 만든 FaultException으로 매핑하는 기본 제공 "오류 계약 예외 처리기"입니다. WCF 클라이언트는 여전히 사용자 지정 계약이 아닌 일반 FaultException을 catch합니다. – iEddie

+0

@iEddie : 원하는대로 작동하는 내장 된 오류 계약 예외 처리기입니까? 나는. FaultException이 아닌 FaultException을 던지고 있습니까? ? –

+0

글쎄, 만약 내가 빌트인 결함 계약 예외 처리기를 사용한다면 - 그렇다. 그래서, 명시 적으로 MyApplicationException을 던지고 있는데, EL에 Fault Contract 예외 처리기를 구성하여 MyApplicationException을 catch하고 FaultException 로 설정합니다. 이런 경우에는 - 모든 것이 잘 작동합니다. 하지만 내 사용자 정의 FaultException FaultCode 필드를 채우려면 원하는 및 표준 매핑 (EL GUI 매핑 인터페이스) 같은 고정 된 값을 새 예외를 설정하는 방법을 하나의 예외 개체에서 다른 값으로 전송할 수 있습니다. – iEddie