Interface inconsistencies between ASMX Web services and System.Xml V1 and V2
I've been wondering why the class designs between ASMX Web services and System.Xml seem to be so disconnected. It seems like the ASMX team really doesn't get to keep up with the way things are done in System.Xml.
Take the feature that you can return an XmlDocument object from a Web serivce for example. It's great that you can fully control the response of a [WebMethod] ... if just the XmlDocument was the prescribed way of working with XML in the .NET Framework.
The XmlDocument really only works well if you write the code to modify the document's content. The classes in the .NET Framework that return XML results, like the XslTransform or an ADO.NET SqlCommand work with XmlWriters and XmlReaders. If you wanted to write the XML results from a SQL Server 2000 query that you obtained by calling ExecuteXmlReader to the response of a [WebMethod] you would first have to load the contents of the reader into an XmlDocument object:
[WebMethod]
[ … more serialization attributes ]
public XmlDocument GetData( … parameters )
{
XmlDocument doc = new XmlDocument();
SqlCommand cmd = new SqlCommand();
// populate SqlCommand
// …
XmlReader reader = cmd.ExecuteXmlReader();
// now load the XML into an XmlDocument
doc.Load( reader );
return doc;
}
It seems to me that it shouldn’t be necessary to parse the content of the XmlReader and construct a DOM just in order to stream it back to the client. Wouldn’t Web services that employ SQL Server XML features and XSLT perform better without the extra, unnecessary document parsing step?
Unfortunately, the new XslCommand and the XQueryCommand follow the API pattern of the XslTransform and it’s not possible to generate a Web service response in one single step without the DOM parsing. I would expect that especially with large XML documents, parsing the XML imposes a significant amount of processing and resource consumption on the server that could be avoided. With the API pattern of the XslTransform, you can write to an XmlDocument with Chris Lovett’s XmlNodeWriter from GotDotNet, but that’s going outside the .NET Framework and it's probably not well known to the average developer:
[WebMethod]
[ … more serialization attributes ]
public XmlDocument GetDataFromTransformation( … parameters )
{
XmlDocument doc = new XmlDocument();
XslTransform trafo = new XslTransform();
XmlNodeWriter writer = new XmlNodeWriter( doc );
// load XslTransform
// …
trafo.Transform( sourceXml, (XsltArgumentList) null, writer, (XmlResolver) null );
return doc;
}
The approach with the XmlNodeWriter works OK, except that there have been some recommendation in the past to favor other options. I would much rather see a lighter weight XmlWriter than the XmlNodeWriter and the underlying XmlDocument if all I want to do is to stream an XML back to a Web service client.
In Whidbey things unfortunately don't change for the better. You can now create an XmlWriter to write the results of an XslCommand or an XQueryCommand to an XPath(Editable)Document, but that doesn’t derive from XmlNode, so yet again, you need to go not follow the guidance that the XPathDocument is the preferred XML API to work with and write the results to an XmlDocument (still via the XmlNodeWriter) or, if you need to use XPathDocument for other reasons, you have to add an extra (potentially expensive) step transferring the XML from the XPathDocument to an XmlDocument.
With Whidbey I was hoping to see some of the following improvements:
- returning an XmlReader from a [WebMethod] should write the contents of the XmlReader directly to the response body, just like it works with the XmlNode derived classes today to integrate better with SqlCommand and other APIs that return XML through an XmlReader:
[WebMethod]
[ … more XmlSerialization attributes ]
public XmlReader GetData()
{
SqlCommand cmd = new SqlCommand();
// populate the command
// now return the XML results
return cmd.ExecuteXmlReader();
} - Allow a [WebMethod] to return an XPathDocument avoid any unnecessary document serialization and parsing steps, to leverage any improvements of the new XPathNavigator and to enforce the message that XPathDocument objects are the preferred approach to pass around XML data in the .NET Framework
- Make available an XmlWriter (possibly one that filters PIs to stay SOAP compliant) from within a WebMethod that one can pass directly to an XQueryCommand where the XML written to the XmlWriter is directly transferred to the response of the [WebMethod]