Let's say I have a WCF contract such as
[ServiceContract]
public interface IContract
{
[OperationContract]
[WebInvoke(Method="POST", RequestFormat=WebMessageFormat.Xml, BodyStyle=WebMessageBodyStyle.Wrapped)]
string ComplexPost(string name, ComplexType data);
}
And a data contract:
[DataContract(Name="ComplexType", Namespace="")] // don't know if those atts are req'd or not but saw them in another example
public class ComplexType
{
public string StringData { get; set; }
public int IntData { get; set; }
public DateTime DateValue { get; set; }
}
I know that the request has to be wrapped in order to have more than one input parameter, obviously you cannot have an XML document with more than one root.
The problem is, the documentation is really sparse about what you have to wrap it WITH.
The goal is not to consume this with WCF, it needs to be accessible to clients as a generic XML web service. They may not have any knowledge of WCF or even use .NET.
Obviously I can tell from the exceptions I've been receiving that it is expecting an Element with name ComplexPost (the same as the method name) with namespace http://tempuri.org/ because I haven't specified anything else yet, so I know I need this:
<ComplexPost xmlns="http://tempuri.org/">
...what exactly?
</ComplexPost>
The goal is not specifically to adhere to REST principles. I'm not looking for answers that embed some of the parameters in the UriTemplate leaving only one complex object, making Bare work. I'm looking for a generalized solution to including all of the data within the POST body.
Found with Fiddler
Here is approximately what the result would be, based on what I found using Fiddler.
<ComplexPost xmlns="http://tempuri.org/">
<name>Value of name parameter</name>
<data xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<StringData>The StringData property value</StringData>
<IntData>10</IntData>
<DateValue>2009-07-07T15:38:39.7738012-05:00</DateValue>
</data>
<ComplexPost>
So the wrapper element is the method name, with the XML namespace that's specified on your ServiceContract, or the temppuri.org if not.
Each parameter becomes, in order, a child element, with base types serialized very easily into string representations.
I did my tests with nullable values, including a nullable DateTime. Apparently the declaration that xmlns:i="http://www.w3.org/2001/XMLSchema-instance" must occur before it's needed, and then for a null value, it's a closed element with i:nil="true", for example
<NullableDateProperty i:nil="true" />
It was also very easy for a DataContract object to have child complex types, or even a list of complex objects.
....
<ChildObjectPropertyName>
<PropertyOfChildObject>value</PropertyOfChildObject>
...
</ChildObjectPropertyName>
<ListProperty>
<ObjectType>
<ObjectProperty>value</ObjectProperty>
....
</ObjectType>
...
</ListProperty>
This may not be complete, but the lesson is definitely get a WCF client working and then examine the exchanges with Fiddler. Thank you Cheeso!