Web Services are supposed to be interoperable, right? Well I'd like to think so at least. I've been continually frustrated about how .NET serializes DataSets. While it's gotten slightly better in 2.0, it's far from being interoperable. Since DataSets are the easiest way to retrieve data from a database, manipulate it etc., .NET has given us strong typed DataSets. With 2.0 they are even better with the addition of TableAdapters that allow you to easily write code to query the database right from the TableAdapter. This works great when hooking up to web page or WinForm controls, but not so great when using them for web services.
Here is what I mean... below is a snip-it of the WSDL of a simple Persons class that I wrote and used as a return type of my web service:
<s:complexType name="Persons">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Persons" type="tns:ArrayOfPerson" />
</s:sequence>
</s:complexType>
<s:complexType name="ArrayOfPerson">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="Person" nillable="true" type="tns:Person" />
</s:sequence>
</s:complexType>
<s:complexType name="Person">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="FirstName" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="LastName" type="s:string" />
</s:sequence>
</s:complexType>
<s:complexType name="Persons">
The WSDL schema for the Persons class above is really how it should look for the web service to be used by 'any' language or platform.Now, if I re-create this class as a typed DataSet in .NET, here is how it comes out:
<xs:schema xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:mstns="http://tempuri.org/Data.xsd" xmlns="http://tempuri.org/Data.xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/Data.xsd" id="Persons2" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element msdata:IsDataSet="true" msdata:UseCurrentLocale="true" name="Persons2">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Person">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="Firstname" type="xs:string" />
<xs:element minOccurs="0" name="LastName" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
Not too bad, but as you can see, there is some Microsoft specific tags in it (msdata). What is worse is that if you look at the 'help' page generated by ASP.NET, you see this:
<GetPerson2Response xmlns="http://tempuri.org/">
<GetPerson2Result>dataset</GetPerson2Result>
</GetPerson2Response>
The return type is 'dataset'? Yuck. Now, lets say I create a DataSet from a stored procedure which will automatically create a TableAdapter. For some reason, there is a lot more unwanted tags:
<xs:schema xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:mstns="http://tempuri.org/Pricing.xsd" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop" xmlns="http://tempuri.org/Pricing.xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/Pricing.xsd" id="Pricing" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element msdata:IsDataSet="true" msdata:UseCurrentLocale="true" name="Pricing">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="sprptPricingWorldwide">
<xs:complexType>
<xs:sequence>
<xs:element msprop:Generator_UserColumnName="Catalog Number" msprop:Generator_ColumnVarNameInTable="columnCatalog_Number" msprop:Generator_ColumnPropNameInRow="Catalog_Number" msprop:Generator_ColumnPropNameInTable="Catalog_NumberColumn" name="Catalog_x0020_Number">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="15" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="ProductName">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="160" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element msprop:Generator_UserColumnName="Dist 1" msprop:Generator_ColumnVarNameInTable="columnDist_1" msprop:Generator_ColumnPropNameInRow="Dist_1" msprop:Generator_ColumnPropNameInTable="Dist_1Column" minOccurs="0" name="Dist_x0020_1" type="xs:decimal" />
<xs:element msprop:Generator_UserColumnName="Dist 2" msprop:Generator_ColumnVarNameInTable="columnDist_2" msprop:Generator_ColumnPropNameInRow="Dist_2" msprop:Generator_ColumnPropNameInTable="Dist_2Column" minOccurs="0" name="Dist_x0020_2" type="xs:decimal" />
<xs:element msprop:Generator_UserColumnName="Dist 3" msprop:Generator_ColumnVarNameInTable="columnDist_3" msprop:Generator_ColumnPropNameInRow="Dist_3" msprop:Generator_ColumnPropNameInTable="Dist_3Column" minOccurs="0" name="Dist_x0020_3" type="xs:decimal" />
<xs:element msprop:Generator_UserColumnName="Dist 4" msprop:Generator_ColumnVarNameInTable="columnDist_4" msprop:Generator_ColumnPropNameInRow="Dist_4" msprop:Generator_ColumnPropNameInTable="Dist_4Column" minOccurs="0" name="Dist_x0020_4" type="xs:decimal" />
<xs:element msprop:Generator_UserColumnName="Dist Japan" msprop:Generator_ColumnVarNameInTable="columnDist_Japan" msprop:Generator_ColumnPropNameInRow="Dist_Japan" msprop:Generator_ColumnPropNameInTable="Dist_JapanColumn" minOccurs="0" name="Dist_x0020_Japan" type="xs:decimal" />
<xs:element minOccurs="0" name="US" type="xs:decimal" />
<xs:element minOccurs="0" name="CN" type="xs:decimal" />
<xs:element minOccurs="0" name="CHF" type="xs:decimal" />
<xs:element minOccurs="0" name="ECU" type="xs:decimal" />
<xs:element minOccurs="0" name="GBP" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
Now, not only are there the 'msdata' tags but 'msprop' tags too. Of course these are all Microsoft (or .NET) specific and have no place in XSD schemas for web services, unless you are always going to talk to .NET web services. Most programmer's solutions are to create their own custom objects using xml serialization tags, which takes a lot of time which turn out to be a coding and maintenance nightmare. Using a tool like the Sample Code Generator (XSDObjectGen) tool (http://go.microsoft.com/?linkid=5559918) makes life somewhat easier, but still not the solution.
What I would like to see is a property, attribute or something to turn off all the .NET specific tags, so the XSD would be truly Interoperable!