EndpointDispatcher上的ContractFilter不匹配(错误处理)

时间:2010-08-11 13:45:02

标签: c# .net wcf web-services

在更新我的WCF客户端的服务引用时(只需在Visual Studio 2008中单击更新服务引用),发生以下错误:

  

System.ServiceModel.FaultException:   带有Action的消息   'http://schemas.xmlsoap.org/ws/2004/09/transfer/Get'   不能在接收器处理,   由于ContractFilter不匹配   EndpointDispatcher。这可能是   因为合同不匹配   (发件人和发件人之间不匹配的行为)   接收者)或绑定/安全   发件人和发件人之间不匹配   接收器。检查发件人和   接收者有相同的合同和   相同的绑定(包括安全性   要求,例如消息,运输,   没有)。在   System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(例外   e,留言信息)

背景:

我已经创建了ErrorServiceBehaviour课程。由于为错误处理创建了此类行为,因此必须对每个IErrorHandler应用ChannelDispatcher实现。

public class ErrorServiceBehaviour : Attribute, IServiceBehavior
{
   ...
   public Type FaultType
   {
      get { return _faultType; }
      set { _faultType = value; }
   }

   public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
   {
       foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
       {
           dispatcher.ErrorHandlers.Add(new ErrorHandler(_faultType));
       }
   }
}

public class ErrorHandler : IErrorHandler
{
     public ErrorHandler(Type faultType)
     {
        _faultType = faultType;         
     }
     ...
}

稍后,我通过将ErrorServiceBehavior属性应用于我的服务类来使用该行为:

[ErrorServiceBehavior(FaultType = typeof(MyServiceFault))] 
public class MyService : IMyService
{
   ...
}

问题是,当我在foreach方法中注释ApplyDispatchBehavior循环时,我得到没有错误,但这不是出路(因为我希望我的错误得到处理。)

下面是我的服务配置:

<system.serviceModel>
    <services>
        <service behaviorConfiguration="DefaultBehavior" name="MyService">
            <endpoint address="" binding="wsHttpBinding" contract="IMyService" bindingConfiguration="NoSecurityBinding"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="DefaultBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <bindings>
        <wsHttpBinding>
            <binding name="NoSecurityBinding" >
                <security mode="None">
                    <transport clientCredentialType="None"/>
                    <message establishSecurityContext="false"/>
                </security>
            </binding>
            <binding name="DefaultBinding" />
        </wsHttpBinding>
    </bindings>
</system.serviceModel>

有人可以帮助我吗?

更新

前面显示的代码:

foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
    dispatcher.ErrorHandlers.Add(new ErrorHandler(_faultType));
}

为所有端点添加自定义错误处理 - 包括元数据。但实际上这是问题的根源 - 即使我禁用为元数据端点添加错误处理,问题仍然存在。

另一个通知是,当我将第一个端点的bindingConfiguration更改为DefaultBinding时,我发现没有错误:

<services>
    <service behaviorConfiguration="DefaultBehavior" name="MyService">
        <endpoint address="" binding="wsHttpBinding" contract="IMyService" bindingConfiguration="DefaultBinding"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
</services>

这样的选择也不是我想要的 - 我仍然需要有问题的NoSecurityBinding才能工作。

提前致谢。

7 个答案:

答案 0 :(得分:1)

查看IExtensibleDataObject,它用于处理仍然能够相互通信的Web服务的不同版本。这样合同就不需要完全匹配。希望这会有所帮助。

答案 1 :(得分:1)

首先,我注意到您尝试将 mexHttpBinding 绑定到端点,尽管它从未在您的&#34; Bindings&#34;中定义。标签。这应该是一个例外,我希望这样的例外看起来像是困扰你的那个。

 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

...

<bindings>
    <mexHttpBinding>
        THIS TAG WAS MISSING (add security features as needed)
    </mexHttpBinding>

    <basicHttpBinding>
        <binding name="NoSecurityBinding" >
            <security mode="None" />
        </binding>
        <binding name="DefaultBinding" />
    </basicHttpBinding>
</bindings>

此外,由于您显然不需要任何安全功能,因此您可能希望使用basicHttpBinding。正如此very thorough answer所述,当您想要安全功能时,wsHttpBinding非常有用。

您的配置最终会变得几乎相同,更改&#34; ws&#34;为&#34;基本&#34;。

<system.serviceModel>
<services>
    <service behaviorConfiguration="DefaultBehavior" name="MyService">
        <endpoint address="" binding="basicHttpBinding" contract="IMyService" bindingConfiguration="NoSecurityBinding"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
</services>
<behaviors>
    <serviceBehaviors>
        <behavior name="DefaultBehavior">
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
    </serviceBehaviors>
</behaviors>
<bindings>
    <basicHttpBinding>
        <binding name="NoSecurityBinding" >
            <security mode="None" />
        </binding>
        <binding name="DefaultBinding" />
    </basicHttpBinding>
</bindings>

答案 2 :(得分:1)

检查App.Config并验证它是否指向已部署的Windows服务主机,或将其设置为指向localhost

答案 3 :(得分:0)

根据您的说法,您的新 WCF 服务确实需要安全性,而在 NoSecurityBinding 中,您可以将其关闭。 检查的一种方法是在本地获取 WSDL 文件,看看它是否包含: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd http://schemas.xmlsoap.org/ws/2004/09/policy 或类似于进口的东西。我非常确定您更新的WCF服务已启用安全性


更新1

为了更好地了解您的问题,您可以使用WCF跟踪。在这里,您可以看到如何打开它以及如何阅读这些痕迹:"How to turn on WCF tracing"

答案 4 :(得分:0)

我不认为你完全取消了安检。试试这个:

<bindings>
        <wsHttpBinding>
            <binding name="NoSecurityBinding" >
                <security mode="None">
                    <transport clientCredentialType="None"/>
                    <message clientCredentialType="None"/>
                </security>
            </binding>
            <binding name="DefaultBinding" />
        </wsHttpBinding>
    </bindings>

答案 5 :(得分:0)

现有的web.config设置可能会产生问题,因为它们适用于以前的版本。 最好从WCF客户端应用程序中删除现有引用并再次添加引用。

答案 6 :(得分:0)

<services>
  <service behaviorConfiguration="ServiceBehaviour" name="Service">
    <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" contract="IService">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>