Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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, e.g. 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.

like image 475
jwaliszko Avatar asked Aug 11 '10 13:08

jwaliszko


3 Answers

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.

like image 188
Chris Avatar answered Nov 06 '22 01:11

Chris


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>

like image 24
Renaud Gauthier Avatar answered Nov 06 '22 02:11

Renaud Gauthier


Check the App.Config and verify that it is pointing to your deployed Windows service host or set it to point to localhost.

like image 1
Manuel Bautista Avatar answered Nov 06 '22 01:11

Manuel Bautista