Rant: Don't return XML in string variables!
I have probably seen a half a dozen article submissions to MSDN in the last year with authors who do the following:
// Bad Bad Bad
[WebMethod]
public string MyLameWebMethod()
{
XmlDocument dom = new XmlDocument();
// load some XML ...
return dom.OuterXml;
}
and then on the client side they do this:
// Bad bad bad
localhost.Service1 proxy = new localhost.Service1();
XmlDocument dom = new XmlDocument();
dom.LoadXml(proxy.MyLameWebMethod());
!!!DON'T DO THIS!!!
Try this instead:
// Better
[WebMethod]
public XmlDocument MyBetterWebMethod()
{
XmlDocument dom = new XmlDocument();
// load some XML ...
return dom;
}
Then the client will look like this:
// Better
localhost.Service1 proxy = new localhost.Service1();
XmlNode xml = proxy.MyBetterWebMethod();
Now you are avoiding an added level of serialization/deserialization. This applies to valid XML only!! Non-wellformed HTML should be passed as a string that is HTML encoded.
I will say that I have sympathy about this sort of thing and the tools often aren't much help, but if I can help it, MSDN will never have an article encouraging users to pass XML as an encoded string to/from a Web service.
By the way, I've been trying to think of a scenario where returning XML as a string to/from a Web service might make sense...without luck. If you have one, I would like to hear about it. I think it is safe to say that for the vast majority of situations, returning XML as an encoded string is not a good practice.
-Matt
Comments
- Anonymous
May 12, 2004
What happens when you're accessing the service with another technology, like PHP or ASP? (I really don't know this...) I've created a few XML-RPC based web services that return xml documents as strings, which is exactly what an xml document is... If a PHP client, for example, is accessing a .NET webservice with a return type of XmlDocument, can it easily process it? - Anonymous
May 12, 2004
AMEN (to the post, not the comment) - Anonymous
May 12, 2004
Returning XmlDocument from a web server serializes itself to xml, so if you are accessing the web server from a non-.Net environment it still works OK. What you save is the XmlDocument->String and String->XmlDocument conversions. - Anonymous
May 12, 2004
As for interop, As David points out, XmlDocument basically just sticks XML in the body of the envelope so it should definitely be x-platform goodness.
And by the way, I've done this too ... back in the early SOAP Toolkit days when a change in toolkit versions changed the wire protocol and we had to live with it until the next revision of our app. But we fixed it as soon as we could - and appropriately repented. - Anonymous
May 12, 2004
So is this a question of changing the type of object that gets wrapped around the bytes? It sounds like the bytes don't change but that perhaps they get copied. Is this what the rant is about? - Anonymous
May 12, 2004
The bytes do change. Sending the string sends this:
<envelope>
<body>
<a><b>blah</b><c>blah</c></a>
</body>
</envelope>
Sending the XML sends this:
<envelope>
<body>
<a>
<b>blah</b>
<c>blah</c>
</a>
</body>
</envelope>
(I hope this formats okay in my comments.)
-Matt - Anonymous
May 12, 2004
Well, it is somewhat cleaner (and safer), but it's not that we dispensed with serialization altogether... - Anonymous
May 12, 2004
Hi Matt,
I have been working with the new MS CRM and note that it sends XML between the client and server as strings, which I also found frustrating! - Anonymous
May 12, 2004
The office team is defined interfaces with stings containing XML for their research and translation web services as well. It would help if service interfaces published by Microsoft Web would follow best practices.
I am sure many developers new to Web services will follow practices the see in interfaces published by the big guys.
Christoph - Anonymous
May 12, 2004
All you need to do now is make the same fix in your products!, seriously go checkout the SOAP interface for MS-CRM, it blows chunks. - Anonymous
May 12, 2004
Take Outs for 12 May 2004 - Anonymous
May 12, 2004
Does this also apply to SignedXML objects? Can they be returned directly as well? - Anonymous
May 13, 2004
What if you don't want the overhead of creating the DOM on the server in the 1st place?
If you look @ a typical "read" stack it's:
client request => server => some object(s) => database (or data store) request
(unwinding stack)
data results => some data format => soap serializer => client
Why would I want to take on the server overhead of "some data format" being a DOM?
If I want to process the data from a database before it's sent back to the client, I probably want to process it in the form of a dataset or datareader -- neither returns a DOM –
So are you suggesting the overhead of creating a DOM so it can be returned in native XML is worth the server overhead? - Anonymous
May 13, 2004
The comment has been removed - Anonymous
May 14, 2004
What about Classic ASP object incompatability?
For example, if I have an "Account" object on my .NET side of things and decide make that object a return value in my .NET Web Service, will ASP know how to handle the object? I don't think so.
In order to keep my .NET apps object-oriented, we just serialize our objects into Xml like this:
<I>
Account asq = new Account()
StringWriter swQuery = new StringWriter();
XmlSerializer xsQuery = new XmlSerializer(typeof(Account));
xsQuery.Serialize(swQuery, asq);
return swQuery.ToString();
</I>
Is there a better way to do this in order to avoid returning a string of Xml? I know the overhead is enormous and would love to know the answer. Thanks!
Shaun McDonnell
Citigroup - Anonymous
May 26, 2004
What about loose coupling?
Bundling various parameters into an primitive type like a string (like the MSCRM APIs do)provides a simple way to acheive loose coupling does it not?
Tim - Anonymous
May 31, 2004
It's not necessary at all to load a DOM to return well-formed XML from a webservice. And as the DOM will be the "legacy-deprecated-dying" API in .NET, it only makes sense to move to XmlReader and XPathNavigator-based processing.
Here's how you can return well-formed XML without wasting server resources in loading DOMs you don't need: http://weblogs.asp.net/cazzu/archive/2004/05/31/144922.aspx (How to return well-formed XML from WebServices without the DOM: from XmlReader and XPathNavigator) - Anonymous
July 11, 2004
Why go through the trouble of instantiating an XmlDocument, XmlReader or even an XPathNavigator if you already have the XML as a string to begin with and have no interest in interacting with it in that context?
Let's take Oracle's (9i+) xmltype for example. It holds and returns XML as CLOB, which you normally cast to string. Assuming I simply want to forward this record from Oracle to my client, without interacting with it at all, why waste time and space over deserialization?
In the client I can simply (assuming client is the browser in this sample and 'result' is callService's callback argument):
var xmlDoc=document.createElement("xml");
xmlDoc.loadXML(result.value); - Anonymous
April 06, 2006
The comment has been removed