Using Datasets in WCF and Webservices with Legacy Applications

Recently I came across the issue of XML DataTable to Clean XML, specifically the problem of “Web Service has to deliver neutral/agnostic XML and NOT .NET related information.”  The solution code used XmlDocument which is not the best performing, as well as not being to “monkey-see, monkey-do” quality that is often needed.

 

The solution is simple if you add an extension to the dataset as shown below:

/// <summary>  
/// Returns a dataset as a Xml String 
/// </summary> 
/// <param name="ds">A DataSet</param> 
/// <param name="isDotNet">If true, optimize for .Net client, if false for Legacy(Java)</param> 
/// <param name="includeSchema">If true,include the Schema in the Xml</param> 
/// <returns>The dataset serialized as Xml</returns> 
public static string GetXml(this DataSet ds, bool isDotNet, bool includeSchema)
{
    var swriter = new StringWriter();
    using (var xwriter = new XmlTextWriter(swriter))
    {
        xwriter.Formatting = Formatting.Indented;
        if (includeSchema)
        {
            ds.WriteXml(xwriter, XmlWriteMode.WriteSchema);
        }
        else
        {
            ds.WriteXml(xwriter, XmlWriteMode.IgnoreSchema);
        }
    }


    if (isDotNet)
    {
        return swriter.ToString();
    }

    // remove the Microsoft tags 
    XDocument doc = XDocument.Parse(

                   swriter.ToString(), LoadOptions.PreserveWhitespace);


    XNamespace namespaceToRemove =

    XNamespace.Get("urn:schemas-microsoft-com:xml-msdata");


    doc.Descendants().Attributes().Where(

         a => a.Name.Namespace == namespaceToRemove).Remove();


    doc.WriteTo(new XmlTextWriter(swriter = new StringWriter()));


    return swriter.ToString();
}

What is the result? With isDotNet=true, we get the code below (with the offending items being struck thru):

   

<NewDataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="
http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Table1">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="LastName" type="xs:string" minOccurs="0" />
                <xs:element name="WT" msdata:DataType="System.DateTimeOffset" type="xs:anyType" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <Table1>
    <LastName>Lassesen</LastName>
  </Table1>
</NewDataSet>

 

With isDotNet=false, we get:

 

<?xml version="1.0" encoding="utf-16"?><NewDataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="
http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Table1">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="LastName" type="xs:string" minOccurs="0" />
                <xs:element name="WT" type="xs:anyType" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <Table1>
    <LastName>Lassesen</LastName>
  </Table1>
</NewDataSet>

Summary

This means that instead of having one contract that is .Net specific:

 

[OperationContract] 
DataSet GetAccountSummary(string user);      

We could use the following which performs as well for .Net and simplifies use from Java or other Legacy issues.

[OperationContract]  
String GetAccountSummary(string user, bool isDotNet, bool includeSchema);

Comments

Popular posts from this blog

Yet once more into the breech (of altered programming logic)

Simple WP7 Mango App for Background Tasks, Toast, and Tiles: Code Explanation

How to convert SVG data to a Png Image file Using InkScape