Last tweaks to make FlatWSDL WCF compatible

Mar 11, 2009 at 7:47 PM
Hi,

first of all. Great work!

XmlComments works right out of the box. I will shortly publish a manual to patch svcutil to actually create annotated classes from annotated schemas/wsdl. Check out the blog at http://my-tech-talk.blogspot.com

When I tried FlatWSDL it worked but the resulting proxy code was not quite what it was before.

Here is what happened:

I have class ServiceFault (FaultContract)

[DataContract]
public class ServiceFault
{
        [DataMember]
        public string MessageText { get;set; }
        [DataMember]
        public Guid Id { get;set; }
}

in common WSDL this gets published as

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema .....>
  <xs:import schemaLocation="http://localhost:49190/SCDService.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
  <xs:complexType name="ServiceFault">
  <xs:sequence>
  <xs:element minOccurs="0" name="Id" type="ser:guid" />
  <xs:element minOccurs="0" name="MessageText" nillable="true" type="xs:string" />
  </xs:sequence>
  </xs:complexType>
  <xs:element name="ServiceFault" nillable="true" type="tns:ServiceFault" />
  </xs:schema>

The Import happens because of the Type Guid in my class which is defined in the http://schemas.microsoft.com/2003/10/Serialization/  namespace.

In FlatWSDL mode you remove the imports. As all included schemas are exported the resulting WSDL is perfectly valid.....

But a valid WSDL is not good enough for WCF.


When I generate the proxy my class ServiceFault all of sudden looks like:

public partial class ServiceFault : object, System.Xml.Serialization.IXmlSerializable
{
        private System.Xml.XmlNode[] nodesField;
        private static System.Xml.XmlQualifiedName typeName = new System.Xml.XmlQualifiedName("ServiceFault", "http://schemas.datacontract.org/2004/07/SCDServices.FaultContracts");
        
        public System.Xml.XmlNode[] Nodes
 .....

I came close to the reason when I switched svcutil to /dconly...

Then I got the error message:

"Error: Type 'ServiceFault' in namespace 'http://schemas.datacontract.org/2004/07/SCDServices.FaultContracts' cannot be imported. It references 'guid' from namespace 'http://schemas.microsoft.com/2003/10/Serialization/' but schema does not contain appropriate <import> statement. Either change the schema so that the types can map to data contract types or use ImportXmlType or use a different serializer."

Then I tracked down that it works fine when I rewrote the schema to

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema .......>
  <xs:import namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
  <xs:complexType name="ServiceFault">
  <xs:sequence>
  <xs:element minOccurs="0" name="Id" type="ser:guid" />
  <xs:element minOccurs="0" name="MessageText" nillable="true" type="xs:string" />
  </xs:sequence>
  </xs:complexType>
  <xs:element name="ServiceFault" nillable="true" type="tns:ServiceFault" />
  </xs:schema>

So simply an import without a schemaLocation on an already defined namespace does the job. It's simply a bug in WCF.

So in your code you must not drop the imports but then you run straight into the next problem.

At the time you get access to the WSDL the schemaLocation in the import element is still null. It gets later replaced with the actual URL of the service.

In order to keep the WSDLexporter from expanding the imports schemaLocation you must delete all schemas from

wsdlExporter.GeneratedXmlSchemas

I create an issue with a modified SingleFileExporter.cs attached.

Cheers,
Tobias