2011-07-05 2 views
14

나는이 모든 것을 읽었 습니다만, 어쩌면 나는 뭔가를 놓치고 있습니다. (물론, 그렇지 않다면 이미 작동하지 않을 것입니다)클라이언트는 일반 FaultException을 catch하지 않을 것입니다 < T >, FaultException 만

내 서버 비즈니스 계층 내부에서 일부 예외 오류를 던지고있어 : 나는 서비스에서 처리되지 않은 떠나지 만, 내가 IErrorHandler

public class RfcException : Exception 
{ 
    public RfcException(string _m, Exception _inner) : base(_m, _inner) 
    { } 

    public Dictionary<string, string> ExtendedProperties 
    { 
     get { return extendedProperties; } 
     protected set { extendedProperties = value; } 
    } 

    private Dictionary<string, string> extendedProperties = new Dictionary<string, string>(); 
} 

가 잡아 만들 FaultMessage :

public class FaultErrorHandler : BehaviorExtensionElement, IErrorHandler, IServiceBehavior 
{ 
    public bool HandleError(Exception error) 
    { 
     if (!Logger.IsLoggingEnabled()) return true; 
     var logEntry = new LogEntry 
     { 
      EventId = 100, 
      Severity = TraceEventType.Error, 
      Priority = 1, 
      Title = "WCF Failure", 
      Message = string.Format("Error occurred: {0}", error) 
     }; 
     logEntry.Categories.Add("MiddleTier"); 

     Logger.Write(logEntry); 
     return true; 
    } 

    public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault) 
    { 
     if (error is RfcException) 
     { 
     RfcException rfcException = error as RfcException; 
     var serviceFault = new RfcServiceFault(rfcException); 
     var faultException = new FaultException<RfcServiceFault>(serviceFault, new FaultReason(string.Format("System error occurred, exception: {0}", error))); 
     var faultMessage = faultException.CreateMessageFault(); 
     fault = Message.CreateMessage(version, faultMessage, Schema.WebServiceStandard); 
     } 
     else 
     { 
     var faultException = new FaultException<Exception>(error, new FaultReason(string.Format("System error occurred, exception: {0}", error))); 
     var faultMessage = faultException.CreateMessageFault(); 
     fault = Message.CreateMessage(version, faultMessage, Schema.WebServiceStandard); 
     } 
    } 

    public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
    { } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) 
    { 
     foreach (ChannelDispatcher chanDisp in serviceHostBase.ChannelDispatchers) 
     { 
     chanDisp.ErrorHandlers.Add(this); 
     }; 
    } 

    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) 
    { } 

    public override Type BehaviorType 
    { 
     get { return typeof(FaultErrorHandler); } 
    } 

    protected override object CreateBehavior() 
    { 
     return new FaultErrorHandler(); 
    } 
} 

요청할 필요가 없습니다. 이미 디버거를 사용하여 부품 번호 if (error is RfcException)에 입력했음을 확인했습니다.이 코드를 통해 단계적으로 진행되었으므로 문제없이 끝까지 도달합니다. 이제

[ServiceContract(Name = "MyService", Namespace = Schema.WebServiceStandard, SessionMode = SessionMode.Allowed)] 
public interface IMyService 
{ 
    [OperationContract(Name = "GetStuff")] 
    [FaultContract(typeof(RfcServiceFault) , Name="RfcServiceFault", Namespace="Service.DataTransfer.Rfc")] 
    LookupResult GetStuff(); 
} 

을 : ErrorHandler를가 FaultException<RfcServiceFault> 메시지를 래핑 는 RfcServiceFault 메시지 서비스는 faultContract와 WCF 서비스를해야하는 모든 주석을 가지고이

[DataContract(Name = "RfcServiceFault", Namespace = "Service.DataTransfer.Rfc")] 
public class RfcServiceFault 
{ 
    public RfcServiceFault(RfcException rfcException) : this((Exception)rfcException) 
    { 
     ExtendedProperties = new Dictionary<string, string>(rfcException.ExtendedProperties); 
    } 

    public RfcServiceFault() 
    { } 

    public RfcServiceFault(Exception regularException) 
    { 
     FaultMessage = regularException.Message; 
     StackTrace = regularException.StackTrace; 
    } 

    public Dictionary<string, string> ExtendedProperties 
    { 
     get { return extendedProperties; } 
     protected set { extendedProperties = value; } 
    } 

    [DataMember] 
    private Dictionary<string, string> extendedProperties = new Dictionary<string, string>(); 

    [DataMember] 
    public string FaultMessage { get; set; } 

    [DataMember] 
    public string StackTrace { get; set; } 
} 

인에서 테스트 클라이언트, 다음과 같은 간단한 테스트 :

try 
{ 
    var result = myService.GetStuff(); 
    Assert.IsTrue(!string.IsNullOrEmpty(result)); 
} 
catch (FaultException<RfcServiceFault> rfcEx) 
{ 
    // OMG FOR THE LIFE OF THE PUPPIES ENTER HERE 
} 
catch (FaultException rr) 
{ 
    // it always falls in here 
} 
catch (Exception ex) 
{ } 

나는 많은 것을 읽었으며, 이 유사한 문제에 대한 많은 게시물 :

하지만 아무것도 지금까지 내가 추적을 WCF를 설정하려고했습니다 도움이 보인다 Web.config의 :

<system.diagnostics> 
    <sources> 
     <source name="System.ServiceModel" 
       switchValue="Information, ActivityTracing"> 
     <listeners> 
      <add name="log" 
       type="System.Diagnostics.XmlWriterTraceListener" 
       initializeData="c:\Traces.svclog" /> 
     </listeners> 
     </source> 
    </sources> 
    </system.diagnostics> 

하고 내가 거기에 svclog 파일을 얻을, 나는 WCF 추적 뷰어로 열고,하지만 난 단지, 노란색 하나는 예외를 보여 메시지의 무리를 볼 수 있지만, 그것은 단지 클라이언트가 이미 System.ServiceModel.FaultException,보고되어 수신되는 것을 확인 오히려 일반적인 하나

어떤 아이디어보다이 문제를 파악하는 방법?

편집 내가 이렇게 설정 내 오류 처리기를 활성화 언급하는 것을 잊었다 :

<behaviorExtensions> 
    ..... 
    <add name="faultErrorHandlerBehavior" 
     type="Service.FaultErrorHandler,Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    ..... 
</behaviorExtensions> 
<serviceBehaviors> 
    <behavior name="ServiceBehavior"> 
     <serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="200" 
          maxConcurrentInstances="200" /> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
     <faultErrorHandlerBehavior /> 
    </behavior> 
</serviceBehaviors> 
+0

을 당신이 한 번에 너무 많은 문제를 해결하기 위해 노력하고있다 – lurscher

+3

서비스 오류에서 사전 속성을 주석 시도 할 것이다. IErrorHandler를 제거하고 단순히 string을 제외한 추가 속성없이 새로운 CustomFault를 사용할 수 있습니까? –

+0

@Henk 사전을 제거하지 않는 것이 상황을 개선하는 것처럼 보입니다 – lurscher

답변

14

(이 어둠 속에서 자상의 비트입니다) 난 당신이 문제가있을 수 있습니다 생각 액션 인해 오류가 클라이언트에서 예상 한 것과 일치하지 않습니다. 다음으로, createMessage의 교체하시기 바랍니다 수 :

fault = Message.CreateMessage(version, faultMessage, faultException.Action); 
+5

당신은 배웠습니다. 힘을 느껴, 당신은 WCF Jedi입니다! .. OWK가 말했듯이, "당신의 눈은 당신을 속일 수 있습니다, 그들을 신뢰하지 마십시오." – lurscher

+0

감사합니다 lurscher. 그것을 듣고 행복하게 문제를 해결했습니다. –

+1

thx이 기사에서는이 문제를 해결했습니다. 참고로, ** [FaultContract (typeof (RfcServiceFault))] ** 특성을 추가 할 때 ** 클라이언트에서 ** Service를 다시 사용해야합니다. 측면 – Gavin