WCF异常:IErrorHandler未被调用

4

我好像遇到了一个问题,无法让IErrorHandler接口正常工作。我的代码如下:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace WcfService3
{
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            throw new Exception("asdf");

        }
    }

    public class MyErrorHandler : IErrorHandler
    {
        public MyErrorHandler()
        {
            string Hello = "";
        }
        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文件如下:

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
      <services>
    <service name="WcfService3.Service1">
      <endpoint address=""
                binding="basicHttpBinding"
                contract="WcfService3.IService1" />
    </service>
  </services>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="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="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
      <extensions>
    <behaviorExtensions>
      <add name="errorHandler"
            type="WcfService3.ErrorHandlerExtension, WcfService3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>

    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

我的 WCF 接口是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

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

    [DataContract]
    public class MyFault
    {

    }

}

我的问题与WCF中的IErrorHandler有关,如果在WCF服务调用期间出现任何异常,则应先调用HandlerError()函数,就像C# Windows应用程序中的UnhandledException类一样,然后服务应该崩溃对吧? 在上面的代码中,在服务调用期间抛出异常,但是我的HandlerError函数在异常抛出之前没有被调用? 我的目标是记录错误,WCF服务可以抛出未处理的异常并崩溃。在调试期间,我期望断点会访问HandleError函数,但是该函数没有被调用,只是显示了一个异常?

2个回答

3
你的behavior部分是否缺少了<errorHandler />呢?
<behavior>
    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
    <serviceDebug includeExceptionDetailInFaults="false"/>
    <!-- HERE -->
    <errorHandler />
    <!-- HERE -->
</behavior>

完整的答案在这里链接。对该回答加1个赞。

0
如果有其他人遇到了这个问题,当我遇到这个错误时,是因为错误是在从某个LINQ表达式调用的方法中抛出的。 直到WCF尝试序列化响应时才实际调用该方法,然后在服务范围之外抛出异常。 WCF不会将这些错误传递给IErrorHandler。
在返回之前使用.ToList()使列表具体化解决了我的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接