Thursday, April 12, 2007

WCF and WSDL

I've recently started using WCF to develop Web Services. It's a very compelling model that sits much better with a service oriented view of web services than ASMX. The flexibility it gives you is wonderful, you can have any executable host a web service, you can serialize your messages any way you want and you can use any transport. However, if you're just doing standard SOAP, XML over HTTP then it's almost as easy as ASMX.

Part of the change to a more standards oriented web service infratructure in WCF is the way it produces WSDL documents. ASMX by default will always spew out a WSDL document when you appended '?WSDL' to your web services' URL and that WSDL document is always a single file. WCF doesn't create a WSDL document by default, you have to configure that behaviour by adding a serviceMetadata behaviour to your config file:

<serviceBehaviors>
  <behavior name="myServiceBehaviour">
    <serviceMetadata httpGetEnabled="true" />
  </behavior>
</serviceBehaviors>

Also the default pattern for the WSDL file itself has changed, it follows best practices and devides the WSDL document up by namespaces, so if your portTypes namespace is different from your service namespace, you'll get two WSDL files and the service WSDL will reference the portTypes WSDL with a wsdl:import element. The types schemas are always produced as seperate files, again, one for each namespace.

The problem with factoring a WSDL document into seperate files is that many tools don't understand wsdl:import (or xml:include and xml:import) and will simply choke if you try to feed them it. You can override this default behaviour as Tomas Restrepo outlines in this blog post 'Inline XSD in WSDL with WCF', but of course it requires you to have access to the web service.

This behaviour has been giving me a headache because I'm currently trying to create a generic web service test tool. I'm using System.Web.Services.Description.ServiceDescription to load and parse a WSDL file that's given by the user as a URL, but when I tried to run it against a WCF service is choked because the URL only points to the root WSDL document which is in fact exported as several linked files. It looks like I'm going to have load the WSDL more intelligently. I tried running the wsdl.exe tool against the same URL and it works fine, so there might be solution there, I'll have to open up Reflector and have a look:)

Update: I resoloved how to do this in my next post.

More update: Christian Weyer has an interesting post on WCF and multipart WSDLs. He shows how to get WCF to output a single unfactored WSDL document.

No comments: