IErrorHandler没有绑定,也没有处理错误

时间:2011-04-26 11:19:24

标签: wcf error-handling ierrorhandler

我有一个WCF服务,我有一个带有IErrorHandler的FaultContract,它运行良好。出于某种原因,我不知道,它在运行时停止了绑定。当我在ApplyDispatchBehaviorValidate上放置断点时,在我开始调试时它们没有被调用(它用来停止),所以当我收到错误时我的异常就不会被处理了。
我最初遵循this blog post来实现它,它工作正常,但是当我添加第二个接口/端点时,它停止工作。我根据this SO post更改了所有代码,但无济于事。另一件事情是,当我使用Microsoft服务配置编辑器打开web.config时,我收到错误:

The 'TestAppServer, Version 1.0.0.0, Culture=neutral, PublicKeyToken=null' assembly could not be found. Do you want to locate it? If you select 'No', you will not be prompted for the same assembly again. To avoid seeing this message every time the system cannot fund the assembly, please copy the assembly file to the same folder as the configuration file.

在我添加第二个端点/接口后,当我在WCF服务上丢失了错误处理时,上述错误开始发生。以下是我的网络配置:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="ServiceErrorHandler" type="company.Test.appserver.implementation.ServiceErrorHandlerBehaviorExtensionElement, TestAppServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>
    <bindings>
      <basicHttpBinding>
        <binding name="SimpleBinding" />
      </basicHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="DefaultBehavior" name="company.Test.appserver.implementation.TestUpdate">
        <endpoint address="udt" binding="basicHttpBinding" bindingConfiguration="SimpleBinding"
          name="TestUpdate" bindingNamespace="http://company/Test/update/2011/04"
          contract="company.Test.appserver.interfaces.ITestUpdate" />
        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
          name="TestUpdateMex" bindingNamespace="http://company/Test/update/2011/04"
          contract="IMetadataExchange" />
      </service>
      <service behaviorConfiguration="DefaultBehavior" name="company.Test.appserver.implementation.TestTransaction">
        <endpoint address="udt" binding="basicHttpBinding" bindingConfiguration="SimpleBinding"
          name="TestTransacao" bindingNamespace="http://company/Test/transaction/2011/04"
          contract="company.Test.appserver.interfaces.ITestTransacao" />
        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
          name="TestTransacaoMex" bindingNamespace="http://company/Test/transaction/2011/04"
          contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultBehavior">
          <serviceMetadata httpGetEnabled="true" httpGetBinding="webHttpBinding"
            httpGetBindingConfiguration="" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" httpGetBinding="webHttpBinding"
            httpGetBindingConfiguration="" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

以下是我的错误处理程序的代码:

namespace company.Test.appserver.implementation
{
  public class ServiceErrorHandlerBehaviorExtensionElement : BehaviorExtensionElement, IServiceBehavior
  {
    public override Type BehaviorType
    {
      get { return typeof(TestErrorHandler); }
    }

    protected override object CreateBehavior()
    {
      return new TestErrorHandler();
    }

    private IErrorHandler GetInstance()
    {
      return new TestErrorHandler();
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {

    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
      IErrorHandler errorHandlerInstance = GetInstance();
      foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
      {
        ChannelDispatcher cd = cdb as ChannelDispatcher;

        if (cd != null)
        {
          cd.ErrorHandlers.Add(errorHandlerInstance);
        }
      }
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
      foreach (var svcEndpoint in serviceDescription.Endpoints)
      {
        if (svcEndpoint.Contract.Name != "IMetadataExchange")
        {
          foreach (var opDesc in svcEndpoint.Contract.Operations)
          {
            if (opDesc.Faults.Count == 0)
            {
              string msg = string.Format("");
            }
          }
        }
      }
    }
  }

  public class TestErrorHandler : IErrorHandler
  {
    public bool HandleError(Exception error)
    {
      return true;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
      if (!(error is FaultException))
      {
        ClsTestFaultContract exContract = new ClsTestFaultContract();

        FaultException<ClsTestFaultContract> fex = 
          new FaultException<ClsTestFaultContract>(exContract, exContract.DescricaoErro,
            new FaultCode(Convert.ToString(exContract.CodigoErro)));
        MessageFault msgFault = fex.CreateMessageFault();
        fault = Message.CreateMessage(version, msgFault, ErrorHandlerConstant.FaultAction); 
      }
    }
  }
}

以下是我的一个界面:

namespace company.Test.appserver.interfaces
{
  [ServiceContract(Namespace = "http://company/Test/transaction/2011/04",
            Name = "ITestTransacao", SessionMode = SessionMode.Allowed)]
  public interface ITestTransacao
  {
    [OperationContract]
    [FaultContract(typeof(ClsTestFaultContract), Action = ErrorHandlerConstant.FaultAction)]
    Int32 RegistrarTransacao(String Param1, String Param2, String Param3, Int32 Param4);
    [OperationContract]
    [FaultContract(typeof(ClsTestFaultContract), Action = ErrorHandlerConstant.FaultAction)]
    void ConfirmarTransacao(String Param1, String Param2, Int32 Param3, String Param4, String Param5);
    [OperationContract]
    [FaultContract(typeof(ClsTestFaultContract), Action = ErrorHandlerConstant.FaultAction)]
    void CancelarTransacao(String Param1, String Param2, String Param3, Int32 Param4, String Param5 = "");
  }
}

我已经浪费了无数个小时,而且我似乎无法弄清楚发生了什么,这破坏了我的错误处理,这工作得很好。 请大家帮忙

修改

在我得到帮助之后,我在工作代码下方张贴。再说一遍...... 下面是正确的错误处理程序:

namespace company.Test.appserver.implementation
{
  public class ServiceErrorHandlerBehaviorExtensionElement : BehaviorExtensionElement
  {
    public override Type BehaviorType
    {
      get { return typeof(TestErrorHandler); }
    }

    protected override object CreateBehavior()
    {
      return new TestErrorHandler();
    }
  }

  public class TestErrorHandler : ServiceErrorHandlerBehaviorExtensionElement, IErrorHandler, IServiceBehavior
  {
    public bool HandleError(Exception error)
    {
      return true;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
      if (!(error is FaultException))
      {
        ClsTestFaultContract exContract = new ClsTestFaultContract();

        FaultException<ClsTestFaultContract> fex = 
          new FaultException<ClsTestFaultContract>(exContract, exContract.DescricaoErro,
            new FaultCode(Convert.ToString(exContract.CodigoErro)));
        MessageFault msgFault = fex.CreateMessageFault();
        fault = Message.CreateMessage(version, msgFault, ErrorHandlerConstant.FaultAction); 
      }
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {

    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
      foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
      {
        ChannelDispatcher cd = cdb as ChannelDispatcher;

        if (cd != null)
        {
          cd.ErrorHandlers.Add(this);
        }
      }
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
      foreach (var svcEndpoint in serviceDescription.Endpoints)
      {
        if (svcEndpoint.Contract.Name != "IMetadataExchange")
        {
          foreach (var opDesc in svcEndpoint.Contract.Operations)
          {
            if (opDesc.Faults.Count == 0)
            {
              string msg = string.Format("");
            }
          }
        }
      }
    }
  }
}

以下是正确的web.config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="ServiceErrorHandler" type="company.Test.appserver.implementation.ServiceErrorHandlerBehaviorExtensionElement, TestAppServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>
    <bindings>
      <basicHttpBinding>
        <binding name="SimpleBinding" />
      </basicHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="DefaultBehavior" name="company.Test.appserver.implementation.TestUpdate">
        <endpoint address="udt" binding="basicHttpBinding" bindingConfiguration="SimpleBinding"
          name="TestUpdate" bindingNamespace="http://company/Test/update/2011/04"
          contract="company.Test.appserver.interfaces.ITestUpdate" />
        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
          name="TestUpdateMex" bindingNamespace="http://company/Test/update/2011/04"
          contract="IMetadataExchange" />
      </service>
      <service behaviorConfiguration="DefaultBehavior" name="company.Test.appserver.implementation.TestTransaction">
        <endpoint address="udt" binding="basicHttpBinding" bindingConfiguration="SimpleBinding"
          name="TestTransacao" bindingNamespace="http://company/Test/transaction/2011/04"
          contract="company.Test.appserver.interfaces.ITestTransacao" />
        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
          name="TestTransacaoMex" bindingNamespace="http://company/Test/transaction/2011/04"
          contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultBehavior">
          <serviceMetadata httpGetEnabled="true" httpGetBinding="webHttpBinding"
            httpGetBindingConfiguration="" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <ServiceErrorHandler />
        </behavior>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" httpGetBinding="webHttpBinding"
            httpGetBindingConfiguration="" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <ServiceErrorHandler />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

1 个答案:

答案 0 :(得分:4)

您的配置文件已注册ServiceErrorHandler行为扩展,但实际上并未在&lt; serviceBehaviors /&gt;下的任何集合中使用它。