Reputation: 6585
I have that error :
Operation 'GetFields' in contract 'IService' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion.
The problem is that my operation was used by two endpoints : CustomEndpoint with messageVersion="Soap12WSAddressing10" and second webHttpBehavior.
And I think that this error fire problem that Rest have MessageVersion.None
Any way to fix it ?
Upvotes: 5
Views: 4979
Reputation: 41
You do not have to provide a different interface and/or implementing service class.
IF you are using code in behaviors that are trying to use XXMessageHeaders via OperationContext, you have to write code to check if MessageVersion on the headers is MessageVersion.None and use WebOperationContext (from System.ServiceModel.Web) instead.
I have a working example with same interface and same implementing service class.
<services>
<service name="ExampleService" behaviorConfiguration="MyServiceBehavior">
<endpoint name="ExampleService.BasicHttpBinding"
binding="basicHttpBinding"
contract="IExampleService"
address="" />
<endpoint name="ExampleService.WebHttpBinding"
binding="webHttpBinding"
contract="IExampleService"
address="restful"
behaviorConfiguration="webHttpRestulBehavior" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webHttpRestulBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
assuming .svc is Example.svc
In IIS the endpoint URL would be:
"http://hostname:port/Example.svc"
for WCF
for Rest:
"http://hostname:port/Example.svc/restful/"
Upvotes: 2
Reputation: 852
I was experiencing the same exception as this when trying to combine two services; one which used a SOAP endpoint and the other which a REST endpoint.
I think the issue is that WCF doesn't seem to like seeing operations which use MessageContract
in the same ServiceContract
as a REST operation. So the way I got around this was by splitting the contracts in two and then having the REST endpoint only implement the WebGet
operation as follows:
[ServiceContract]
public interface IExampleSoapService : IExampleRestService
{
[OperationContract]
void SomeSoapOperation(ExampleMessageContract message);
}
[ServiceContract]
public interface IExampleRestService
{
[OperationContract]
[WebGet(UriTemplate = "/{id}", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare)]
void SomeRestOperation(int id);
}
And then in configuration:
<services>
<service name="ExampleService">
<endpoint name="ExampleService.BasicHttpBinding"
binding="basicHttpBinding"
contract="IExampleSoapService"
address="soap" />
<endpoint name="ExampleService.WebHttpBinding"
binding="webHttpBinding"
contract="IExampleRestService" />
</service>
</services>
One I split the contracts like this, the issue seems to go away.
Upvotes: 1
Reputation: 56439
Unfortunately, in WCF RESTfulness tends to be a contract-level feature. That means that you often can't use a RESTful contract in a non-RESTful context and vice-versa.
You have two options here, and each have their tradeoffs. First, you can have two separate contracts (one marked up for RESTful features and a "plain", non-RESTful one) that are both implemented by your WCF service. This requires that both contracts have identical method signatures, which may not always be possible.
The second option is to have two separate WCF services, each with their own contract and processing code, but to have them both offload operation calls to a third class they both know about that does the actual work. This is the most flexible solution, but tends to require special translation code in either (or both) WCF service in order to call the third class.
Upvotes: 3