【问题标题】:IErrorHandler doesn't seem to be handling my errors in WCF .. any ideas?IErrorHandler 似乎没有处理我在 WCF 中的错误 .. 有什么想法吗?
【发布时间】:2011-03-03 11:25:37
【问题描述】:

一直在阅读有关 IErrorHandler 的信息,并想走配置路线。 因此,我已阅读以下内容以尝试实施它。

MSDN

Keyvan Nayyeri blog about the type defintion

Rory Primrose Blog

这基本上只是封装在一个继承 IErrorHandler 和 IServiceBehaviour 的类中的 msdn 示例......然后它封装在从 BehaviourExtensionElement 继承的 Extension 元素中,据称允许我将该元素添加到 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)
    {


    }
}

以及行为扩展元素

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

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

【问题讨论】:

    标签: wcf ierrorhandler


    【解决方案1】:

    这是一个完整的工作示例:

    [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>
    

    【讨论】:

    • 非常感谢,抱歉,我花了这么长时间才回答我的工作设置很糟糕。不过,这在我在家中的设置上效果很好。
    • 为我工作,即使 Visual Studio 抱怨“元素行为具有无效的子元素错误处理程序” - 我只是忽略它并在运行时工作。
    • 如何让它返回一个自定义类型的 json 对象(例如 MyFault)?
    • 这里是如何让它返回 json:stackoverflow.com/questions/1149037/…
    【解决方案2】:

    您可以通过向 ApplyDispatchBehavior 添加打印或断点来查看 web.config 是否正在工作和加载,并查看在服务首次打开时是否打印/命中。那么它正在加载吗?

    我也会在 ProvideFault 添加一个打印/断点。

    【讨论】:

    • 没有命中断点。我唯一能遇到的断点是在 web 服务本身。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多