views:

664

answers:

4

Current Implementation

Sql Server 2005 Database with a table called messages with a column called MessageXml of type xml.

C# Library project with a Linq to Sql class that generates a class called Message with a field called MessageXml of type XElement.

WCF Webservice that exposes a MessagePayload class with a property called MessageXml of type XElement.

The webservice doesn't serve up my Message class created by Linq to Sql. I use a light weight object as a go between.

Question

Is XElement really the type I want to be using in my WCF Service or is there a better type. The xml that is intended to be passed into the service should be a full doc. Also, I'm having a bit of trouble loading xml documents as an XElement. I think that I should expose a full xml document type in the light weight class for the service but I'm a bit confused on the differences between XDocument and XmlDocument.

On top of that, I can't expose the WCF Message class with a property of XDocument type because it contains a property of XDeclaration type that can't be serialized.

If I use XmlDocument than I have to do this weird conversion of xml types in my translation between the Linq class and the lightweight class.

 XmlDocument doc = new XmlDocument();
 doc.LoadXml(message.MessageXml.ToString());

 MessageEnvelope retVal = new MessageEnvelope()
 {
      MessageXml = doc,
 };

XmlDocument seems like the right one and I know I'll have to do some translation but want to get as close to appropriate as possible.

A: 

Use whatever type you need to serialize the class (String has always worked well for me) and then do conversions when necessary on server or client side to maintain the integrity of the document. You can build an XDocument out of one or more XElements also, so I would go with XElement.

Worst case, you can even override the serialization behavior of your class (not too terrible if you're good with reflection).

XmlDocument is the old, non Linq document. They're the same concept implemented in different classes.

marr75
-1: XML is not the same thing as string. Do not use it to represent XML.
John Saunders
I'm aware, that's why you have to validate it before and after converting for serialization...
marr75
+1  A: 

You can use either XElement or XmlElement:

public XmlElement GetXmlElement()
{
    var doc = new XmlDocument();
    doc.Load(PREFIX + @"Enumerations.wsdl");

    return doc.DocumentElement;
}

public XElement GetXElement()
{
    var doc = XDocument.Load(PREFIX + @"Enumerations.wsdl");
    return doc.Root;
}

You do not want either XDocument nor XmlDocument. Remember that whatever you return will be in the middle of an XML document containing the SOAP envelope. You can't have a document inside a document, so what you want is an element.

John Saunders
A: 

In general, XDocument and XElememnt are preferable to XmlDocument and XmlElement in terms of performance.

However, I would suggest to use string to send an XML document via WCF service for the following reasons:

  1. Interoperability
    • Clients are not tied to specific .NET framework version (Client can choose to use XDocument or XmlDocument. Even Java-based clients can be supported as long as WCF services are configured in such way).
  2. Handling Xml declaration properly if the original XML document contains it.

Note: Please make sure to adjust the configuration appropriately to support a large xml document. For example, basicHttpBinding's default max message size is 64KB.

Chansik Im
-1: Total nonsense. Just send an XmlElement. What's wrong with that? It just sends the XML.
John Saunders
+1  A: 

John Saunders is on the money here. To elaborate slightly, if you look at the WSDL that is generated when you return either an XmlElement or an XElement, you'll see something like this:

<xs:complexType>
  <xs:sequence>
    <xs:any minOccurs="0" processContents="lax"/>
  </xs:sequence>
</xs:complexType>

That's it. It basically means any XML can go here. It also means that, contrary to Chansik's suggestion, it does not bind the return type to a .NET specific type.

So yeah, you don't need to use a string.

Gavin Schultz-Ohkubo