IErrorHandler 未绑定,且不处理错误

发布于 2024-11-03 03:24:49 字数 12524 浏览 3 评论 0原文

我有一个 WCF 服务,并且有一个绑定了 IErrorHandler 的FaultContract,并且它工作得很好。由于某种原因,我不知道,它在运行时停止绑定。当我在 ApplyDispatchBehaviorValidate 上放置断点时,当我开始调试(它通常会停止)时,它们不会被调用,因此当我得到时,我的异常不会被处理一个错误。
我最初关注了这个博客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>

I have a WCF service, and I have a FaultContract with an IErrorHandler binded to it, and it was working great. For some reason, that I don't know, it stopped being binded at runtime. When I place breakpoints on ApplyDispatchBehavior and Validate, they aren't being called when I start debugging (it use to stop), so my exceptions aren't handled when I get an error.
I initially followed the this blog post to implement it, and it worked fine, but when I added a second interface/endpoint, it stopped working. I changed all of my code according to this SO post, but to no avail. Another thing that started happening is that, when I open the web.config with the Microsoft Service Configuration Editor, I get the error:

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.

The error above started happening after I added the second endpoint/interface, when I lost error handling on my WCF service. Below is my 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" />
        </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>

Below is the code for my Error Handler:

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); 
      }
    }
  }
}

Below is one of my interfaces:

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 = "");
  }
}

I've wasted countless hours, and I can't seem to figure out what happened that broke my error handling, that was working great.
Tks SO MUCH for any help

EDIT

I'm posting below the working code, after the help I got. Tks so much again...
Below is the correct error handler:

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("");
            }
          }
        }
      }
    }
  }
}

And below is the correct 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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

独木成林 2024-11-10 03:24:49

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

Your config file has the ServiceErrorHandler behavior extension registered, but it's not actually using it in any of the collections under <serviceBehaviors/>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文