tags:

views:

304

answers:

2

I have a WCF service that has REST and SOAP endpoints for every service. This was implemented similarly to this post: http://stackoverflow.com/questions/186631/rest-soap-endpoints-for-a-wcf-service with a configuration similar to the following:

<services>
  <service name="TestService">
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    <endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
    <endpoint address="rest" binding="webHttpBinding" contract="ITestService"/>
  </service>
</services>

The problem is that the REST endpoint shows up in the resulting WSDL as an additional port and binding.

Is there any way to prevent the REST endpoint from being included in the WSDL?

+1  A: 

You can get a copy of the WSDL, manually edit it to remove unwanted artifacts, and store it in a known location. Once you have the version of your WSDL that removes unwanted artifacts, you can redirect the ?wsdl query to that location:

<behaviors>
 <serviceBehaviors>
    <behavior name="TestServiceBehavior">
     <serviceMetadata httpGetEnabled="True" externalMetadataLocation="http://localhost/TestService.wsdl"/&gt;
    </behavior>
 </serviceBehaviors>
</behaviors>

A couple caveats about this solution. You have to be careful about what you edit. If you change critical aspects of the contract, WCF may not be able to handle messages from clients generated from it. Removing an endpoint is generally not a big deal, however changing names for bindings, operations, message types, etc. can cause problems.

You also need to be aware of imports. The WSDL generated by WCF usually defines the endpoints, then imports another .wsdl that defines the actual service contract. The service contract wsdl in tern usually imports several .xsd files that define your message and data types. You will need to make sure you have copies of these uploaded relative to the root .wsdl, and that you update the import elements to reference them appropriately.

Another issue with this is that you are now manually controlling your contract...which means if you change it, you have to edit it again and replace it on whatever site you are hosting the .wsdl file. Now, a properly designed contract should NEVER change, as that breaks one of fundamental SOA rules about web services. However, it appears that you are doing code-first development, so its something to be aware of.

jrista
The manual solution will work, however as you point out, it's far from ideal. For better or worse, this service will evolve over time with new methods added periodically, so the contract WILL change. I'm looking for a more automated solution, so I don't have to remember to muck with the WSDL on every service enhancement.
WayneC
There is no reason you couldn't automate the process. It is all XML, and it should be easy enough to write some process, maybe even a powershell script, that is run as part of your deployment process. It could pull down all the files from the normal ?wsdl query, use XPath to find and remove the required element, and deploy all the .wsdl and .xsd files. Finally, it could update the configuration automatically to add the <serviceMetadata ...> element to your binding behavior.
jrista
A: 

It would be nice if there was an attribute to decorate the endpoint so that it is hidden from mex/wsdl generation in future versions of WCF for exactly this reason (hiding restful services from soap clients).

infocyde