netmajor
netmajor

Reputation: 6585

SOAP headers in WCF REST error

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

Answers (3)

Hpcd
Hpcd

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

Dougc
Dougc

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

Randolpho
Randolpho

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

Related Questions