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 函数,但该函数没有被调用,只是出现了一个异常?

4

2 回答 2

3

你不是<errorHandler />在你的behavior部分失踪吗?

<behavior>
    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
    <serviceDebug includeExceptionDetailInFaults="false"/>
    <!-- HERE -->
    <errorHandler />
    <!-- HERE -->
</behavior>

完整的答案在这里。对该答案加1。

于 2013-07-10T20:57:21.457 回答
0

万一其他人遇到这个,当我遇到这个错误时,这是​​因为从某个 LINQ 表达式调用的方法中抛出了错误。直到 WCF 尝试序列化响应之后才实际调用该方法,然后将响应抛出服务范围之外。WCF 不会将这些错误传递给 IErrorHandler。

在使用 .ToList() 返回之前具体化列表为我解决了这个问题。

于 2018-08-02T19:36:05.573 回答