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" contrac开发者_StackOverflow社区t="IMetadataExchange"/>
</service>
</services>
Such an option in also not what I want - I still need problematic NoSecurityBinding
to work.
Thanks in advance.
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.
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>
Check the App.Config
and verify that it is pointing to your deployed Windows service host or set it to point to localhost
.
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>
精彩评论