简体   繁体   中英

ContractFilter mismatch at the EndpointDispatcher (error handling)

While updating a service reference of my WCF client (simply by clicking Update Service Reference in Visual Studio 2008), following error occurs:

System.ServiceModel.FaultException: The message with Action ' http://schemas.xmlsoap.org/ws/2004/09/transfer/Get ' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, eg Message, Transport, None). at System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(Exception e, Message message)

Background:

I've created ErrorServiceBehaviour class. Because such a behavior is created for error handling, IErrorHandler implementation must be applied to each 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;         
     }
     ...
}

Later, I've used that behaviour by applying ErrorServiceBehavior attribute to my service class:

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

The thing is, when I comment out the foreach loop inside ApplyDispatchBehavior method, I get no error at all, but that is not the way out (because I want my errors to be handled).

Below there is my service config:

<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>

Can someone help me?

UPDATE

The code shown earlier:

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

adds custom error handling for all endpoints - including the metadata one. But actually this is not the source of the problem - even when I disable adding error handling for metadata endpoint, the issue still occurs.

The other notice is, when I change the bindingConfiguration of the first endpoint to DefaultBinding , I have no error at all:

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

Such an option in also not what I want - I still need problematic NoSecurityBinding to work.

Thanks in advance.

To begin with, I notice your try to bind a mexHttpBinding to an endpoint although it was never defined inside your "Bindings" tag. This should rise an exception, and I would expect such an exception to look like the one that's bothering you.

 <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>

Also, since you apparently dont need any security feature, you might want to favor basicHttpBinding. As this very thorough answer states, wsHttpBinding really is useful when you want security features.

Your configuration would end up being almost the same, changing "ws" for "basic".

<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>

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

Look into the IExtensibleDataObject , it is used to handle different versions of a web service still being able to communicate with each other. This way the contracts don't need to match exactly. Hope this helps.

On what you say it seems that your new WCF service do require security and in your NoSecurityBinding you turn it off. One way to check that is to get WSDL file locally an see if it has: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd or http://schemas.xmlsoap.org/ws/2004/09/policy or something like that in imports. I'm pretty sure that your updated WCF service has security enabled


Update 1

To get a better vision of your problem you could use WCF Tracing. Here you could see how to turn it on and how to read that traces: "How to turn on WCF tracing"

I don't think you are turning the security completely off. Try this:

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

Existing web.config setting can create a problem as they are for previous version. Better to remove existing reference from your WCF client application and Add the reference again.

<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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM