【问题标题】:WCF exception IErrorHandler not getting calledWCF 异常 IErrorHandler 没有被调用
【发布时间】:2013-03-08 13:02:15
【问题描述】:

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

【问题讨论】:

    标签: c# wcf exception ierrorhandler


    【解决方案1】:

    您的behavior 部分中是否缺少&lt;errorHandler /&gt;

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

    完整答案是here。对那个答案加 1。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 2013-07-31
        • 1970-01-01
        • 1970-01-01
        • 2013-06-08
        • 2011-02-21
        • 2012-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多