2010-06-14 9 views
23

Ho letto su IErrorHandler e voglio seguire il percorso di configurazione. quindi, ho letto quanto segue nel tentativo di implementarlo.IErrorHandler non sembra gestire i miei errori in WCF ... qualche idea?

MSDN

Keyvan Nayyeri blog about the type defintion

Rory Primrose Blog

Questo è fondamentalmente solo l'esempio msdn avvolto in una classe che eredita IErrorHandler e IServiceBehaviour ... allora questo è avvolto l'elemento di estensione che eredita da BehaviourExtensionElement presumibilmente mi permetta di aggiungere l'elemento nel web.config. Cosa ho perso?

L'ho ottenuto per la compilazione e dai vari errori che ho risolto sembra che WCF stia effettivamente caricando il gestore degli errori. Il mio problema è che l'eccezione che sto lanciando per gestire nel gestore degli errori non fa passare l'eccezione ad essa.

L'implementazione del mio servizio chiama semplicemente un metodo su un'altra classe che genera ArgumentOutOfRangeException, tuttavia questa eccezione non viene mai gestita dal gestore.

mio web.config

<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="basic"> 
      <security mode="None" />      
     </binding> 
     </basicHttpBinding> 
    </bindings> 
    <extensions> 
     <behaviorExtensions> 
     <add name="customHttpBehavior" 
      type="ErrorHandlerTest.ErrorHandlerElement, ErrorHandlerTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
     </behaviorExtensions> 
    </extensions> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="exceptionHandlerBehaviour">   
      <serviceMetadata httpGetEnabled="true"/> 
      <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> 
      <serviceDebug includeExceptionDetailInFaults="true"/> 
      <customHttpBehavior /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <services> 
     <service behaviorConfiguration="exceptionHandlerBehaviour" name="ErrorHandlerTest.Service1"> 
     <endpoint binding="basicHttpBinding" bindingConfiguration="basic" contract="ErrorHandlerTest.IService1" /> 
     </service> 
    </services> 

Contratto di Servizio

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    [FaultContract(typeof(GeneralInternalFault))] 
    string GetData(int value); 
} 

La classe ErrorHandler

public class ErrorHandler : IErrorHandler , IServiceBehavior 
{ 
    public bool HandleError(Exception error) 
    { 
     Console.WriteLine("caught exception {0}:",error.Message); 
     return true; 
    } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     if (fault!=null) 
     { 
      if (error is ArgumentOutOfRangeException) 
      { 
       var fe = new FaultException<GeneralInternalFault>(new GeneralInternalFault("general internal fault.")); 
       MessageFault mf = fe.CreateMessageFault(); 

       fault = Message.CreateMessage(version, mf, fe.Action); 

      } 
      else 
      { 
       var fe = new FaultException<GeneralInternalFault>(new GeneralInternalFault(" the other general internal fault.")); 
       MessageFault mf = fe.CreateMessageFault(); 

       fault = Message.CreateMessage(version, mf, fe.Action); 
      } 
     } 
    } 

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

    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     IErrorHandler errorHandler = new ErrorHandler(); 
     foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers) 
     { 
      ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher; 
      if (channelDispatcher != null) 
      { 
       channelDispatcher.ErrorHandlers.Add(errorHandler); 
      } 
     } 
    } 


    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 


    } 
} 

ed il comportamento Elemento di estensione

public class ErrorHandlerElement : BehaviorExtensionElement 
    { 
     protected override object CreateBehavior() 
     { 
      return new ErrorHandler(); 
     } 

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

risposta

43

Ecco un esempio di lavoro completo:

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    [FaultContract(typeof(MyFault))] 
    string GetData(int value); 
} 

[DataContract] 
public class MyFault 
{ 

} 

public class Service1 : IService1 
{ 
    public string GetData(int value) 
    { 
     throw new Exception("error"); 
    } 
} 

public class MyErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) 
    { 
     return true; 
    } 

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

public class ErrorHandlerExtension : BehaviorExtensionElement, IServiceBehavior 
{ 
    public override Type BehaviorType 
    { 
     get { return GetType(); } 
    } 

    protected override object CreateBehavior() 
    { 
     return this; 
    } 

    private IErrorHandler GetInstance() 
    { 
     return new MyErrorHandler(); 
    } 

    void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
    { 
    } 

    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     IErrorHandler errorHandlerInstance = GetInstance(); 
     foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) 
     { 
      dispatcher.ErrorHandlers.Add(errorHandlerInstance); 
     } 
    } 

    void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints) 
     { 
      if (endpoint.Contract.Name.Equals("IMetadataExchange") && 
       endpoint.Contract.Namespace.Equals("http://schemas.microsoft.com/2006/04/mex")) 
       continue; 

      foreach (OperationDescription description in endpoint.Contract.Operations) 
      { 
       if (description.Faults.Count == 0) 
       { 
        throw new InvalidOperationException("FaultContractAttribute not found on this method"); 
       } 
      } 
     } 
    } 
} 

e web.config:

<system.serviceModel> 
    <services> 
    <service name="ToDD.Service1"> 
     <endpoint address="" 
       binding="basicHttpBinding" 
       contract="ToDD.IService1" /> 
    </service> 
    </services> 

    <behaviors> 
    <serviceBehaviors> 
     <behavior> 
     <serviceMetadata httpGetEnabled="true"/> 
     <serviceDebug includeExceptionDetailInFaults="false"/> 
     <errorHandler /> 
     </behavior> 
    </serviceBehaviors> 
    </behaviors> 
    <extensions> 
    <behaviorExtensions> 
     <add name="errorHandler" 
      type="ToDD.ErrorHandlerExtension, ToDD, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </behaviorExtensions> 
    </extensions> 

</system.serviceModel> 
+0

grazie mille, scusa ci ho messo così tanto tempo per rispondere alla mia configurazione al lavoro è alle prese. Questo ha funzionato bene sul mio setup a casa però. –

+0

Grazie per l'esempio completo. Questo ha funzionato come un fascino! – Stewie

+0

Ha funzionato per me, anche se lo studio visivo si lamenta che "il comportamento dell'elemento non ha un elemento figlio errato errorhandler" - Ho appena ignorato e in runtime funziona. – BornToCode

1

È possibile vedere se web.config funziona e si carica aggiungendo una stampa o un punto di interruzione a ApplyDispatchBehavior e vedere se viene stampato/colpito quando il servizio viene aperto per la prima volta. Quindi viene caricato?

aggiungerei anche una stampa/punto di interruzione a ProvideFault.

+0

I punti di interruzione non vengono colpiti. l'unico punto di interruzione che posso colpire è il webservice stesso. –

Problemi correlati