3

我有一个 WCF 服务,我有一个绑定了 IErrorHandler 的 FaultContract,它运行良好。出于某种原因,我不知道,它在运行时停止绑定。ApplyDispatchBehavior当我在and上放置断点时Validate,在我开始调试时不会调用它们(它用于停止),因此当我收到错误时不会处理我的异常。
我最初按照这篇博客文章来实现它,它运行良好,但是当我添加第二个接口/端点时,它停止工作。我根据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>
4

1 回答 1

4

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

于 2011-04-26T12:42:12.037 回答