Web Services in Windows Communication Framework publish their WSDL in a different format than ASMX based services did. WCF publishes the WSDL with discreet XSD schemas for each of the subsections which results in an XML document that pulls from the server.

For example here's a simple WSDL output generated by WCF for a simple 3 method service:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="TimeTrakkerService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
  <wsdl:import namespace="" 
        location="http://rasnote/TimeTrakkerWeb/Services/TimeTrakkerService.svc?wsdl=wsdl0"/>
  <wsdl:types/>
  <wsdl:binding name="BasicHttpBinding_TimeTrakkerService" type="TimeTrakkerService">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="Helloworld">
      <soap:operation soapAction="urn:TimeTrakkerService/Helloworld" style="document"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="LoadCustomer">
      <soap:operation soapAction="urn:TimeTrakkerService/LoadCustomer" style="document"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="GetCustomerList">
      <soap:operation soapAction="urn:TimeTrakkerService/GetCustomerList" style="document"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="TimeTrakkerService">
    <wsdl:port name="BasicHttpBinding_TimeTrakkerService" binding="tns:BasicHttpBinding_TimeTrakkerService">
      <soap:address location="http://rasnote/TimeTrakkerWeb/Services/TimeTrakkerService.svc"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

If you've reviewed a WSDL file before you'll quickly notice that this file seems awfully small and the reason is that most of the full content is actually stored in the import section. Depending on the types and exported there could be any number of imported schema references.

This works all fine and good with WCF clients and even old Web Reference clients understand this functionality.

However, many older Web Service clients don't understand this. The SOAP Toolkit for example chokes on the WSDL, as do many other popular clients like those for Adobe Flex and various scripting language SOAP clients. And yeah my old manual wwSOAP parser written in FoxPro too doesn't deal with the imported schemas and I'm not exactly thrilled about the thought of fixing this old code base to make it work with WCF.

Now one could argue that's too bad for these 'crusty' technologies to not be keeping up with the latest standards, but given that Web Services is above all supposed to be an interoperable technology it's not exactly appropriate to be 'in your face' about it as WCF is.  WCF doesn't internally support flattened WSDL which is quite unfortunate. Given that WCF is trying to be the jack of all trades and its high configurability it seems strange that this functionality was simply omitted effectively breaking a number of Web Service scenarios for various (less fortunate clients) clients.

Fix me up

However, it's good to know that WCF DOES have the capability to fix this issue via a custom ServiceHost implementation and Web Service guru Christian Weyer has a component, sample code and a description of how to hook it up here. It basically creates a custom service host and factory that you can use instead of the standard hosts to provide flat WSDL support. Thanks Christian - I'm glad the community can fill an obvious hole...

ASMX, WCF, ASMX, WCF - eeenie, meenie, meinie moo...

While this works this is still a bit of a headache, and in this case I actually ended up just creating an ASMX service and be done with it instead of including another assembly and configuring web.config. ASMX services are still a lot easier to deal with for simple scenarios compared to WCF which does require a few extra steps.

But it depends on your scenario of course - WCF has a much better serialization story with its DataContractSerializer and one reason I opted for WCF in the first place in this sample app is that I am returning some LINQ generated entities. Using ASMX these entities fail to serialize due to circular references - the WCF serializer handle this correctly by cutting off the circular back reference. In this case I had to explicitly kill some of the related entity references to make the ASMX service work.

Trade-offs, trade-offs always trade offs. There's never a simple clear cut answer <shrug>.