2010-06-14 3 views
23

Читали об этом в IErrorHandler и хотите перейти в конфигурационный маршрут. поэтому, я прочитал следующее в попытке реализовать его.IErrorHandler, похоже, не обрабатывает мои ошибки в WCF .. любые идеи?

MSDN

Keyvan Nayyeri blog about the type defintion

Rory Primrose Blog

Это в основном только пример MSDN, завернутый в класс, который наследует IErrorHandler и IServiceBehaviour ... то это заворачивается в элемент расширения, который наследуется от BehaviourExtensionElement предположительно, позволить мне добавить элемент в файл web.config. Что я пропустил?

У меня есть его для компиляции и из различных ошибок, которые я исправил, похоже, что WCF фактически загружает обработчик ошибок. Моя проблема в том, что исключение, которое я бросаю для обработки в обработчике ошибок, не получает исключение, переданное ему.

Реализация службы просто вызывает метод в другом классе, который вызывает ArgumentOutOfRangeException - однако это исключение никогда не обрабатывается обработчиком.

Мой 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> 

Сервисный контракт

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

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) 
    { 


    } 
} 

И поведение Extension Element

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

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

ответ

43

Вот полный рабочий пример:

[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"); 
       } 
      } 
     } 
    } 
} 

и 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

Большое вам спасибо, извините, что так долго для меня, чтобы ответить на мои настройки на работе, было измотано. Тем не менее, это хорошо работало на моей установке дома. –

+0

Спасибо за полный пример. Это работало как прелесть! – Stewie

+0

Работал для меня, хотя визуальная студия жалуется на «поведение элемента имеет недопустимый дочерний элемент errorhandler» - я просто игнорирую и во время выполнения он работает. – BornToCode

1

Вы можете увидеть, работает ли web.config и загружается, добавив печать или точку останова в ApplyDispatchBehavior и посмотрите, будет ли это печататься/ударяться, когда служба открывается. Так это загружается?

Я бы добавил точку печати/останова в ProvideFault.

+0

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

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